The Basics of CommonJS
With CommonJS modules, every file explicitly states its dependencies, letting the tooling figure out what the ordering is. Using CommonJS modules also keeps us from polluting the global namespace which enables engineers to now write and distribute high quality libraries with shared dependencies.
Every CommonJS module is given two main globals:
Require Caches Modules
From Good Eggs: “An important behavior of
require is that it caches the value of
module.exports and returns the same value for all future calls to
require. It caches based on the absolute file path of the required file.”
You can see that
require is returning the same reference for each call.
Different Exporting Styles
There are a few different ways that you can and should export from your module. They are good for different times and different uses. Exporting objects and classes are the most common patterns we use.
- Monkey Patch
You can also use this style to return a collection of functions that don’t share any state:
If you want to have multiple instances with shared state, then you should probably be exporting a class.
require caches the value assigned to
module.exports, all calls to require the module are given the same reference. This makes creating a singleton extremely similar to creating a class. We simply return a
new instance of our class.
Warning! This pattern is dangerous and should rarely ever be used. Monkey patches are modules that modify global state. You may also hear them called shims.
This is typically a very dangerous pattern to follow because it breaks the dependency graph of the application. Depending on where
shim is required we could be changing the behavior of our application.
This is typically only a reasonable thing to do if you are importing polyfills at the very top of your application. This will have pretty much the same behavior as saying:
Public / Private State
One of the great parts about CommonJS is that everything is private except for what is set to
module.exports. That means that we can separate our public api and private helpers quite easily:
Simply don’t export the things you don’t want to have be public, and they won’t be accessible!
Specifying dependencies using CommonJS enables us to work on individual units of code and better reason about the environment they are being run in. By explicitly stating the dependencies for each file we don’t need to maintain an ordered list of our files and can instead let our tools figure that out for us.
Browserify and Webpack are both bundlers which can be given a CommonJS module. They will walk the dependency tree of
requires and bundle all of the files’ dependencies into a single file (generally) that is then meant to be used on websites. Ben Clinkinbeard has written a great post explaining how Browserify works with CommonJS.