Live data from Hacker News

CommonJS is hurting JavaScript

deno.com

21–30 of 134 posts

Re: CommonJS is hurting JavaScript

#21
post #2

[flagged]

Every time this is mentioned, the person is heavily downvoted.

But if you were here in the 2000, that's exactly what happened.

In fact, this very article starts with "JavaScript, the undisputed king of web development, is being sabotaged — not by a rival language or a revolutionary new technology, but by its own baggage from the past.". That's the first sentence.

Nobody wanted to work with JS, it was used to make snowflakes on your home page on Xmas at best.

Then things like gmail happened (using GWT!), and the web became the most awesome platform in the world. By then it was too late, JS was the de facto language of the coolest tech of human history.

It was such a trap Google spent billions and hired the best minds out there to make chrome, with a VM that could execute it fast enough, so the company could make its vision happen.

At the time, JS was a nuisance and an embarrassment, something we had to deal with. The "good parts" was the bible because it's a language you could only use if you ignore half of it.

Case in point, the most popular JS techs created after that existed precisely to avoid writing ES5. Like coffeescript, babel, webpack, etc.

JS is a decent language now, because the community invested so much into it. Provided you use tooling. A lot of it.

But that's not how it started. We were forced to use it, and had to spend considerable resources to make up for how bad it was.

I've yet to met anybody who knows Python/Ruby/C#/Java/Rujst/Go and JS to chose JS outside of the web. Because there, we have the choice.

Electron, unfortunately, might take a chunk of that choice, because once again, the browser platform is that great.

Re: CommonJS is hurting JavaScript

#22

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…

I can speak to the one listed in the article: "difficult to tree-shake, which can remove unused modules and minimize bundle size."

This is because of a much deeper issue: static analysis is highly complex with the near-free-for-all that is CommonJS require & module.exports syntax. ES Modules is stricter and much easier to statically deal with.

At a high level, why? You can throw just about anything in an exports.module statement, and the syntax to "require" it also has a lot of leeway. You can actually see the code for this in the Node codebase--module resolution is handled in javascript @ /lib/internal/modules/cjs/loader.js vs /lib/internal/modules/esm (heads up, both approaches are a Lot to grok)

Understand that with the CJS approach, you can dynamically export modules at runtime under whatever name you wish, with whatever value you want, which may even include dynamic require statements themselves. Nightmare for static analysis.

It makes a lot more sense if you try it for yourself. Build a module resolution algorithm including: determining all the imports, all the files those imports are from, mixing with 3rd party and local imports, and building that chain recursively.

You can do it, but the edge cases surrounding CommonJS make it super difficult. I'd go so far as to say it's basically impossible to get 100% success in all the desired scenarios without directly invoking the code.

Re: CommonJS is hurting JavaScript

#24
I’ve managed several open source projects through their transition from CommonJS to ES modules and the least interesting part was the server-side of the equation. More often, the most exciting, and most excruciating aspect is wrangling TypeScript to emit browser friendly module paths. Anything short of relative paths everywhere won’t cut it, and TypeScript really doesn’t like to emit file extensions when TSX is involved.

There’s also some unsolved mysteries surrounding the path resolution defined by a package.json file, but at least there’s now a proper way to have a package use project root relative imports. Things usually go well until you get back to the browser, which now needs an Import Map to bridge the two worlds. I still haven’t figured out how to wean off NPM either since all the magic compiling CDNs use its namespace to create browser friendly bundles…sort of where we started from.

There’s a few foot guns on bundles now too, like deduping React so hooks work, along with some surprises about modules being stateful. And while Deno is pushing the dream forward, I can’t help but feel they compromised the vision too far for Node compatibility. At this rate, I could see Node v30 being a merge of the two projects.

I’m honestly happy it’s all coming along. It seems like this is JavaScript’s Python 3 moment, where everyone has to rewrite code to slightly new paradigm for the next generation of apps to fully appreciate. I’m most thankful for async imports operating like ordinary Promises!

Re: CommonJS is hurting JavaScript

#25

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…

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 future of JavaScript lies with making each source file a valid, correct piece of JavaScript. When each source file is valid and correct, and doesn’t need to be preprocessed in order to work, your tooling will work a lot better.

The browser authors know you can’t un-ship JavaScript features. ES6 import/export is damn good stuff, and people in the browser aren’t saddled with some weird compatibility shim like AMD.

The adoption of ES6 modules in the client-side landscape has far outstripped its adoption in Node.js. I honestly can’t wait for require() to die, in both its cjs and AMD variations. The tooling support for ES6 modules is miles better.

Re: CommonJS is hurting JavaScript

#27
> I really think that the needs of server side code are different enough than the needs of client side code that we’re better off drawing from Python and Ruby than from Dojo and jQuery.

This sentence sounds ok until Python and Ruby are held as the apparent gold standard of server development. That's not really the case, I think?

Re: CommonJS is hurting JavaScript

#28

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 packages from URL sources. Since the syntax cannot be parsed efficiently, runtimes like Deno and Bun would have a much harder time fetching resources from URLs prior to running the code. The idea here, IIRC, was to eliminate the install step, the need for centralization on a single package manager and registry, and a general "non-Web" approach to the idea of packages and modules in JS.

I believe the `import` syntax was chosen to allow transitions away from `require()`, so that your programs wouldn't just stop working if ESM was enabled.

Re: CommonJS is hurting JavaScript

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

That’s mostly because of how Jest absolutely brutalizes the Require stack. It’s a problem with Jest AND CommonJS, not ES Modules.

In fact it’s a very illustrative example of why CommonJS should be taken out back and shot.

Re: CommonJS is hurting JavaScript

#30
post #27

> I really think that the needs of server side code are different enough than the needs of client side code that we’re better off drawing from Python and Ruby than from Dojo and jQuery. This sentence sounds ok until Python and Ruby are held as the apparent gold standard of server development. That's not really the case, I think?

Compared to JS it's hard to throw a rock and not hit something better than it...

But I can confirm deploying Python or Ruby apps is generally bigger PITA.

Post reply on HN