-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
esm: Implement esm mode flag #18392
esm: Implement esm mode flag #18392
Conversation
862219d
to
cfb5d70
Compare
I have a writeup from conversations in form of a pseudo design document. |
@@ -39,14 +43,22 @@ function search(target, base) { | |||
} | |||
} | |||
|
|||
const extensionFormatMap = { | |||
const extensionFormatStd = { | |||
__proto__: null, | |||
'.mjs': 'esm', | |||
'.json': 'json', | |||
'.node': 'addon', | |||
'.js': 'commonjs' | |||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☝️ still not a fan of using short forms for most names but not commonjs
. We have ECMAScript module -> esm
, JavaScript Object Notation -> json
, CommonJS -> should be cjs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh I have no idea why I made this change and if it had been brought up before my PR landed I would have most likely changed it back, kinda feelin' guilty about this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Babel now allows specifying "cjs"
, in addition to "commonjs"
, as their module mode because folks kept reaching for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also like to see it changed back to "cjs"
src/node.cc
Outdated
} | ||
config_main_mode = arg + 7; | ||
if (config_main_mode != "esm") { | ||
fprintf(stderr, "%s: \"%s\" is not a valid module mode\n", argv[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👆 I'm not a pro in c++ but is config_main_mode = arg + 7
a number result? If so would it never match "esm"
in the if
statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config_main_mode
is a std::string
, so comparing using the operator works. :) I assume arg + 7
is the pointer to the null-terminated string starting 7 bytes from the pointer arg
, skipping the --mode=
(7 bytes). But it's not the most straight-forward to follow.
src/node.cc
Outdated
args_consumed += 1; | ||
config_main_mode = main_mode; | ||
if (config_main_mode != "esm") { | ||
fprintf(stderr, "%s: \"%s\" is not a valid module mode\n", argv[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👆 If there is two modes documented shouldn't both modes be allowed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does seem like you should be able to set "commonjs" or "cjs" as the mode
What about extensionless bin files that CLI's often use? Update There's a mention in the writeup about The writeup mentions a gotcha with |
Thanks a lot for your work that might save us from a new javascript extension. I know this is an entirely minor detail to consider right now, but I would only argue using shorthand, |
@jdalton |
What about tackling it in the shebang of the bin file like #!/usr/bin/env node --mode esm |
@jdalton punted and as describe in the design doc "bin" files can have extensions even if the command does not which is the common case for using command line wrappers, feel free to PR the |
The bin file is opting in to esm with the |
@jdalton |
Having it specified in the shebang is a nice descriptive and natural way to tackle extensionless bins. |
@jdalton PR up the |
Naw. It doesn't have to be |
@jdalton One problem with putting arguments into the shebang is that it's not super portable. :( https://unix.stackexchange.com/questions/63979/shebang-line-with-usr-bin-env-command-argument-fails-on-linux P.S.: Shipping something like a |
Or we could try it in this PR, write tests, and see if issues are had. |
Not sure I follow - this isn't hard to verify. The following:
Works on OSX but won't run on (all) Linux (the same without
|
Many times ideas are shot down with a quick SO post without actually seeing if, in the given scenario, it is doable or an issue is able to be worked around. Pinging @ceejbot and @chrisdickinson who had this in their npm proposal, though it was unimplemented (wondering if they ran into similar issues or if they've thought of anything to workaround the gotcha).
That may be it 😋. I never considered something like that. Kinda neat! |
Question: with such a proposal, how would I write a "dual mode package", one which works whether we If we go with this proposal, all library developers that want to migrate to the esm model will need to fork their modules. So we will have Given that we're going to live in dual-mode world for a long time, I believe this is not viable. |
@giltayar You would still use the |
@BridgeAR i re-opened nodejs/modules#42 which should be good enough for now i suppose |
d6d6913
to
f61aa91
Compare
303d5a8
to
459ec5c
Compare
This implements a package.json "mode": "esm" module boundary. When loading a module from a package with this esm mode, ".js" files are loaded as es modules. In addition package.json caching is implemented in the module lookup process, and package.json boundaries are only checked when necessary.
0df17e9
to
9b1de85
Compare
@devsnek nodejs/modules#42 is closed, any other reference? |
@MylesBorins maybe has something, I'm not 100% sure |
Is this superseded by #26745? |
Yes. |
This provides a
mode: "esm"
flag for package.json files which will treat ".js" files as ES modules within a given package boundary.The package boundary of a package.json file is deemed to be all modules in that folder and subfolder until the next nested package.json file.
The plan is to add a top-level
--mode
flag to this, roughly matching the npm proposal, but restricted to the current package boundary. This work is currently at https://github.com/guybedford/node/tree/package-top-mode.The mode effectively marks a directory as an "esm mode" directory, where all ".js" files in that directory are loaded as ES modules, unless they are located in a subfolder that contains a package.json without an "esm mode", which results in reverting to the transparent interop of treating ".js" as CommonJS.
In addition this PR enables caching of package.json lookups within the ES module resolver.
Presentation: https://docs.google.com/presentation/d/1xK1ana_TIxfAHX33CYVHFnJsV0If_YirLtRBBga9cv0/edit#slide=id.p
This work is based on the following prior proposal work:
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
esmodules