The rise of CommonJS
Within a week, 224 people had joined the then-called ServerJS google group, including npm founder Issac Schlueter, and Node.js creator Ryan Dahl (here’s where he introduces Node to the group). This mailing list would go on to spec out the first versions of CommonJS, the module system that became part of Node.
The proposed CommonJS syntax (
module.exports, etc.) do not look
CommonJS Google Group in 2009:
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.
In retrospect, it seems to me like the goal of CommonJS was (or at least, should have been) to discover Node, and enable what we’ve built here. Some mistakes were made, because hindsight doesn’t go in the direction you’d like it to, but overall, I think the whole CommonJS project can be considered a success.
— Issac Schlueter, comment on Breaking the CommonJS standardization impasse (2013)
Despite being the default module system, CommonJS have some core problems:
- module loading is synchronous. Each module is loaded and executed one by one, in the order that they are required.
- difficult to tree-shake, which can remove unused modules and minimize bundle size.
- not browser native. You need bundlers and transpilers to make all of this code work client-side. With CommonJS, you are stuck with either big build steps or writing separate code for client and server.
ECMAScript Modules are web-first
ES modules assume they’ll fetch data over a network rather than in a filesystem, delivering better performance and user experiences.
Now that a module loading system is built right into the language, everyone will agree to use that so we can focus our energy on higher level, more important problems, right?
Node decides to support both CJS and ESM
ES Modules and Common JS go together like old bay seasoning and vanilla ice cream
— Myles Borins, from a talk on Modules Modules Modules
(I’m from Maryland so this sounds great to me.)
Borins was one of the developers on the Node ‘modules team’ tasked with implementing ES modules in Node. Despite successfully adding ESM to Node, the team couldn’t come to a clear consensus on interoperability between ESM and CJS. Yet Node couldn’t rip out CJS since its so deeply embedded. This meant that the interoperability problem was pushed to package authors.
Here’s a snippet of a module’s
package.json needed to support both ESM and
Other module authors have found success supporting CommonJS and ESM
using dnt. Simply write your module in
TypeScript and this build tool will transform it to Node.js, emit
ESM/CommonJS/TypeScript declaration files, and a
It’s clear that supporting CommonJS in 2023 has become too big of a problem to ignore. It’s time we bury CommonJS and transition into an all ESM future.
So long and thanks for all the
We envision a future where after installing a module, developers will be able to run the code in Node.js or the Browser without requiring a build step.
— Myles Borins, The Current State of Implementation and Planning for ESModules (2017)
But with ESM as the standard and the focus shifting towards cloud primitives — the edge, browsers, and serverless compute — and CommonJS simply doesn’t cut it. ESM is a better solution for developers, as they can write browser-compliant code — and for users who get a better end experience.
Don’t miss any updates — follow us on Twitter.