You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Sep 2, 2023. It is now read-only.
Repository navigation
This repository was archived by the owner on Sep 2, 2023. It is now read-only.
Suppose I have a project where I'm using the CommonJS default, and I install a module with "type": "module" in its package.json from npm. Is the current plan that I'll be able to use require to load exports from that ESM module? (Or similarly, if I just try to require an .mjs file...)
(To be clear: This is purely a question, not a veiled suggestion or criticism. Here's an unveiled comment, though: Thank you for the updated ESM stuff!)
It doesn't work with the v12 nightlies, but hey, it's nightlies, stuff is in flux. :-)
(node:20699) ExperimentalWarning: The ESM module loader is experimental.
/home/blah/blah/node_modules/foo/index.js:1
export function foo(...args) {
^^^^^^
SyntaxError: Unexpected token export
at Module._compile (internal/modules/cjs/loader.js:768:23)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:835:10)
at Module.load (internal/modules/cjs/loader.js:693:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:731:19)
at require (internal/modules/cjs/helpers.js:14:16)
at Object. (/home/tjc/temp/esmcheck/index.js:1:17)
at Module._compile (internal/modules/cjs/loader.js:824:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:835:10)
at Module.load (internal/modules/cjs/loader.js:693:32)
There are currently no plans on the road map to support requiring esm
Some members of the team are exploring the possibility but I am personally
skeptical of the ability to do so
The biggest challenge is moving from and async loader to a sync loader and
back or sync to async to sync. Something we have referred to as zebra
striping.
It introduces all sorts of problems including deadlock and cache
duplication.
On Sat, Apr 6, 2019, 12:07 PM T.J. Crowder ***@***.***> wrote:
I'm embarrassed to say that I can't quite tell from the Plan for New
Modules Implementation
<https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md>
.
Suppose I have a project where I'm using the CommonJS default, and I
install a module with "type": "module" in its package.json from npm. Is
the current plan that I'll be able to use require to load exports from
that ESM module? (Or similarly, if I just try to require an .mjs file...)
(To be clear: This is purely a question, not a veiled suggestion or
criticism. Here's an unveiled comment, though: *Thank you* for the
updated ESM stuff!)
It doesn't work with the v12 nightlies, but hey, it's nightlies, stuff is
in flux. :-)
My test setup, in case I'm just doing it wrong:
index.js:
const { foo } = require("foo");
foo("Hi");
node_modules/foo/index.js:
export function foo(...args) {
console.log("foo:", ...args);
}
node_modules/foo/package.json:
{
"type": "module",
"name": "foo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
Command:
node12 --experimental-modules index.js
Result:
(node:20699) ExperimentalWarning: The ESM module loader is experimental.
/home/blah/blah/node_modules/foo/index.js:1
export function foo(...args) {
^^^^^^
SyntaxError: Unexpected token export
at Module._compile (internal/modules/cjs/loader.js:768:23)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:835:10)
at Module.load (internal/modules/cjs/loader.js:693:32)
at Function.Module._load (internal/modules/cjs/loader.js:620:12)
at Module.require (internal/modules/cjs/loader.js:731:19)
at require (internal/modules/cjs/helpers.js:14:16)
at Object. (/home/tjc/temp/esmcheck/index.js:1:17)
at Module._compile (internal/modules/cjs/loader.js:824:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:835:10)
at Module.load (internal/modules/cjs/loader.js:693:32)
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#308>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAecV5TL4vgOurOA-5m8zAN8rpCRKXxfks5veMZNgaJpZM4cgRwj>
.
Even if require(esm) was provided today it becomes hazardous to use over time as async-to-eval modules get introduced. For example a JS module using top-level await or a WebAssembly module. This can happen in dependencies you don't control, so it's not easy to defend against this hazard.
For this reason I'm also skeptical that this feature could be provided in a safe way that guaranteed future compatibility.
The safe way for CJS to import ESM is dynamic import().
Even if require(esm) was provided today it becomes hazardous to use over time as async-to-eval modules get introduced. For example a JS module using top-level await or a WebAssembly module. This can happen in dependencies you don't control, so it's not easy to defend against this hazard.
This is baseless fearmongering, IMO - the synchronicity (or lack thereof) of the execution of a module has no bearing on the synchronicity of the resolution of the module graph containing it; which is all that matters for pulling on the correct namespace objects. Introducing async evaluation does introduce the possibility of witnessing namespaces whose members do not yet have final values, but this is already possible in CJS today, eg with
setTimeout(()=>module.exports={x: 12},100);
nodejs/node#49450 has a proposal allowing require(esm) and this is a partial implementation (a proof of concept that integrating a require(esm) is certainly possible), with full support of "zebra striping" as it is called. Cache duplication isn't an issue when there's only one canonical loader for each cache entry (unlike a dual impl model where "cache duplication" is replaced with "implementation duplication" which is even worse), and deadlocking isn't a problem provided the code within node itself that's doing the syncification doesn't introduce async dependencies that can deadlock (user code cannot produce a deadlock, pending the final design of loaders with might be within the syncificed pipeline and thus may need some extra (already desired) context separation).
@NullDev no, rewriting the code is what you'd need to do to keep using a dep in CJS or transpiled ESM that dropped support for CJS. Changing the imports is the easy path - iow, using a different dependency. TLA isn't available outside of native ESM, so your solution wouldn't work.
Activity
MylesBorins commentedon Apr 6, 2019
devsnek commentedon Apr 6, 2019
we do have a design for allowing require(esm) but it's still in the early stages.
as a side note, i would not advise mixing cjs and esm in the same extension within a package
robpalme commentedon Apr 6, 2019
Even if
require(esm)was provided today it becomes hazardous to use over time as async-to-eval modules get introduced. For example a JS module using top-level await or a WebAssembly module. This can happen in dependencies you don't control, so it's not easy to defend against this hazard.For this reason I'm also skeptical that this feature could be provided in a safe way that guaranteed future compatibility.
The safe way for CJS to import ESM is dynamic
import().ljharb commentedon Apr 6, 2019
There also remains the possibility of dual modules, so you’d be able to require or import them.
tjcrowder commentedon Apr 6, 2019
Wow, never expected to get such quick and complete answers. Thank you all!!
tjcrowder commentedon Apr 6, 2019
@devsnek -
LOL no. That would be...bad...
weswigham commentedon Apr 8, 2019
This is baseless fearmongering, IMO - the synchronicity (or lack thereof) of the execution of a module has no bearing on the synchronicity of the resolution of the module graph containing it; which is all that matters for pulling on the correct namespace objects. Introducing async evaluation does introduce the possibility of witnessing namespaces whose members do not yet have final values, but this is already possible in CJS today, eg with
nodejs/node#49450 has a proposal allowing
require(esm)and this is a partial implementation (a proof of concept that integrating arequire(esm)is certainly possible), with full support of "zebra striping" as it is called. Cache duplication isn't an issue when there's only one canonical loader for each cache entry (unlike a dual impl model where "cache duplication" is replaced with "implementation duplication" which is even worse), and deadlocking isn't a problem provided the code withinnodeitself that's doing the syncification doesn't introduce async dependencies that can deadlock (user code cannot produce a deadlock, pending the final design of loaders with might be within the syncificed pipeline and thus may need some extra (already desired) context separation).The fears around it are overblown, IMO.
robpalme commentedon Apr 8, 2019
@weswigham Thanks for highlighting the proposal. Let's continue main discussion there.
I look forwards to learning how you can eliminate the hazard 😉
module: support requiring .mjs files
stevenvachon commentedon Feb 27, 2021
Any update on this?
NullDev commentedon Oct 29, 2021
This would be really nice. Many dependencies are dropping require for ESM. So once we update, we'd have to change all the CommonJS imports to ESM.
ljharb commentedon Oct 29, 2021
… or, you could drop those dependencies and find replacements that maintain compatibility.
NullDev commentedon Oct 29, 2021
@ljharb So, rewriting the whole code instead of changing the imports? 😄
Why not just add the ability to load ESM with commonjs.
I mean, while at it why not just replace all the
require()'s toimport()'s...Not really a solution either ^^
ljharb commentedon Oct 29, 2021
@NullDev no, rewriting the code is what you'd need to do to keep using a dep in CJS or transpiled ESM that dropped support for CJS. Changing the imports is the easy path - iow, using a different dependency. TLA isn't available outside of native ESM, so your solution wouldn't work.