CommonJS and the History of Javascript Modularity

Lisa Berteau Smith
3 min readJul 8, 2019

--

It may be hard to picture a time before NodeJS, but an even darker time was before CommonJS. Not exactly sure what CommonJS is? Well let’s start in the middle, shall we?

CommonJS was started by Mozilla engineer Kevin Dangoor in January 2009 to address the lack of commonly accepted modularity practices in Javascript programming. How did they achieve this?

“The CommonJS group defined a module format to solve JavaScript scope issues by making sure each module is executed in its namespace. This is achieved by forcing modules to explicitly export those variables it wants to expose to the “universe,” and also by defining those other modules required to properly work.”
— Webpack Docs

Why modularity? Well, there are four significant advantages to modularity. The first is reusability. Modules allow code to be imported and used in other modules, or several modules can be exported into a package and installed in different environments. Next, modules grant us composability because the code can be explicitly defined and quickly deleted. Working in modules isolates sections of methods so work can be built (and then repaired) separately. Several developers can work on isolated modules independently and avoid merge conflicts. Finally, modularity provides organization to a program due to natural separation points. Writing extensive amounts of code and variables is less prone to error with modularity because it doesn’t pollute the global namespace and avoids collisions.

A long, long time ago, before modularity, if developers wanted to make code from other files available to each other, they would access the variables and functions from the global window object. Then, to compile all the code in the browser, every file is included with script tags in the index.html file. This system isn’t very reusable, and the majority of the program is in the same scope. But there had to be a better way.

Along came Immediately Invoked Function Expressions. IIFE’s are anonymous functions that are wrapped in parentheses. Then, just like any other function, to invoke it, we add another pair of parentheses to the end of it. IIFE’s clean up the global namespace a great deal, but script tags are still required. There has to be a better way!

Finally, we have CommonJS. CommonJS makes each file its module. Then each file explicitly defines imports (or dependencies) and explicit exports which will be available to any other file. Take a look at the explicitly defined exports below.

// customers.jsvar customers = ["Rachel", "Galen", "Charles"]

module.exports = {
getCustomers: function () {
return users
},
sortCustomers: function () {
return users.sort()
},
firstCustomer: function () {
return users[0]
}
}

To keep things simple, any information regarding the module can go on the object. Then, anything we want to export from a module we can stick on module.exports! Now, look at how we can import.

// acounting.js
const customers = require('./users')
customers.getCustomers() // ["Rachel", "Galen", "Charles"]
customers.sortCustomers() // ["Charles", "Galen", "Rachel"]
customers.firsCustomer() // ["Charles"]

If you’ve used Node before, you’ll recognize the CommonJS standard. Node uses a variation of this specification. However, unlike Node, browsers don’t naturally support CommonJS. Another downside is CommonJS loads its modules synchronously. Bah! All those benefits and still two problems. We can fix this by using Module Bundlers like Webpack. If we ignore complexity, a module bundler essentially turns your code from multiple files into one.

payroll.js ------> |         |customers.js ----> | Bundler | -> bundle.jsaccounting.js ---> |         |

After all the files are bundled into one, what then? How do they do it? Well, with one great big IIFE!

In conclusion, CJS modules are reusable code made available for dependent files. It achieves all our goals of organized dependency management, separation of concerns, isolation, and composability. Although much has changed since 2009, CommonJS paved the way for modern modularity practices that are a requirement of any program written today.

--

--