Hacker News new | past | comments | ask | show | jobs | submit login

Commonjs is synchronous. If you used it in the browser, it would block the main thread each time you required a module.

That's bad.




ESM has dual syntax for static and dynamic imports too.

What I am saying is that

import Foo from "foo"

could be sematically equivalent to

const Foo = require("foo")

and

const Foo = await import("foo")

could be semantically equivalent to

const Foo = await Promise.resolve(() => require("foo"))

if tc39 designed ESM import spec with CJS compat in mind.

It is fully possible to introduce additional syntax while not breaking the ecosystem.


CJS makes an assumption that all of the main body of a module is synchronous including its imports and that the main body of all of its imports also ran synchronously prior to the main body of that module. A lot of CJS modules are built around side-effects during module loading, built on assumptions from the way that Node especially synchronously loads everything, that break in any attempt to make the process asynchronous. It's not just a matter of syntax sugar, it's a trouble of bad assumptions and presumptions in the CJS format itself that browsers have no way to paper over (but bundlers can fake by putting everything in the same file). Loading a new file is always an asynchronous operation in a browser. CJS has never supported that. Those problems were known at the time when Node picked CJS. (AMD was the competing format that worked in browsers. AMD had its own problems and was a pain to work in without tools like Typescript, but it was compatible with browsers. CJS never was. ESM imports are backward compatible with AMD imports but because AMD is mostly a dead format in 2023 no browser today actually implements the shims to support that, but they were on the table for a long time and can still be ponyfilled if anyone is crazy enough to have an AMD codebase in 2023 that didn't switch to a CJS-based hodge podge in Node at some point in the last decade and that they can't all-at-once migrate to ESM. Which in my experience mostly just describes what's left of Esri's over-reliance on Dojo's AMD loader for ArcGIS JS and just about nothing else in the wild in 2023.) This mess is all Node's fault and it should have never picked CJS in the first place, that was always the losing horse.

(Hypothetically there might have been a place and time in CJS history to force CJS require() to always return a promise and module.exports to always take a function that returns a promise and that hypothetical version might have been compatible enough to import directly from ESM. Nobody actually wanted that hypothetical "ACJS" so it never existed. ACJS could have at least met browsers half-way and might have made the transition less overall painful.)


Nobody is advocating for synchronously importable modules in browsers. Also, people had already written support utilities like require1k [1] to support cjs in browsers. We don't necessarily need a full bundler - we only need a module analysis step between parse and execute which a native js engine is quite well positioned to facilitate.

Having said that, the fact remains that vast majority of pain points that people who actually need to maintain isomorphic libraries face today have nothing to do with synchronous vs asynchronous nature of cjs and esm modules.

It is the myriad pointless nuances like default export, namespace imports etc. that are sources of biggest headaches in day to day work. In cjs there is a simple model that a module exports an object and while importing you import that object. Instead now we have a situation where we need to deal with:

    export default { 
        foo() {...} 
    }
is not same as:

    export function foo() { ... }
and

    import Foo from "foo"
is something different from

    import * as Foo from "foo"

Plus the additional complexities introduced by import bindings being live etc. are just annoyances that one has to deal with over and over again every time module interop is involved.

[1] https://github.com/Stuk/require1k




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: