-
Notifications
You must be signed in to change notification settings - Fork 43
Undocumented behavior of package type searches within node_modules #436
Comments
My assumption is that it's to avoid breaking packages or symlinks inside the I don't think it's something that can happen with regular |
Example of implications as promised in nodejs/node#30514 (comment) This occurs in projects with the following directory structure, which resembles mine. The hierarchy enables access to free bare specifier imports, which is a technique popularized by @Rich-Harris in his wildly popular tweet about it.
To enable ESM in projects with this current structure post-unflagging, it should be as simple as adding a |
@DerekNonGeneric could |
/to @MylesBorins
If I understand correctly, that would also require a
"name": "lorem",
"exports": {
".": [
"./index.mjs"
]
}
import * as constants from './src/node_modules/shared/constants.js';
export default constants;
import lorem from 'lorem'; Run the following command. node --experimental-resolve-self x.mjs Error:
|
What do you mean by, package.json is not recognized in node_modules? |
@ljharb, the ESM resolver bails before it can read |
@DerekNonGeneric that's not how type module is supposed to work; only the closest package.json can set it. so |
Albeit rare, this is precisely the use-case that currently lacks support. I was able to solve this issue by implementing a modified version of I was informed that the "node" resolution mode will more likely be removed than become the default. In light of this information, and the loader solution described above, a PR to Node core for additional support of this directory structure may be unnecessary. I don't foresee myself continuing to use this structure, which is a "hack" after all. If I uncovered a bug in my above attempt at the suggestion, I will try to create a reduction and file a separate issue about it. As such, the highest-priority item remaining in this issue would be considering illuminating |
If I remember correctly, the special handling of As far as replicating the behavior of that popular tweet, // package.json
"name": "foo",
"type": "module",
"exports": {
".": "package-main-entry-point.js",
"./utils/": "./src/utils/" // package-main-entry-point.js
import { shuffle } from 'foo/utils/shuffle.js'; I haven’t tested the above code, but if I understand correctly this is how |
/to @GeoffreyBooth Thanks. Unfortunately, the self-reference solution would require refactoring the codebase. At the very least, all of the specifiers would need to be updated. Adding the specifier-path mappings would also be another chore (probably needs to be autogenerated by a separate tool). |
Then just add I think the |
To get this issue closed, I believe the consensus was to put the algorithms more front-and-center. I think to accomplish this, at the very least, we should keep these algorithms' details expanded. On the left you can see how it looks by default, on the right is how it looks expanded (after tapping it). https://nodejs.org/api/esm.html#esm_resolver_algorithm There is prior art on this with the All Together... section of the Modules API docs. |
/to @GeoffreyBooth This relates to UX and user journey. Is there anyone else who you think has an opinion on this before I seek input via a PR? (I would be proposing either keeping the accordion expanded or taking these algorithms out of an accordion). |
I'm not sure why the algorithm needs to be expanded. It feels like information for a very select audience, namely developers implementing tools that work closely with Node's resolution. The general audience shouldn't need to know the detailed algorithm. |
As suggested, I've opened an issue for tracking the undocumented behavior of package type searches performed by implementations of the
READ_PACKAGE_SCOPE
algorithm occurring withinnode_modules
directories. I've moved my preliminary findings from the code review to this thread to allow for more focused discussions to take place.Initial observations (non-exhaustive)
From the original thread:
node_modules
.package.json
with a"type": "module"
field in anode_modules
directory doesn't result in.js
(or even.mjs
) files as being interpreted to be in ESM context.package.json
that aren't switching context. Files within subdirectories of thenode_modules
that contains thispackage.json
are similarly unaffected.This behavior doesn't seem to be documented anywhere, so I'm not sure if is intentional. I'll keep looking and update this issue with any other findings.
Aside from local manual testing, further details can be gleaned from:
The following step1 of the
READ_PACKAGE_SCOPE
specification.The following code block2 of the internal implementation.
Conclusion
If this behavior is by design, the Package Scope and File Extensions section should probably mention it. I'm curious as to what the rationale is behind
node_modules
being a DMZ (de-modularized zone). 😄Footnotes
1: This is step 2.1. in the pseudocode for the
READ_PACKAGE_SCOPE(url)
function located in the Resolver Algorithm section of ECMAScript Modules document.2: This block starts on line 683 of
module_wrap.cc
in the internal C++ implementation.Implications of node_modules being a DMZ
node_modules
./src/node_modules
directory structure pattern may be forced to refactor.The text was updated successfully, but these errors were encountered: