Live data from Hacker News

CommonJS is hurting JavaScript

deno.com

111–120 of 134 posts

Re: CommonJS is hurting JavaScript

#111

Does anyone have a detailed understanding of why CommonJS (and its async incarnation, AMD) were not adopted by browsers? I do much like the `import` syntax personally and its a little cleaner to read, but CommonJS and AMD were the undisputed winners of the module format until ES Modules were born. Not that I have a problem with ES Modules, I don't, however I am interested in what was so insufficient about the precedi…

From what I remember, reading the conversations over the years...the issue was twofold: 1. Because `require()` is "just a magic function", it can't be statically analyzed by a JS runtime prior to actually running the code. This leads to limitations with regards to tree-shaking and other optimizations. 2. The last point leads to the even bigger (and probably "deal-breaker") reason for the change, the desire to fetch p…

Why can't implementations tree-shake through require(x) where x can be determined statically and warn where x cannot?

Re: CommonJS is hurting JavaScript

#112

Earlier quoted context omitted.

To be honest, I think the AMD incarnation is a complete non-starter. It’s just such a funky, weird little thing that only makes sense because it’s a compatibility shim. Nobody wants to directly author AMD, and someone shipping a JS implementation wants to ship features that people will use directly. I mean, I guess people will directly write AMD modules, and make modules using some giant script that uses cat, but the…

+this ... AMD was just weird and clunky to use in practice... CJS bundlers were much easier to grasp by comparison, and when browserify (and those that followed) came out, it was kind of a no-brainer at the time. If ESM were finalized maybe even 2 years earlier, we'd probably be using that already for everything. I think the Node team choosing to make esm/cjs interop more difficult than what babel had been doing slow…

Yeah. The interop between ESM and CJS in Node is beyond horrible. My sense is that the developers are trying to iron out some differences so ESM can behave according to spec and CJS can also behave according to spec. These have to be problems with edge cases, right?

I don’t quite understand why you need the .cjs/.mjs stuff, either. You can tell the difference between an ES2015 module and CommonJS module after parsing, with the one exception of modules that have no imports and exports (which should be rare). What is the holdup, then? What’s breaking?

Re: CommonJS is hurting JavaScript

#113

Earlier quoted context omitted.

I've seen some great development environments where all of development/debugging is unbundled ESM directly in the browser. It's going to take a lot of momentum shift to swing the "bundler pendulum" back away from "always" to "as needed" (or even, shockingly, "never"), but I think it is going to happen. HTTP/2+ really does make "never" a bigger possibility than ever before, especially in cases like MPAs (and SSR SPAs…

I, too, thought http/2+ would encourage unbundled js, but unfortunately in a world where people are used to whole-program minification and dynamic app slicing, I don't think we'll _ever_ move away from bundlers. The build step is here to stay for most serious projects. ESM may very well be the module system designed for a world that'll actually never exist, and will mostly just be an ill defined compilation target. B…

I do think it is "just" a matter of time/momentum. There's definitely a lot of cargo culting around bundlers ("these bundlers were gifted to us from the gods!", "these were my father's bundlers, I simply must use them!") and there's a lot of developers who "love" scaffolding and boiler plate that are just going to blindly do whatever `create-react-app` or `ng new` or whatever scaffolder of the day briefly masticates then vomits out for their baby bird mouths. Those things (culture, scaffolders) all move slowly (for lots of good reasons, too) and just take time and a few revolutionaries.

HTTP/1 still isn't going anywhere, anytime soon, especially in developer tools (because for better and worse HTTP/2+ requires TLS and developer tools are tougher to build with TLS), so it's still hard to combat the cultural assertions that "bundlers are best practice" and "bundlers are required for performance". But that too is something that shifts slowly over time. There are decades of momentum behind HTTP/1.x.

There's also still so much momentum behind frameworks like React, Angular, plenty more that spent so much time in CommonJS that they still haven't yet sorted out their ESM builds. That's also something getting better with time. Especially now that Node LTS covers enough that you can take an "ESM ONLY (in Node)" approach with confidence.

As I mentioned, I've had the pleasure of working with some projects that were 100% unbundled ESM in development and then spot-bundled (often with esbuild) to highly specific sub-bundles just for Production where Production performance noted improvements. The world of ESM-first is nice when you give it a chance. It will take a bit longer to get to "ESM ONLY, EVERY WHERE", but it still seems to be a matter of time/momentum rather than a problem with ESM.

Re: CommonJS is hurting JavaScript

#114
post #4

That's all well and good, but what about those of us that already have a mountain of Jest tests with mocks that aren't supported in ESM mode? https://github.com/jestjs/jest/issues/9430 I've definitely worked around my fair share of CommonJS issues but until ESM "just works" I'm slightly pained by how aggressive the tone of this article is.

Jest mocking is one of the worst anti-features ever invented.

We would be much better off if it had never been created.

Re: CommonJS is hurting JavaScript

#115
post #94

Would anyone be interested in an article about the crusade to move JS to ESM? I've been considering writing one, here's a preview: Sindresorus wrote a gist "Pure ESM modules"[0] and converted all his modules to Pure ESM, breaking anyone who attempted to `require` the latest versions of his code; he later locked the thread to prevent people from complaining. node-fetch released a pure ESM version a year ago that is ~1…

This is irresponsible approach and this package should be forked by more responsible people. Person who made this change should be avoided in the future.

I'm all for ESM but alienating your own users is stupid. Create node-fetch-esm and support both versions until commonjs popularity would be low enough to be dropped.

Re: CommonJS is hurting JavaScript

#116

Does anyone have a detailed understanding of why CommonJS (and its async incarnation, AMD) were not adopted by browsers? I do much like the `import` syntax personally and its a little cleaner to read, but CommonJS and AMD were the undisputed winners of the module format until ES Modules were born. Not that I have a problem with ES Modules, I don't, however I am interested in what was so insufficient about the precedi…

> and its async incarnation, AMD A bare-bones implementation of AMD could be put together with less than a kilobyte of JavaScript (this is what we used at Mozilla for a minute circa 2012). Meanwhile, the ECMAScript folks were working on ES6, which was going to have a module system. Why would the browser build in support for a highly-opinionated system that you could implement yourself so trivially, all while a TC39-b…

> Adding promises later would be challenging and leave technical debt.

I wrote an "aio loader" many years ago that can load (in the browser) AMD/CommonJS/node or just "include this script in your html" dependencies that asynchronously loads dependencies (and their own dependencies) with support for use via plain `require()` without callbacks, `require(foo, foo => {})` callback support, and even dynamic async loading (`var App = await requireAsync("foo")`).

I never published it publicly (it's just ticking away on our production sites) but I was motivated to push it to GitHub just now [0].

[0]: https://github.com/mqudsi/loader

Re: CommonJS is hurting JavaScript

#117

Earlier quoted context omitted.

FWIW they did it[0]. Alameda is promise based AMD from the same folks that were key in AMD being successful when it was so successful [0]: https://github.com/requirejs/alameda

Alameda does a great job of explaining why you can't just slap promises on something: it breaks the semantics of what `require()` returns. `require('foo')` returns foo, maybe. `require(['foo'])` returns `Promise `.

That's correct. For my own library (see sibling comment above) I started off with a single `require()` entry point that can be used to load a dependency, load a dependency and invoke a callback, or asynchronously load a dependency (e.g. return a promise) but then changed it to two separate functions (everyone's favorite `require()` plus an async version very cleverly named `requireAsync()`).

Re: CommonJS is hurting JavaScript

#118
post #94

Would anyone be interested in an article about the crusade to move JS to ESM? I've been considering writing one, here's a preview: Sindresorus wrote a gist "Pure ESM modules"[0] and converted all his modules to Pure ESM, breaking anyone who attempted to `require` the latest versions of his code; he later locked the thread to prevent people from complaining. node-fetch released a pure ESM version a year ago that is ~1…

I mean, I took Sindre's move to ESM-only publishing as his own choice as the author and maintainer of his own OSS packages. In the spirit of OSS, he doesn't need to justify the choice, it's good enough that as the author he's making it. The previous CJS versions are still published, and anyone can fork the modules if they want to take on the maintenance burden of the CJS version.

That preference has had an impact on the Node ecosystem at large, given how prolific an OSS contributor Sindre is, but IMO that influence has been earned by the large body of work he's contributed.

Re: CommonJS is hurting JavaScript

#119
Today I came across a dilemma. I wanted to somehow stub or fake Azure's Service Bus. There's no official way to do it. So, I came up with an idea to overwrite its implementation with my own, by mapping @azure/service-bus to my own class in tsconfig.json, no luck, because the framework that I use is using Webpack under the hood, so I would need to create a plugin, rule, whatever, to make it work, but I didn't want to write a specific configuration just for Webpack.

Instead, I had another idea: to import @azure/service-bus dynamically, using ES dynamic `import`, in place of static imports. But, since I'm using Node.JS, I have to set the package.json type to module, so I can use top-level `await`, with dynamic `import` to import, with the help of a ternary, the correct implementation on the fly.

I had a extremely bad experience trying to convert a CommonJS project to use ES Modules before. So I did not go through with the plan.

Finally, after spending some time trying to not use CommonJS I gave up, and in place of dynamic import I used the "good" ol' `require()`, ending up with something like this:

    const { ServiceBus } = (isDev ? require('./my-service-bus') : require('@azure/service-bus')) as import('@azure/service-bus');
.

And that was that.

Project maintainers have to make ES Modules practical before it's pretty.

Re: CommonJS is hurting JavaScript

#120
The problem was never CommonJS. The problem was never ESM.

The problem has always been, and continues to be, stubborn backward compatibility. Node is making the same mistake that Microsoft made with Windows, that Apple did not make with OSX - rather than letting go of a system that's been outgrown and forcing the userbase to grow, they cling to the old way and the old API, allowing it to ferment.

This is the fault of the team working on Node and leadership making poor choices, including TC39.

Post reply on HN