This post was created on Jun 2016
In this post we will go over the current state of ES6 modularity, by learning how to use the Jspm package manager and its associated SystemJs module loader (the sample code is available here). We will go through the following topics:
- Using ES6 modules today
- The Jspm package manager and how to use it today
- creating a ready to use bundle with Jspm
- The SystemJs module loader
- Jspm vs Bower
- Jspm vs npm
Using ES6 modules today
- a single command to install the library
- one single line of code to import the library and use it
Imagine a world where you could install a library with a command like this:
jspm install jquery
And then import the library with a single line of code, and just start using it:
It turns out that this is actually possible today with Jspm and its associated SystemJs module loader, without any further tooling needed.
Note that the import above can also be done in the ES6 syntax if using a transpiler like Babel:
We will see how all this works, and how its really easy to use.
- it encourages the development of small isolated modules with clear interfaces, as opposed to large chunks of monolithic code
- it helps with testability, as modules can be replaced at runtime with mocks that implement the same interface
- it improves code maintainability, as smaller and well-isolated modules are easier to understand
Fundamental problems that Jspm solves
When projects get to a certain size, they will have to deal sooner or later with the 'dependency hell' problem. This happens when two different versions of the same library are needed at the same time.
Another problem related to dependency management is making sure we always have a valid combination of library versions, meaning that if we require a library that itself has a dependency, that transitive dependency should be downloaded and included transparently for us.
All these problems are handled transparently by Jspm: it allows multiple versions of the same package and it even supports circular dependencies.
The Jspm package manager in action
As we mentioned, in order to install a library we only need one command. Libraries can be installed from multiple sources, for example from github or npm. Let's install a couple of libraries:
jspm install npm:timezone-js jspm install github:pablojim/highcharts-ng
The installation command takes care of downloading the whole dependency tree, and copy it into the file system under the form of a versioned flat tree that looks like this:
email@example.com firstname.lastname@example.org email@example.com
Creating a ready to use bundle with Jspm
jspm bundle-sfx --minify src/main bundle.min.js
This command creates a self-executing and minified bundle, where the execution entry point is the file
The result is a ready to use bundle that can be used on a web page simply like this:
Notice that we managed to use all our dependencies without even thinking about configuring a module loader.
What about SystemJs?
Did you notice that so far the SystemJs module loader is nowhere to be seen? This is because Jspm knows about SystemJs, and will transparently install it, include it in the self-executing bundle and use it to load the entry point of the application.
This is very powerful: we can use ES6 modules in production today in a transparent way. It all just works, even in a ES5-only project (using the require syntax).
What is the SystemJs module loader?
SystemJs is a universal module loader capable of loading modules of different formats: AMD, CommonJs, globals. It works both in node and in the browser.
SystemJs is composed of an ES6 module loader polyfill and a compatibility layer that allows it to use different module formats. SystemJs can be used independently of Jspm, but the two tools are really best used together.
Using SystemJs independently of Jspm does not provide so many advantages over other solutions like Bower + Browserify or Bower + Webpack. You would still have to download the dependencies using another package manager and configure a build tool to create a bundle. Also you would need to install the module loader and learn how to configure it and use it.
With Jspm, we basically can more or less forget that there is a module loader being used, and simply use the ES6 import syntax (or the ES5 equivalent).
Jspm vs npm
More and more frontend libraries are getting published to npm with meaningful CommonJs exports, but those libraries cannot be used in node as they often require a DOM. The goal is to have a CommonJs module easily installable so that frontend libraries can be for example consumed by browserify, or even SystemJs and used in the browser instead of node. One frontend library that gets published to npm is for example AngularJs.
The npm team is planning to make npm more frontend friendly. The Angular team made or will make npm a concrete proposal for how that could be achieved.
Npm just released version 3 a couple of weeks ago and only in this latest version they implemented a maximally flat dependency tree. This is certainly a good first step to help cover frontend modularity, but Jspm has a huge head start on this and has a lot of momentum behind it.
Jspm vs Bower
Note that Bower is being slowly discontinued in favor of other package managers. Jspm and Bower were built with very different philosophies. Bower is based on the assumption that there can only be one version of a library at the same time in the browser.
Bower will download transitive dependencies into a flat tree, but if two versions of the same library are required it will ask the user which one it should choose. Bower allows saving that decision into
bower.json so that other users can have reproducible builds.
Jspm is designed for a world where developers build many small different frontend modules that get reused a lot, similarly to what happens in the npm world. To handle this, multiple versions of the same module can be loaded independently without conflict, but the user ultimately keeps control on those decisions if he wants to. SystemJs can even handle circular library references!
Jspm allows for ES6 modules to already be used today, even with an ES5 syntax if needed. Although the SystemJs module loader can be used separately, you really get the most benefit if you use it transparently via Jspm.
Conceptually and feature-wise, Jspm and SystemJs are way ahead of other similar tools. Not only Jspm/SystemJs have more features but they are actually much simpler to use, especially in the self-executing bundle scenario presented above.
We will be publishing soon a course on SystemJs and the SystemJs Builder at the Angular University.
The following post provides an in-depth comparison of Bower, Jspm and npm - Is Bower dead? What is JSPM? Npm for client-side?
This talk from the creator of Jspm, SystemJs and the ES6 module loader polyfill Guy Bedford provides an in-depth dive into Jspm and SystemJs - Package Management for ES6 Modules
Also, the code in this post can be found here, with running instructions for seeing Jspm in action for the first time.
The Angular framework works with all module loaders, but you might have noticed that many of the examples that we see out there use SystemJs.
If you want to learn more about Angular, have a look at the Angular for Beginners Course:
Other posts on Angular
If you enjoyed this post, here some other popular posts on our blog:
- Angular Router - How To Build a Navigation Menu with Bootstrap 4 and Nested Routes
- Angular Router - Extended Guided Tour, Avoid Common Pitfalls
- How to run Angular in Production Today
- How to build Angular apps using Observable Data Services - Pitfalls to avoid
- Introduction to Angular Forms - Template Driven, Model Driven or In-Between
- Angular Universal In Practice - How to build SEO Friendly Single Page Apps with Angular
- Angular ngFor - Learn all Features including trackBy, why is it not only for Arrays ?
- How does Angular Change Detection Really Work?