The Popular module formats/loaders
The CommonJS loading scenario is relatively straightforward because the modules/files are loaded directly from the local file system. It is naturally a sync operation. In fact, in node.js, it is just a require() function call, as shown below:
The AMD format, however, is a bit different. In a browser world, loading resources, e.g. scripts from an Internet server should always be asynchronous considering the IO latency. Also, the module codes need to be wrapped, usually in IIFE format, otherwise, they are all gonna be globals. Here is an example:
In order to load the scripts, a browser context aware loader is needed. RequireJS was the de facto AMD loader. It is a bit outdated now. I’ll show you why later. Today we have the new cool kid called systemjs. We’ll get back to systemjs’ details later in this post. Based on the above code snippets, we can see there are some clear pros and cons for each format.
The ideal module solution, ES6/ES2015
In the above code snippets, I’m also using the new ES6 class syntax which is another very nice feature. Back to the point of module format, you can see now we have a much cleaner way of defining modules and their dependencies. There is no need to wrap things in an IIFE anymore. There is also no need for the magic exports holder object either. With all these good aspects, what really left is that we need a loader to make this module format works. And the loader better work in a much less overhead way.
The systemjs loader
Systemjs is a loader that can support the new ES6 module format, perfectly. In addition to that, it supports not only the new format, but also all popular legacy formats, CommonJS, AMD, and even globals. Isn’t it awesome? In fact, it is even more powerful, I’ll show you why in below. For a detailed demo, please see this little github demo repository.
Firstly, systemjs can load various different module formats as I mentioned above. Though in reality, we don’t usually mix too many different formats in a project. What we really want is the ES6 module format support. It is amazing to have this supported even before the main stream browsers fully support it. It accomplishes this with the help of the transpilers, the popular ones are Babel, Traceur and our beloved TypeScript. What does this mean? This means that, you can write ES6 modules today and don’t need to worry about if the browsers support them or not, because the ES6 modules will be seamlessly transpiled down to ES5 which is fully supported today by all main stream browsers. The transpilation can happen on the fly in browser for development workflow. It can also and must happen during build/bundle time for production scenarios, of course.
Thirdly, systemjs is not alone. It is accompanied by two other awesome tools, JSPM and systemjs-builder. JSPM as the name suggests is a package manager for browser scenarios, similarly as npm to node.js. With JSPM’s support, you can easily consume both well designed npm packages, and even the raw repositories on github.
Systemjs-builder is the build/bundle part of the systemjs story. Remember bundling is a way to overcome the HTTP 1.x header of line blocking issue that will eventually disappear once HTTP 2 is established by major Internet service providers. Bundling by that time will be an anti-patter that we would need to un-learn. Really the loader is the thing we are looking at and bundling is the nice necessary feature it carries to solve the reality issue. This is also the reason why I personally favor the loader concept/tool over the bundler solutions like webpack. Webpack is also an awesome tool, but I don’t see a clear future of it because it solves the problem in a not-very-correct way.
Till next time,