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.
Replace the current --experimental-modules with the new implementation?
Unflag the new implementation?
With “the new implementation” here meaning, the new ecmascript-modules implementation plus whatever features you consider must-haves for either of the above milestones. What’s your “release as flagged” minimum viable product, and your “release as unflagged” minimum viable product?
Fair point :-) one way to describe the “levels” of interop, as i see it, is:
can import both named and default from cjs into esm without any change to the cjs, and without knowing that the module is cjs
the current dynamic modules proposal, which allows the above except for export * from cjs during a cycle
the first one, minus named
any of the above, but you have to know it’s cjs
no interop, except by custom loaders, some of which ship with node
no interop, except by userland loaders
I see each one as strictly better than the one that follows it, and i think that while the first is the ideal, shipping the second is far superior to any of the others.
My view is that we could ship without interop altogether (level 7?) and still get high adoption over the long-term. But we should have higher ambitions.
The sweet spot of reconciling what is best for our users whilst still being implementable/acceptable looks like level 3. It means named imports become a progressive enhancement you can use in your package as and when your dependencies upgrade to ESM. That matches the mental model of named exports being a value-add feature of introducing ESM in the first place.
@ljharb thanks for expressing your preference, in that case lets see if we can keep dynamic modules moving forward. But as mentioned previously, if we don't get them, then I think we have to go back to (1) and shouldn't let this bump cause reconsideration of the entire approach.
@robpalme i don’t think that’s how users will view it; many are already using named imports via babel or esm (and in tons of docs and tutorials) and without them in node, our implementation will be seen as lacking features, not adding them.
I think people can recognize the difference between using tools and core
platform. If our loaders implementation allows next generation tools to
accomplish this people will use it, or alternatively augment their code.
I don't think this is so black and white though... We can also ship
something and incrementally improve it over time
I think we are also underestimating the people-power of the ecosystem to adapt to no-cjs-imports. All it takes to add import support to any package is a simple PR adding an ESM entry point (or points) which maps CJS names to ESM names.
Here's one such PR I just received over the weekend, unsolicited:
It seems like that’s a smaller underestimation then underestimating the people-power of the ecosystem to adapt to the incredibly rare “export * from cjs when inside a cycle” case.
To clarify, it's not just the cycle case where dynamic modules disallows "export * from cjs".
Also, there was no claim made with regard to the ecosystem adapting to the lack of certain module features when importing CJS. Rather, the claim was that the lack of certain features will likely be perceived as a bug without any simple explanation as to why it doesn't work.
Folks, do you mind keeping the export * discussion in its own thread? In this one, please just answer the questions in the original post.
@ljharb, is there anything more than interoperability that you would want to see in the new implementation before it’s released flagged or unflagged? Loaders? Same goes for @guybedford@zenparsing@MylesBorins@robpalme
@ljharb@devsnek Please could you confirm if your extensionless/index requirement is satisfied by the web-compatible approach of solving this for bare specifiers? That is the problem we have work in-flight to solve in the form of Jan's pkg-exports
@devsnek Please could you clarify which loader hooks must exist before we unflag. Also, given our working group explicitly prioritised fixed-functionality (phase 2) over extensibility (phase 3), what would be the reasoning for needing loaders from day 1?
features like automatically switching the parse goal and such can also be included with node, but they shouldn't be the default because they introduce ambiguity. the defaults should never be ambiguous.
i think it would be pretty reasonable to add a new transform target called "ambiguous" or something which would perform your proposed parse which switches based on syntax that pops up. then it would be as simple as ".js": "ambiguous" or whatever the format of the package.json ends up being. (and you could also use it with resolve hooks)
@devsnek There is a place for principles and there is a place for practicality. A little ambiguity is practical and tolerable if it helps us meet our users. I don't think our users want a long term future where they have to intone some incantation (in package.json or whatever) in order to use ".js" for ESM.
Reacted by John-David Dalton, Rasmus Porsager, Michael Ciniawsky, Corbin Uselton and Evan Plaice
@zenparsing the problem is that TC39’s unwillingness to make the parse goals unambiguous means that those users simply can’t get what they want by default - it’s not our choice to make; tc39 made it in es6.
In the future we could change the default or make it more ergonomic, but the long term future of modules is “nothing” if we don’t have a good interop story here.
Firstly: I deeply respect people's right to configure node however they want to. That being said, there are no real technical arguments against mjs, and so it has to be ranked a bit lower so we can deal with actual technical issues we have. There isn't even a problem with migrating to new extensions, people do it with a smile on their faces for ts and jsx, which don't even have any syntatic ambiguity with ecmascript parse goals.
Secondly: The node runtime should not - by default - be in situations where it can be wrong about the handling of your code. If it has a problem with your code, the only sane option is to not run the code. Contrary to what you say, the thing that executes your code (with a lot of potential side effects) is the exact right place for a hard requirement on correctness by default. This same issue came up with promise rejections a few months ago, and eventually we came to the same conclusion.
Thirdly: I've spent far less time in the ecosystem than you have, so I can't claim to know what people want more than you can. However, I spend a lot of time hanging out with people who use js, and I see the mjs topic come up a lot. Whenever the topic comes up, it's usually people with very valid frustrations about mjs because it's different from their {babel, webpack, ts, whatever} project. So then someone will explain the actual constraints of why mjs exists, and why node wouldn't just magically know whether a file is esm or cjs. At this point the response is usually one of "they should have just put <the module bundler i use> in node" or "oh that's pretty interesting, I guess mjs actually makes a lot of sense then".
On top of all of that, you also are also promoting a solution where the safest usage is (by your own suggestion) to put export {} in every file, and then saying that putting a single line in your package.json is somehow untenable. At this point the only emotions I'm left with are surprise and disappointment that you're unable to work to compromise for a safe and usable runtime for all people, not just 99% of people.
I look forward to working with you on the best possible outcome for all users of node, and I hope we can avoid this thread devolving into another argument about mjs.
Reacted by Charles Samborski, Jayden Seric and Ben Painter
Good discussion everyone, but I was really just hoping for a thread where each member of the group could answer the questions posed in the initial post. That way I could start to see what work remains in the new implementation. If I start a new thread could we please keep it focused on answering the questions like a survey?
The longer there are delays in unflagging this functionality, the more detrimental this will be for the node community. Such a widely adopted syntax/module system should have had a more decisive outcome literally years ago. At least support .mjs for the time being while you move to the perfect solution, it's just a file extension for gods sake
\o a little late here
To un-flag modules I need a way to provide module source via loaders without any calls to the file system like i can and do with -r loaders for cjs. (this includes io reading package.jsons) Happy to provide more info and help in the WG here if needed.
Activity
ljharb commentedon Jan 21, 2019
To unflag (not exhaustive):
Must have: Transparent interop
Should have: transparent interop by default
guybedford commentedon Jan 21, 2019
@ljharb can you clarify what you mean by transparent interop? Because all the current implemetations support importing CJS from ESM with ESM syntax.
ljharb commentedon Jan 22, 2019
Fair point :-) one way to describe the “levels” of interop, as i see it, is:
I see each one as strictly better than the one that follows it, and i think that while the first is the ideal, shipping the second is far superior to any of the others.
robpalme commentedon Jan 22, 2019
These levels make sense to me.
My view is that we could ship without interop altogether (level 7?) and still get high adoption over the long-term. But we should have higher ambitions.
The sweet spot of reconciling what is best for our users whilst still being implementable/acceptable looks like level 3. It means named imports become a progressive enhancement you can use in your package as and when your dependencies upgrade to ESM. That matches the mental model of named exports being a value-add feature of introducing ESM in the first place.
guybedford commentedon Jan 22, 2019
@ljharb thanks for expressing your preference, in that case lets see if we can keep dynamic modules moving forward. But as mentioned previously, if we don't get them, then I think we have to go back to (1) and shouldn't let this bump cause reconsideration of the entire approach.
ljharb commentedon Jan 22, 2019
@robpalme i don’t think that’s how users will view it; many are already using named imports via babel or
esm(and in tons of docs and tutorials) and without them in node, our implementation will be seen as lacking features, not adding them.MylesBorins commentedon Jan 22, 2019
zenparsing commentedon Jan 22, 2019
I think we are also underestimating the people-power of the ecosystem to adapt to no-cjs-imports. All it takes to add import support to any package is a simple PR adding an ESM entry point (or points) which maps CJS names to ESM names.
Here's one such PR I just received over the weekend, unsolicited:
zenparsing/zen-observable#55
ljharb commentedon Jan 22, 2019
It seems like that’s a smaller underestimation then underestimating the people-power of the ecosystem to adapt to the incredibly rare “export * from cjs when inside a cycle” case.
zenparsing commentedon Jan 22, 2019
To clarify, it's not just the cycle case where dynamic modules disallows "export * from cjs".
Also, there was no claim made with regard to the ecosystem adapting to the lack of certain module features when importing CJS. Rather, the claim was that the lack of certain features will likely be perceived as a bug without any simple explanation as to why it doesn't work.
GeoffreyBooth commentedon Jan 22, 2019
Folks, do you mind keeping the
export *discussion in its own thread? In this one, please just answer the questions in the original post.@ljharb, is there anything more than interoperability that you would want to see in the new implementation before it’s released flagged or unflagged? Loaders? Same goes for @guybedford @zenparsing @MylesBorins @robpalme
ljharb commentedon Jan 22, 2019
I also want extension and index resolution, just like CJS has.
devsnek commentedon Jan 22, 2019
I also consider this incomplete without extension/index resolution. Same with loaders.
robpalme commentedon Jan 23, 2019
@ljharb @devsnek Please could you confirm if your extensionless/index requirement is satisfied by the web-compatible approach of solving this for bare specifiers? That is the problem we have work in-flight to solve in the form of Jan's pkg-exports
@devsnek Please could you clarify which loader hooks must exist before we unflag. Also, given our working group explicitly prioritised fixed-functionality (phase 2) over extensibility (phase 3), what would be the reasoning for needing loaders from day 1?
6 remaining items
devsnek commentedon Jan 24, 2019
@zenparsing "by default"
features like automatically switching the parse goal and such can also be included with node, but they shouldn't be the default because they introduce ambiguity. the defaults should never be ambiguous.
i think it would be pretty reasonable to add a new transform target called "ambiguous" or something which would perform your proposed parse which switches based on syntax that pops up. then it would be as simple as
".js": "ambiguous"or whatever the format of the package.json ends up being. (and you could also use it with resolve hooks)zenparsing commentedon Jan 24, 2019
@devsnek There is a place for principles and there is a place for practicality. A little ambiguity is practical and tolerable if it helps us meet our users. I don't think our users want a long term future where they have to intone some incantation (in package.json or whatever) in order to use ".js" for ESM.
ljharb commentedon Jan 24, 2019
@zenparsing the problem is that TC39’s unwillingness to make the parse goals unambiguous means that those users simply can’t get what they want by default - it’s not our choice to make; tc39 made it in es6.
In the future we could change the default or make it more ergonomic, but the long term future of modules is “nothing” if we don’t have a good interop story here.
devsnek commentedon Jan 24, 2019
@zenparsing
Firstly: I deeply respect people's right to configure node however they want to. That being said, there are no real technical arguments against mjs, and so it has to be ranked a bit lower so we can deal with actual technical issues we have. There isn't even a problem with migrating to new extensions, people do it with a smile on their faces for ts and jsx, which don't even have any syntatic ambiguity with ecmascript parse goals.
Secondly: The
noderuntime should not - by default - be in situations where it can be wrong about the handling of your code. If it has a problem with your code, the only sane option is to not run the code. Contrary to what you say, the thing that executes your code (with a lot of potential side effects) is the exact right place for a hard requirement on correctness by default. This same issue came up with promise rejections a few months ago, and eventually we came to the same conclusion.Thirdly: I've spent far less time in the ecosystem than you have, so I can't claim to know what people want more than you can. However, I spend a lot of time hanging out with people who use js, and I see the mjs topic come up a lot. Whenever the topic comes up, it's usually people with very valid frustrations about mjs because it's different from their {babel, webpack, ts, whatever} project. So then someone will explain the actual constraints of why mjs exists, and why node wouldn't just magically know whether a file is esm or cjs. At this point the response is usually one of "they should have just put <the module bundler i use> in node" or "oh that's pretty interesting, I guess mjs actually makes a lot of sense then".
On top of all of that, you also are also promoting a solution where the safest usage is (by your own suggestion) to put
export {}in every file, and then saying that putting a single line in your package.json is somehow untenable. At this point the only emotions I'm left with are surprise and disappointment that you're unable to work to compromise for a safe and usable runtime for all people, not just 99% of people.I look forward to working with you on the best possible outcome for all users of node, and I hope we can avoid this thread devolving into another argument about mjs.
devsnek commentedon Jan 24, 2019
zenparsing commentedon Jan 24, 2019
Hey, let's start over with this tomorrow - sorry for the quick response.
(Btw, after digging around in the current modules implementation, I think it's really good actually!)
GeoffreyBooth commentedon Jan 24, 2019
Good discussion everyone, but I was really just hoping for a thread where each member of the group could answer the questions posed in the initial post. That way I could start to see what work remains in the new implementation. If I start a new thread could we please keep it focused on answering the questions like a survey?
zenparsing commentedon Jan 24, 2019
This was not a good discussion, and I will be taking a break from participating in this group.
jpike88 commentedon Jan 25, 2019
The longer there are delays in unflagging this functionality, the more detrimental this will be for the node community. Such a widely adopted syntax/module system should have had a more decisive outcome literally years ago. At least support .mjs for the time being while you move to the perfect solution, it's just a file extension for gods sake
soldair commentedon Jan 25, 2019
\o a little late here
To un-flag modules I need a way to provide module source via loaders without any calls to the file system like i can and do with -r loaders for cjs. (this includes io reading package.jsons) Happy to provide more info and help in the WG here if needed.
MylesBorins commentedon Mar 13, 2019
@GeoffreyBooth are you open to closing this in favor of #286
GeoffreyBooth commentedon Mar 13, 2019
Yup!