Skip to content
This repository has been archived by the owner on Sep 2, 2023. It is now read-only.

Minimum to release? #253

Closed
GeoffreyBooth opened this issue Jan 21, 2019 · 32 comments
Closed

Minimum to release? #253

GeoffreyBooth opened this issue Jan 21, 2019 · 32 comments

Comments

@GeoffreyBooth
Copy link
Member

In your opinion, what needs to be added to the minimal kernel/new ecmascript-modules implementation (and/or the implementation that Guy has built atop that), in order to:

  • 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?

@ljharb
Copy link
Member

ljharb commented Jan 21, 2019

To unflag (not exhaustive):
Must have: Transparent interop
Should have: transparent interop by default

@guybedford
Copy link
Contributor

@ljharb can you clarify what you mean by transparent interop? Because all the current implemetations support importing CJS from ESM with ESM syntax.

@ljharb
Copy link
Member

ljharb commented Jan 22, 2019

Fair point :-) one way to describe the “levels” of interop, as i see it, is:

  1. can import both named and default from cjs into esm without any change to the cjs, and without knowing that the module is cjs
  2. the current dynamic modules proposal, which allows the above except for export * from cjs during a cycle
  3. the first one, minus named
  4. any of the above, but you have to know it’s cjs
  5. no interop, except by custom loaders, some of which ship with node
  6. 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.

@robpalme
Copy link
Contributor

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
Copy link
Contributor

@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
Copy link
Member

ljharb commented 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
Copy link
Member

MylesBorins commented Jan 22, 2019 via email

@zenparsing
Copy link

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
Copy link
Member

ljharb commented 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
Copy link

zenparsing commented 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
Copy link
Member Author

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
Copy link
Member

ljharb commented Jan 22, 2019

I also want extension and index resolution, just like CJS has.

@devsnek
Copy link
Member

devsnek commented Jan 22, 2019

I also consider this incomplete without extension/index resolution. Same with loaders.

@robpalme
Copy link
Contributor

@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?

@ljharb
Copy link
Member

ljharb commented Jan 23, 2019

@robpalme import maps aren’t in the language and it’s not clear yet how node would support them; it’s certainly a potential path forward tho. package-specific solutions aren’t interesting to me here (but are for other reasons) because of the use cases that don’t involve a package.json.

@ljharb
Copy link
Member

ljharb commented Jan 23, 2019

Also note the consensus on phases was for implementation/progress, not for unflagging early. All phases must be completed before unflagging, imo.

@robpalme
Copy link
Contributor

package-specific solutions aren’t interesting to me here (but are for other reasons) because of the use cases that don’t involve a package.json.

Are there any proposals in-flight that address the need you are highlighting?

@ljharb
Copy link
Member

ljharb commented Jan 23, 2019

No, since we've decided to split things up in phases, we haven't really talked about "defaults" yet.

Having spent years working on this before this working group even formed, I remain convinced that the ideal solution is extension and directory lookup by default, .mjs is the only ESM, and maximally transparent interop by default such that you can import 'cjs' - and then any of the defaults would be customizable via loaders. I'm very happy to have a per-package field in package.json that remaps mimes/extensions, but that'd be on top of the defaults mentioned.

@devsnek
Copy link
Member

devsnek commented Jan 23, 2019

@robpalme i think the exact hooks are still in flux, but we should have the ability to entirely override resolution and to create synthetic modules in some way.

overall i agree with ljharb, we should unflag a proper and complete implementation. lets get it done and get it done right.

@zenparsing
Copy link

.mjs is the only ESM

Users have specifically told us (for years) that this design element is a big problem for them. If we are designing something for our users, then I think we must not go there.

@devsnek
Copy link
Member

devsnek commented 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
Copy link

@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
Copy link
Member

ljharb commented 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
Copy link
Member

devsnek commented 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 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.

@devsnek

This comment has been minimized.

@zenparsing
Copy link

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
Copy link
Member Author

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
Copy link

This was not a good discussion, and I will be taking a break from participating in this group.

@jpike88
Copy link

jpike88 commented 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
Copy link
Contributor

soldair commented 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
Copy link
Member

@GeoffreyBooth are you open to closing this in favor of #286

@GeoffreyBooth
Copy link
Member Author

@GeoffreyBooth are you open to closing this in favor of #286

Yup!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants