-
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
Enable explicit .m.js
intent for ESM
#16170
Conversation
That is already possible with |
The portability of each module is currently compromised and this is bad already, not even in the long term, as you could read through my post that explains all the caveats.
|
It's a very minor change to tweak existing servers to supply the proper mime type for |
not everyone controls external environments/servers and the proposed change is one line full of wins for the entirety of the community. |
Like WebReflection, I often have no control over the server/environment. It's going to be a lot longer for me to able able to use |
s/will/would/ |
Just for context, there is an EPS with a suggestion for explicit ESM intent (via a package.json flag) - nodejs/node-eps#60 Also AFAIK the timeline for completing the ESM loader (i.e. until the CLI flag is removed) is for node 10, which is 6 more months away. So there is no rush, and hopefully improvement suggestions will have time for discussion. |
If you're using node, |
There is no reason to create an unnecessary portability barrier for the sake of it. A standard JS module should work everywhere, there are not just browsers and Node, there's an infinity of other environment to consider too. It's surprising, to say the least, someone from TC39 is pushing NodeJS to break where every other standard JS env would not.
Are we saying, or reached the point, JavaScript is finally fully incapable, as a programming language, to work cross platform without needing third parts build processes? Or we are consciously creating an unnecessary portability barrier?
This hasn't even landed in NodeJS and you call servers unaware of
Why it's a huge burden to enable, as alternative solution, my proposal? Where are stats about Where are stats about the impact of unrecognized If everyone is concern about |
I went ahead and done little research. Apparently, over 80% of the Web uses PHP. So I've tried to see if latest PHP would be able to serve a My version is 7.1.10 So I've spinned the server and this is the result: As you can see, the most updated PHP wouldn't be able to serve JavaScript modules with an extension only NodeJS recognizes. Since Then you say ...
So I've found few stats of the most common PHP versions online, for that over 80% of the Web. The reality is that if environments are so outdated, how can we even believe it's "a minor change" to tweak existing servers? TL;DR we are breaking the whole package distribution ecosystem. We're unable to publish native ESM modules so we are slowing adoption of the standard because files with Accordingly, since the slice of side effects and issues with this new extension is way bigger than advantages, 'cause there are zero advantages outside NodeJS env niche, why are we destroying the future of native ES2015 modules like this here? Where is the list of pros that overtake the list of cons, considering JavaScript has bigger adoption outside NodeJS, and again I'm not talking just about browsers? |
Update if I understand correctly, using this loader and running node as such: node --loader es.mjs this PR/proposal would be enabled by default using an official mechanism provided in core. If this is correct, than maybe using that loader is a way to understand how relevant, needed, or used, is the |
Every environment needs to know whether the file is a module or not before it can run it. |
|
No. The the Accordingly, for the time being, this loader should help migrating without involving any import _url from 'url';
const builtins = new Set(
Object.keys(process.binding('natives')).filter(str =>
/^(?!(?:internal|node|v8)\/)/.test(str))
);
const esmIfExplicit = url => {
const eof = url.slice(-5);
return {
url,
format: eof === '.m.js' || eof.slice(1) === '.mjs' ?
'esm' : 'dynamic'
};
};
export const resolve = (specifier, base) =>
builtins.has(specifier) ?
{url: specifier, format: 'builtin'} :
esmIfExplicit(new _url.URL(specifier, base).href; |
Quoting an email that didn't land here, without mentioning the author, in case it didn't land for that reason
Every developer spinning a localhost with PHP will have issues but it's true that's not the production scenario. However, the point here is that if PHP versions are not updated, it's clear that it's not so easy/straight-forward to expect the whole world suddenly will be able to serve
Yes, even latest Apache does not serve |
@WebReflection Nope, just as a reminder that from usage standpoint this could be simple :)
Your proposal is much better then introducing an new file extension && MIME for all the reasons your already extrapolated above 😛 . I would still prefer the 'metadata' approach since this aligns more with how browsers implemented it, but that's less of a concern to the status quo imho To say it directly If all of this isn't sufficient resolvable then there must be spec changes proposed until a env agnostic workable standard is found (from a pure Module System point of view) and node is better off with CJS meanwhile |
Since there were metrics about extension issues, here I've found also metrics about how backward incompatible would be to adopt I would personally file a PR to fix that single module with |
@michael-ciniawsky @WebReflection please see: ayojs/ayo#91 as it appears we are duplicating efforts. This implements I'm currently battling with v8 to land |
@tbranyen yes, absolutely agreed and the only reason I've filed this PR is that My only attempt is to not diverge from standards and other environments, creating an absolutely redundant extension nobody needs to signal that its JavaScript is really just JavaScript. Having Node shipping standard import behaviors and People early adopting CommonJS as ESM already use tooling so those won't be affected, everyone else that would like to jump into fully standard ESM and keep the ability to require CommonJS legacy modules could simply do so. It'd be the best solutions we all want but for some reason somebody prefers to promote community failures and curse the language with two extensions. Thank You !!!P.S. the only reason I won't abandon this and I'm fulfilling all steps to have a proper PR is that I'd like to keep all possible doors open until a final, not experimental anymore, decision has been taken. |
@tbranyen I saw that one, but |
[Partially OT] Just finished watching @MylesBorins give the modules talk for NINA 2017 - |
As discussed in the [.mjs extension trade-offs](nodejs/node-eps#57 (comment)) post, it would be great if NodeJS could provide a way to explicitly opt-in as ESM, without needing to use a different extension. The purpose of this PR is to enable a universal convention for ESM that would work out of the box in both browsers and other JavaScript environment including SpiderMonkey and JSC. If the file is imported with a fully qualified path name, and such path name uses the `.m.js` convention, the format will be ESM and it will throw if such file does not respect such format. The current NodeJS diversion from the rest of the JavaScript environments is alarming for various reasons and consistency, as well as code reliability, is currently potentially compromised, as described in details in [this blog post](https://codeburst.io/the-javascript-modules-limbo-585eedbb182e). If there is anything else I could do in order to land this PR while ESM is still behind an experimental flag, please let me know, thank you.
@michael-ciniawsky good point! once I get the latest v8 landed and swap |
For the record, it was me. I deleted the comment because I realized this topic is sprawling and has multiple rabbit holes, and that the rabbit holes I was gravitating towards weren't the ones that were going to get us to a resolution or greater understanding. So I removed my comment. Your reply is helpful, though. I understand now why you brought that topic up. So thanks for that. |
@devsnek TC39 and browsers have all rejected that option; node is not likely to go with that option in that light. Yes, the only person who should decide if something is ESM or not is the author of that code, not the consumer - only the author has the ability to safely decide that. A file extension, as well as package.json metadata, achieve that. |
@LinusU yes, |
@devsnek The concern with |
This is key. I can make up my own requirements too and decide that keeping It's been months we're discussing this issue with some people talking like a secret room of very important people made up constrains so that nothing works because of these constrains nobody can even read to make counter-proposals ... so to whoever is concerned about the quality of this discussion, how about we start moderating every subjective opinion delivered as VIP decision? Thank you. |
This isn't just a subjective thing; this requirement is necessary for there to be a smooth migration path to ESM for everyone. Either ESM becomes the universal module format for JS, or it's DOA, and if "migrating my module to ESM" has to be a breaking change, then package authors won't do it en masse. The requirement to not have to know the module format you're importing is precisely for this reason: because without it, ESM is dead. |
@ljharb I totally agree with this requirement. However, unless I'm missing something, this can only work if we have named imports with CJS interop. Otherwise, one has to know that a module is CJS or ESM to use its exported functions. And worse: a module migrating to ESM would be a breaking change for people who already Note: we are trying to get named exports from CJS in this PR: #16675 |
I kind of think that it is though. All the different way forwards has different pros and cons, and which one you care most about is subjective...
I think a very good migration path is to introduce it in a way where you can use both the new (
I mean, won't that always be the case? Because if the module starts using the Furthermore, it doesn't have to be a breaking change to the api, if paired with a field in the package.json a module could publish a file with
I don't really see how you are making this connection. The only thing this would mean is that when I'm importing another library, I need to know how to import it. Since at this point I'll probably be looking at the documentation for the modules anyway, that is probably the first thing mentioned. It's also a really simple rule to remember, to import an es module use |
By the time ESM is shipped in Node, you will probably be able to use the old
I depends on how the module is published. Authors can write the module with the import syntax and publish it along with the code transpiled to CommonJS. |
I use ESM daily, it's pretty much alive to me, and this is the kind of speculative tone I'm a bit tired about. I will no answer anymore to speculative, subjective, arguments that bring to this topic absolutely nothing.
I fully agree on this approach, which is the same shared by Chris in this tweet: |
@targos I believe |
@targos awesome! I had tried landing the latest v8 at the time |
everything in JS works with |
@WebReflection yeah, I'm wondering if Node intends to interfere with that or if that will inevitably become a "backdoor" into loading (async () => {
const { default: map } = await import('/node_modules/lodash-es/map.js');
})();
I much prefer the To echo what @jmeas had brought up before, it would be great to see evidence that is clearly documented that refutes the notion of a CLI flag. At the time I was working on that implementation, I was constantly told that Node would never support it, and any attempts to land it would be blocked. More specifically, we need more concrete reasons, instead of (what I consider FUD):
I hope the TSC can be more open-minded about how users will consume modules, it's hard to discuss alternatives when one side is absolutely deadlocked. |
There is |
also, from that very same thread:
this basically erase any concern about not needing to know what kind of module you are importing, something I've anyway never experienced in 18+ years of JS (require, import, globals, JSONP, I always knew what I was consuming). |
@tbranyen I might not be telling you anything you don't already know below, but I'm going to say it anyway for observers/readers.
The TSC doesn't usually get involved in things to that level of detail. Generally, the decisions are made by the people doing the implementation work along with whatever subset of the 100+ Collaborators who review the specific contributions. The TSC gets pulled into ESM frequently because it's so contentious, so I wouldn't remotely be surprised if the TSC had to weigh in on a PR implementing a
The opinion your quoting/responding to is not from the TSC or even a TSC member. That said, I get it that from your perspective, the TSC is not being sufficiently open-minded. I'll just add that it has also been stated (including by someone doing actual implementation work on ESM for Node.js) that the TSC has been insufficiently decisive about this stuff, meaning we get to have the same conversations over and over and get pull requests that undermine decisions/direction that should have been set a long time ago. I'm not saying your wrong to feel the way you do. But ESM is an explosive topic in some ways and the TSC is getting it from all sides. This is going to require patience (and a tolerance for repetition, I'm afraid). Thanks to everyone for participating. I know it can be frustrating. |
@Trott since TSC is aware of the situation I also hope it can help moving forward with the right decision for Node and the JS community. If I can summarize the current status, since I've been involved a lot over the last months, and I've proposed already various alternatives, patches, solutions, this is in favor of keeping
On the other side, to argument against this very same PR which is a last resort for Thanks for reading through. |
Hey all
I've been putting a lot of thought into this but have unfortunately been
too busy to review this thread yet
A few apis I'm interested in exploring independent of the interop story are
import.meta.require and require.import
import.meta is coming in V8 6.4 and @targos has a working proof of concept
As for require.import, I'm imagining it would behave very similarly to
"await import("module")" if top level await were a thing
I've also been having conversations with stakeholders from the web platform
around how we can improve the story around resolution in the browser,
including bare imports. Nothing exciting to report yet, but there are
people from both the web and node platform who think this is important.
My first priority is making sure that published modules can easily be
shared between the node + browser platform without a build step and I
promise to advocate for that path across the entire api surface
I will try to find time in the next week to review this thread and respond
to particular comments, but wanted to quickly give an update of where I'm
coming from on this as the champion of the modules effort on the TSC
One request I have for everyone on this thread, please remember that
everyone working on this is a volunteer. We all our trying hard to come up
with the best solution to a very difficult problem (socially and
technically). Please have faith that we are listening and will be acting in
good faith to help maintain / sustain the JavaScript ecosystem at large
The stakes here are high, we know that. Our best chance at finding a good
solution is by working together.
|
@MylesBorins not sure it could be helpful/related but I've proposed on January
which is unfortunately the feeling I have every time I try to interact with NodeJS repository. There are always quite few unproductive, subjective, theories exposed like absolute truth written in stones. I am looking forward to read every comment you have on this matter and thanks in advance for taking the time. |
last thought about the JS community: if it really matters, reading developers feedback on this very same thread should be considered. I'm the first one that doesn't like this last resort proposal to keep the Scrolling through the rest of the discussion it's easy to spot what is welcomed by the community and what is considered more hostile. |
i don't think that 30 people speak for a community of millions, and it would be irresponsible to assume so. |
Neither do I, although that’s the only data we have here so counter evidence is needed to state otherwise 🤷♂️ |
I'm going to go ahead and close this as we are not currently exploring You can find out more about the current state of modules in https://medium.com/the-node-js-collection/the-current-state-of-implementation-and-planning-for-esmodules-a4ecb2aac07a please let me know if this should be reopened |
For future visitors: npm’s recommendation for ES Modules uses flags (similar to ayojs/ayo#91) rather than |
As discussed in the .mjs extension trade-offs post, it would be great if NodeJS could provide a way to explicitly opt-in as ESM, without needing to use a different extension.
Goal
The purpose of this PR is to enable a universal convention for ESM that would work out of the box in both browsers and other JavaScript environment including SpiderMonkey and JSC.
If the file is imported with a fully qualified path name, and such path name uses the
.m.js
convention, the format will be ESM and it will throw if such file does not respect such format.Please consider this PR
The current NodeJS diversion from the rest of the JavaScript environments is alarming for various reasons and consistency, as well as code reliability, is currently potentially compromised, as described in details in this blog post.
If there is anything else I could do in order to land this PR while ESM is still behind an experimental flag, please let me know, thank you.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)