Hopefully by now, you’ve settled on a module format. If you haven’t, then please read my prior article for some information on that topic. You cannot select a module loader unless you know what sort of modules you are writing. If you want the short version:
- ECMAScript 6 – use the babel-core engine to compile to the AMD or CommonJS format
- AMD – good for browser applications
- CommonJS – good for server applications
What we will look at today is the various major module loaders and how to use them in the browser. If you are using NodeJS, then the CommonJS loader is built-in, so you don’t need to worry about it.
If you are using ECMAScript 6 then use the babel-core compiler to compile your modules into an equivalent AMD or CommonJS format, depending on requirements.
What to look for
There are only 4 things to look for in a module loader when you are starting out.
- Support for Module Format: Your chosen module loader needs to support the modules you are going to write plus the modules in libraries that you need.
- Asynchronous or not?: Module loaders are only really used in the browser (node has its own loader support for CommonJS). If you are a multi-page application, then you get major benefits from caching by using asynchronous loading. If you are a single-page application, it’s likely less important but caching is still good. I recommend an Asynchronous loader.
- Support for Gulp and Grunt?: If your module loader requires pre-processing of the modules, then it should support grunt or gulp – your chosen task runner.
- Support for loading plugins: Sometimes you want to lazy-load your CSS and HTML as well, mostly so you can componentize your CSS and templates. If your module loader doesn’t support it, you can’t have it.
I’ve listed the major candidates I found out on the Internet. Note that ECMAScript 6 support is not in there. Babel-core will compile your ES6 modules to one of the formats (AMD or CommonJS), then you use a module loader as normal. Just look for the requirements.
RequireJS was the original standlone module loader and is still probably the most used module loader out there today. It supports AMD natively. You can wrap your CommonJS modules in a simple wrapper. It’s got lazy (asynchronous) loading and it doesn’t need any pre-processing of the modules (beyond the ES6 to ES5 conversion that babel-core does). It also has a third-party plugin for CSS. This is a really good choice if you are just starting out and don’t know what else you need out of a module loader.
Downsides are few. However, there is a major one. If you are using certain frameworks (Angular is a culprit here) in a single-page application, then using RequireJS is more complex than it needs to be. In this case, you may want to re-visit the module loader topic based on the recommendations of that framework.
Of course, this gets rid of all the benefits of lazy loading – most of which you don’t want anyway. The one you do want is when you have that large charting library. For that purpose, Browserify has a require functionality that is in CommonJS. The problem will be, of course, that now you have to mix require() (the old syntax) and import (the ES6 syntax) in your code, so you lose the benefit of writing code in ES6.
Browserify does get around the complexity described around AngularJS. If you are or are intending on using a framework like Angular, you may want to check out Browserify in that context.
Webpack is another bundling application, much like Browserify. It has native support for AMD formatted modules (which isn’t to say it lazy loads them – just that it supports them). You can use loader plugins to pre-process files, so you can distribute ES6, Coffeescript or the like if you include their preprocessors as well. You can load external libraries, just like Browserify, although implementing lazy-loading is much easier. It has support for grunt and gulp, just like Browserify. Basically, it’s Browserify plus native support for AMD formatted modules and lazy loading.
Yes, there are a whole load of other dynamic or asynchronous module loaders out there. None of them have a following like the ones above. Here is a list for investigation purposes.
- curljs (deprecated)
- lazyload (abandoned)
- RaveJS (in development)
- yepnope (abandoned)
Geez – come on guys. We don’t need more module loaders!
I mentioned in a prior article that I like ECMAScript 6, so I’m going to compile my code to another format anyway. That format is AMD as more module loaders support asynchronous loading using AMD than the others. It’s hardly a ringing endorsement, I know, but this area is likely to be in flux while the browsers start supporting ECMAScript 6 anyways.