nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
106.58k stars 29.06k forks source link

When will CommonJS modules (require) be deprecated and removed? #33954

Closed trusktr closed 4 years ago

trusktr commented 4 years ago

Just curious if this is planned to happen, or is it something no one is thinking about yet?

ljharb commented 1 year ago

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

benjamingr commented 1 year ago

@ljharb what do you mean? What's stopping you from createRequire in and then exporting whatever you want from there?

Haringat commented 1 year ago

@benjamingr That is the wrong direction. That is for consuming CJS files from ESM files. You were talking about exporting ESM to CJS.

ljharb commented 1 year ago

@benjamingr i'm confused, createRequire is used to make a require function, which can't pull in ESM - afaik the only way to consume ESM in a CJS module is import(), which is async.

aquapi commented 11 months ago

CommonJS starts faster. ESM is meant to be used with browser, which means that it is async. Async does cost some microticks and overhead.

Haringat commented 11 months ago

CommonJS starts faster.

Not always, but it can be the case (especially when everything is on the FS)

ESM is meant to be used with browser, which means that it is async.

It is async but not because it was meant to be a browser-technology, but because it was meant to work everywhere.

Haringat commented 11 months ago

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

ljharb commented 11 months ago

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).

jsumners commented 11 months ago

Why are we talking about what Bun is doing in a thread about what Node.js should or shouldn't do?

ljharb commented 11 months ago

I totally agree - node has different constraints, and “but not-node does X” isn’t relevant to whether node can or should do X.

tbjers commented 11 months ago

if there is not competition to nodejs, your prediction might be right.

but since there is competing server runtime supporting both.

people forced by nodejs to remove all commonjs code from their codebase maybe will simply choose the competing runtime.

if it is your team and your app, what you would do?

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.

Haringat commented 11 months ago

@xieyuheng

millions not thousands.

Okay, more thousands than I thought 😉

if there is not competition to nodejs, your prediction might be right.

but since there is competing server runtime supporting both.

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

people forced by nodejs to remove all commonjs code from their codebase maybe will simply choose the competing runtime.

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.

if it is your team and your app, what you would do?

See my prediction above.

jsumners commented 11 months ago

Please take whatever this conversation is to another thread.

Offroaders123 commented 8 months ago

My 2c, today I wrote this file because CommonJS can still do things ESM cannot, and work in both cases (as that file does).

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.

My demo might be incorrect, but I feel like it may still be possible, doing so like this maybe?

If you instead compare module.exports = to that of export * from, rather than export default, then yeah I think you're right, you can't have conditionally-imported named exports from another module.

/* 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 */