-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
When will CommonJS modules (require) be deprecated and removed? #33954
Comments
@nodejs/modules has probably discussed this extensively, and so have many other project members. Sharing my opinion on this: deprecation and removal of CommonJS would be extremely disruptive to the entire ecosystem, and would cause more pain to our users than Python users experienced with migrating to Python 3. As such, deprecation is unlikely to happen in the mid-term future, if at all. |
I don’t see any point in ever doing that - CJS isn’t legacy, it’s just one of two first-class module systems in node. |
I think it’s too early to come up with a clear timeline for this. We’re just approaching the first non-trivial module based apps being possible (without compiling from something else, at least rewriting imports). And there’s a huge amount of code in the ecosystem and even more so in various companies that’s based on CJS - much of which may be non-trivial to convert to ESM (since ESM lacks certain features and is fully async). So - I wouldn’t go as far as Jordan and say “never” but I’d say “long enough that it could as well be never at this point”. |
Still way too early to even consider, especially given that ESM is still experimental |
Seems answered, closing |
I hate to revive a long closed issue, but I don't think this topic is resolved. At least one major module developer is planning to remove support for CJS from their modules by the end of 2021 -- https://twitter.com/sindresorhus/status/1349294527350149121 I think without a clear signal from core that CJS is deprecated, module authors are going to have a maintenance nightmare on their hands. As a result of the above announcement, @mcollina has asked the Fastify community if we should do the same fastify/fastify#2847. What we will have is a hodgepodge of incompatible modules and fragmentation throughout the community. CJS codebases that wish to remain CJS will have to try and find replacement modules, fork and maintain older versions of the modules they use, or refactor their code base to either load modules asynchronously or convert to ESM. Personally, as a backend only developer, I have not seen any "oh I gotta have that" benefits to ESM that would convince me to shift everything over. But if core were to come out and say "look, keeping both around is going to be a problem so we are deprecating CJS," then I'd basically have no choice. And it would give clarity to the community at-large as to what their maintenance path forward should be. cc: @sindresorhus for your own visibility to whatever discussion happens here. |
It isn’t deprecated, so no such signal should exist. CJS and ESM are both first-class module systems in node. If a package switches to only ESM, that package has chosen to exclude CJS users, and those users will either switch to ESM, or more likely find alternatives that don’t capriciously exclude them (since providing an ESM wrapper on a CJS package is relatively trivial). |
My 2c, There was a lot of effort to make dual packaging reality, and for personal experience I can say it works fine with everything out there (bundlers, CJS only projects, ESM ony projects), plus cache invalidation/hot reloading is still extremely hard in ESM, so that choosing to ditch CJS when there are tools (ascjs/ucjs to name two) that makes dual packaging a no-brainer, beside the only constraint that is live bindings, sounds a bit "capricious" indeed. |
There is no plan to deprecate cjs. |
I am aware. My statement is that some discussion should be had about if a plan to do so should be created. In my view, there is clearly a painful future in store if it isn't deprecated. To be clear, I have no desire to use ESM. But if having both CJS and ESM supported means there will be a fragmented community, then only one should be supported. |
There would only be a fragmented community if authors decide to exclude one part of it by shipping a non-dual ESM package. The solution to that fragmentation is community pressure on those authors, and/or abandoning those authors. |
Sadly, I see myself doing that last part. |
That is also an effective form of community pressure. |
I think, ultimately, we need to come up with a new definition of "Deprecated" in Node.js. There used to be a very toxic notion in Node.js that an API or subsystem could be "locked", and that was used to justify all kinds of bad behavior around rejecting changes, fixes, and necessary improvements. I'm very happy that mentality has been pushed out of the project but we do need a formal notion of some API or subsystem that is just... done, or obsolete, even if it's not going anywhere, and even if someone wants to keep maintaining it. We have some examples of this already in core. The Whatever our personal opinions are about whether CommonJS was good enough -- it's not the standard, it's not where the ecosystem is going, it's not where JavaScript is going, and we need to just accept that fact and clearly communicate the direction we think things are heading in. So, no, I don't think we're anywhere close to Deprecating CommonJS in Node.js... at least not from the point of view of removing it outright, but I do think we can and should draw a line in the sand and say that ESM is the direction we're going from here on out. |
How would core communicate that, in your opinion? |
Would you take, "At this point I have no idea yet" as an answer for now? ;-) |
"new code should never use it" is objectively a false claim for CJS; there are a great many reasons new code should use CJS for the foreseeable future. If things change, then we can make changes at that time.
I think this would be the wrong statement for node to make - now or any time soon - and that stance would do great harm to the ecosystem. |
The harm has already been done by making two module systems available. |
Possibly by releasing a major version where esm is the default for files and a |
Maybe we should also consider the consequence of Node being perceived as directionless on the matter. Browsers are clear. Deno is clear. Modern tooling is clear. Import Maps just landed in Chrome Stable today. We have already leveraged them to get portable/universal ESM code running across both client & server environments. The Developer Experience is amazing. The future is quickly arriving. I think Node has a very healthy future. It's easier to sell that vision to others when we have coherent message that table-stakes features like ESM are the way forwards, even if rough edges (feature gaps) still exist today. CJS support will likely never go away, but in my personal opinion, it would weaken the Node project for it to appear confused about which way the world is going. |
/to @jasnell
Perhaps the term “effectively frozen” would be a good fit here.
Refs: https://twitter.com/ryzokuken/status/1359612226009616386 |
@robpalme where have browsers messaged that no new code should be written as Scripts? I'll add, that TC39 won't be adding any language features that are ESM-only (besides ESM-related ones, ofc) - in other words, TC39 isn't stating that no new code should be written as Scripts either. |
@ljharb -- I would push back just a bit to make it clear: I'm not saying that Node.js users shouldn't have the ability to keep writing Scripts rather than Modules... and I'm not saying that the CommonJS support should go away. What I'm arguing for is that, given the direction the ecosystem is going, and given the massive differences that exist in the models, if we continue to keep our feet firmly planted on both sides we're not going to do either well. For better or worse (and I'm in the camp that it is indeed worse) ESM is the direction the platform has chosen and we should be emphasizing that moving forward (while continuing to support the legacy approach also). |
I see some other issues here. How will UMD modules work with I think we need a larger discussion as soon as possible, so we can get the headaches of migrating out of the way. I wonder if @github-staff can start a discussion about standardization and the legitimacy of ECMAScript. |
None of that has anything to do with CJS and ESM: the two module types that Node.js supports.
What? |
Additionally, UMD already works fine - it’s treated as CJS by anything that understands modern module systems. |
Never mind. 🤦♂️ |
CJS will probably never be removed from Node.JS as there are thousands of unmaintained packages out there in the NPM ecosystem that use it and even more packages relying on those (for better or worse). However, CJS will lead a shadowy existence in the future as it provides no real advantage, but a number of disadvantages when compared to MJS (e.g. no top-level await, cannot use MJS libraries) so fewer and fewer people will use it for new projects. At that point it will probably become deprecated, if only because people will have problems using it due to no interoperability with MJS libs and it will be like domains. Deprecated, but probably forever in Node.JS as a relic of times past. |
@Haringat "no real advantage" may be true in the future, and i hope it is - but it's not true now, since loaders aren't shipped yet, hot reloading still can't work without a memory leak, etc. However, time will tell if the ecosystem's long term response to ESM-only packages is "switch to ESM" or "use/create CJS-friendly packages". |
@ljharb "create CJS-friendly packages" is a headache, as you either simply wrap a CJS module with ESM (at which point you basically maintain a CJS package as the entire functionally relevent code is in CJS) or you have two instances of your module hanging around which is bound to cause state-problems. |
No one is stopping you from exporting your esm code to cjs :] |
@Haringat or you just make a CJS-only package and you're done. @benjamingr you can't do that synchronously. |
@ljharb or I just make a ESM-only package and I'm done. |
@Haringat except that your package can't be used by the majority of the ecosystem. to me that's not "done" but certainly you're not alone in calling it thus. |
@ljharb what do you mean? What's stopping you from |
@benjamingr That is the wrong direction. That is for consuming CJS files from ESM files. You were talking about exporting ESM to CJS. |
@benjamingr i'm confused, |
CommonJS starts faster. |
Not always, but it can be the case (especially when everything is on the FS)
It is async but not because it was meant to be a browser-technology, but because it was meant to work everywhere. |
@xieyuheng Well it is not really about it being technically impossible to support both, but rather about it becoming annoying in the long run. For the moment the call is definitely to support both, simply because there are literally thousands of cjs packages out there. I predict that in a few years there will be two kinds of packages: Those that use mjs and those that have not seen an update in years by then. And then the argument to keep supporting cjs only to not break some unmaintained packages will not be too strong. |
No, it’s technically impossible - the way bun did it is to disable a language feature, top-level await, and likely to violate some of the timing guarantees in the spec (i haven’t investigated yet to be certain). |
Why are we talking about what Bun is doing in a thread about what Node.js should or shouldn't do? |
I totally agree - node has different constraints, and “but not-node does X” isn’t relevant to whether node can or should do X. |
The fact that this thread is still open for comments is a testament to the overwhelming patience and tolerance of the steering committee and the Node core team. |
Okay, more thousands than I thought 😉
AFAIK there are two competing JavaScript runtimes: deno and bun. Deno promotes ESM as it is typescript-first. Bun supports both as you mentioned. I fail to see your point...
My guess would be that if node ever removed cjs (which they would only do after one hell of a deprecation period), people who would still depend on it would either move on to ESM or stay on a node version that supports cjs.
See my prediction above. |
Please take whatever this conversation is to another thread. |
My demo might be incorrect, but I feel like it may still be possible, doing so like this maybe? If you instead compare /* c8 ignore start */
let canvas;
try {
canvas = await import('canvas');
} catch (fallback) {
canvas = await import('./canvas-shim.cjs');
}
export default canvas;
/* c8 ignore stop */ Come to think of it, I think this pattern may be similar as well. /* c8 ignore start */
export default await import('canvas').catch(() => import('./canvas-shim.cjs'));
/* c8 ignore stop */ |
Just curious if this is planned to happen, or is it something no one is thinking about yet?
The text was updated successfully, but these errors were encountered: