When you come from languages like C++ and Java, one of the first things you can observe in JavaScript world is an absence of robust language built-in modular approach which is ready-to-use. ES6 resolves this but it will take some time until it is supported in current browsers so it’s currently more or less on the paper.
Writing module in JS
One aspect of writing modules is to structure and isolate private stuff from public API. We can do something like that:
// lib.js
var MyModule = (function() {
// private
var localVar = "this is internal stuff"; // public
var exports = {};
exports.foo = function() {
console.log("foo");
}
return exports;
})();
// app.js
MyModule.foo();
This is more or less something like static class in some other languages.
It doesn’t really solve proper context and isolation of modules, dependencies and name-spacing which are quite critical because everything is global here.
CommonJS
CommonJS basically utilizes this approach above with adding “require” function for modules loading. Then we have these major building blocks for JS modules:
- “require” function for modules loading
- “module.exports” variable providing exported API
Let’s assume we have again two JavaScript files, lib.js - providing a function that should be “imported” and app.js as the API consumer.
// app.js
var lib = require('./lib');
lib.myFunction();// lib.js
module.exports = {
myFunction : function() {
console.log("my function called");
}
}
When we take a look we can see, there is require function undefined here.
However this works in node.js as it has out-of-box support CommonJS-like modules but for browser we will need to use browserify or some other facility as browser doesn’t know anything about “require” and this format of modules. So let’s pack this with browserify to “fix” it. If you don’t have it installed, install it as a “global” module.
npm install -g browserify
Now we create bundle. We just need to give a root app.js to browserify as it will take care of all API that is used internally.
browserify app.js -o bundle.js
Now bundle.js is all-in-one bundle with all needed parts ready to be used directly in browser.
<!-- index.htm -->
...
<script src="bundle.js"></script>
...
Now we have fully operational module code in browser environment.
If we load index.html into a browser, we will see “myFunction” properly called in browser console. On top of this we can simply use additional node js modules installed by npm.
This is basically how we can use CommonJS modules in a browser.
However CommonJS is not the only way. There are also AMD modules and also already mentioned ES6 modules. AMD modules seem to be quite marginal and ES6 are not yet natively supported but you can make it working with for example Polyfill loader. My impression is that so far CommonJS / node.js modules are “the standard” way to go for now at least until JS world fully adopts ES6 way of modules properly.