-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
module: implement the "module-sync" exports condition #54648
Conversation
Review requested:
|
cc @guybedford |
ee9bdea
to
89c1e4f
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #54648 +/- ##
==========================================
+ Coverage 88.03% 88.24% +0.21%
==========================================
Files 652 652
Lines 183797 183886 +89
Branches 35863 35853 -10
==========================================
+ Hits 161804 162279 +475
+ Misses 15242 14896 -346
+ Partials 6751 6711 -40
|
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.
Should we document the subtle difference between "module" and "import" at https://nodejs.org/api/packages.html#conditional-exports?
There is a huge section in |
I did a bit more testing with other bundlers, and put the results in https://github.com/joyeecheung/test-module-condition In summary it allows running unbundled code that produce the same output as bundled produced by webpack and esbuild. Rollup has a difference in that it doesn't respect insertion-order priorities, but I guess that's probably a problem that can apply to any other exports conditions. |
It would be great if the docs mentioned that |
This could be problematic where packages ship build explicitly for bundlers, but not for node. Just as an example: there is a good bunch of packages that use You can find some explanation on this in https://github.com/graphql/graphq where we are exploring to ship CommonJS for I do not think that this exact bundling schema would be impacted negatively (as this PR would also get around the dual package hazard), but I imagine there might be more reasons to have something "not for node" in |
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.
Good point @phryneas !
I confirm that this PR breaks require('xstate')
under --experimental-require-module
.
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.
Meant to block.
How did you confirm that this breaks According to graphql/graphql-js#4062, take the base path for example: ".": {
"module": "./dist/xstate.esm.js", // Original ESM version
"import": "./dist/xstate.cjs.mjs", // Re-exports of the transpiled CJS
"default": "./dist/xstate.cjs.js" // Transpiled ESM version
}, Before this PR, ".": {
"require-module": "./dist/xstate.esm.js", // Original ESM version
"module": "./dist/xstate.esm.js", // Original ESM version
"import": "./dist/xstate.cjs.mjs", // Re-exports of the transpiled CJS
"default": "./dist/xstate.cjs.js" // Transpiled ESM version
}, This further bloating is what we are trying to avoid by implementing |
Do you have an example? Considering bundlers have been using this as an optimization for bundling code that does |
I'm no longer with my computer but my reproduction ended up in a throw (while v22 with the flag doesn't throw). |
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 src: * mark node `--run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: TODO
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 src: * mark node `--run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 src: * mark node `--run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Adding don't land labels for release branches, because this as a feature detection thing must be released together with #55085 which require manual backports. |
Actually this commit was landed behind the CLI flag, so the code could be released first, though we should mention in the release notes that it's only enabled when |
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 src: * mark node `--run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 * (SEMVER-MINOR) add `process.features.typescript` (Aviv Keller) #54295 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 * (SEMVER-MINOR) add `process.features.typescript` (Aviv Keller) #54295 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 * (SEMVER-MINOR) add `process.features.typescript` (Aviv Keller) #54295 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) #55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) #54159 doc: * add abmusse to collaborators (Abdirahim Musse) #55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) #54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) #54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) #54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) #54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) #54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) #54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) #55241 * (SEMVER-MINOR) add `process.features.typescript` (Aviv Keller) #54295 src: * mark `node --run` as stable (Yagiz Nizipli) #53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) #55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) #54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) #53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) #55234 PR-URL: #55343
Refs: nodejs/admin#917 Refs: nodejs/package-examples#1 Refs: #54648 PR-URL: #55444 Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
Refs: nodejs/admin#917 Refs: nodejs/package-examples#1 Refs: #54648 PR-URL: #55444 Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
This patch implements a "module-sync" exports condition for packages to supply a sycnrhonous ES module to the Node.js module loader, no matter it's being required or imported. This is similar to the "module" condition that bundlers have been using to support `require(esm)` in Node.js, and allows dual-package authors to opt into ESM-first only newer versions of Node.js that supports require(esm) while avoiding the dual-package hazard. ```json { "type": "module", "exports": { "node": { // On new version of Node.js, both require() and import get // the ESM version "module-sync": "./index.js", // On older version of Node.js, where "module" and // require(esm) are not supported, use the transpiled CJS version // to avoid dual-package hazard. Library authors can decide // to drop support for older versions of Node.js when they think // it's time. "default": "./dist/index.cjs" }, // On any other environment, use the ESM version. "default": "./index.js" } } ``` We end up implementing a condition with a different name instead of reusing "module", because existing code in the ecosystem using the "module" condition sometimes also expect the module resolution for these ESM files to work in CJS style, which is supported by bundlers, but the native Node.js loader has intentionally made ESM resolution different from CJS resolution (e.g. forbidding `import './noext'` or `import './directory'`), so it would be semver-major to implement a `"module"` condition without implementing the forbidden ESM resolution rules. For now, this just implments a new condition as semver-minor so it can be backported to older LTS. Refs: https://webpack.js.org/guides/package-exports/#target-environment-independent-packages PR-URL: nodejs#54648 Fixes: nodejs#52173 Refs: https://github.com/joyeecheung/test-module-condition Refs: nodejs#52697 Reviewed-By: Jacob Smith <[email protected]> Reviewed-By: Jan Krems <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]>
Notable changes: crypto: * (SEMVER-MINOR) add `KeyObject.prototype.toCryptoKey` (Filip Skokan) nodejs#55262 * (SEMVER-MINOR) add Date fields for `validTo` and `validFrom` (Andrew Moon) nodejs#54159 doc: * add abmusse to collaborators (Abdirahim Musse) nodejs#55086 http2: * (SEMVER-MINOR) expose `nghttp2_option_set_stream_reset_rate_limit` as an option (Maël Nison) nodejs#54875 lib: * (SEMVER-MINOR) propagate aborted state to dependent signals before firing events (jazelly) nodejs#54826 module: * (SEMVER-MINOR) support loading entrypoint as url (RedYetiDev) nodejs#54933 * (SEMVER-MINOR) implement the `"module-sync"` exports condition (Joyee Cheung) nodejs#54648 * (SEMVER-MINOR) implement `flushCompileCache()` (Joyee Cheung) nodejs#54971 * (SEMVER-MINOR) throw when invalid argument is passed to `enableCompileCache()` (Joyee Cheung) nodejs#54971 * (SEMVER-MINOR) write compile cache to temporary file and then rename it (Joyee Cheung) nodejs#54971 process: * (SEMVER-MINOR) add `process.features.require_module` (Joyee Cheung) nodejs#55241 * (SEMVER-MINOR) add `process.features.typescript` (Aviv Keller) nodejs#54295 src: * mark `node --run` as stable (Yagiz Nizipli) nodejs#53763 test_runner: * (SEMVER-MINOR) support custom arguments in `run()` (Aviv Keller) nodejs#55126 * (SEMVER-MINOR) add `'test:summary'` event (Colin Ihrig) nodejs#54851 * (SEMVER-MINOR) add support for coverage via `run()` (Chemi Atlow) nodejs#53937 worker: * (SEMVER-MINOR) add `markAsUncloneable` api (Jason Zhang) nodejs#55234 PR-URL: nodejs#55343
Refs: nodejs/admin#917 Refs: nodejs/package-examples#1 Refs: nodejs#54648 PR-URL: nodejs#55444 Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
This patch implements a "module-sync" exports condition that's enabled when
require(esm)
is enabled, so that packages can supply a sycnrhonous ES module to the Node.js module loader, no matter it's being required or imported. (Currentlyrequire(esm)
is still under--experimental-require-module
on v22. It will be unflagged in the upcoming v23 release first. We expect to also unflagrequire(esm
) in v22 after testing in 23).This is similar to the "module" condition that bundlers have been using to support
require(esm)
in Node.js, and allows dual-package authors to opt into ESM-first only on newer versions of Node.js that supports require(esm) to avoid the dual-package hazard.Or if the package is only meant to be run on Node.js and wants to fallback to CJS on older versions that don't have
require(esm)
For package authors: this only serves as a feature-detection mechanism for packages that wish to support both CJS and ESM users during the period when some active Node.js LTS versions support
require(esm)
while some older ones don't. When all active Node.js LTS lines supportrequire(esm)
, packages can simplify their distributions by bumping the major version, dropping their CJS exports, and removing themodule-sync
exports condition (with onlymain
ordefault
targetting the ESM exports). If the package needs to support both bundlers and being run unbundled on Node.js during the transition period, use bothmodule-sync
andmodule
and point them to the same ESM file. If the package already doesn't want to support older versions of Node.js that doesn't supportrequire(esm)
, don't use this export condition.For bundlers/tools: they should avoid implementing this stop-gap condition. Most existing bundlers implement the de-facto bundler standard
module
exports condition, and that should be enough to support users who want to bundle ESM from CJS consumers. Users who want both bundlers and Node.js to recognize the ESM exports can use bothmodule
/module-sync
conditions during the transition period, and can dropmodule-sync
+module
when they no longer need to support older versions of Node.js. If tools do want to support this condition, it's recommended to make the resolution rules in the graph pointed by this condition match the Node.js native ESM rules to avoid divergence.We end up implementing a condition with a different name instead of reusing "module", because existing code in the ecosystem using the "module" condition sometimes also expect the module resolution for these ESM files to work in CJS style, which is supported by bundlers, but the native Node.js loader has intentionally made ESM resolution different from CJS resolution (e.g. forbidding
import './noext'
orimport './directory'
), so it would be semver-major to implement a"module"
condition without implementing the forbidden ESM resolution rules. For now, this just implments a new condition as semver-minor so it can be backported to older LTS.The tests added in this patch match the output of using the
module
condition from webpack and esbuild bundles, will a small difference in rollup outputs. See https://github.com/joyeecheung/test-module-conditionFixes: #52173
Refs: https://github.com/joyeecheung/test-module-condition
Refs: #52697
Refs: https://webpack.js.org/guides/package-exports/#target-environment-independent-packages