Menu

Introduction to the Jspm package manager and the SystemJs module loader

Last Updated: 09 June 2017local_offer

This post was updated 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

Why is modularity important in Javascript

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

Conclusions

Using ES6 modules today

One of the main goals of ES6 modularity is to make it really simple to install and use any Javascript library from anywhere on the Internet (github, npm, etc.). Only two things are needed:

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.

Why is modularity important in Javascript

Modularity is important in Javascript by the same reasons it's important in any other language:

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:

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:

babel-core@5.8.25
babel-runtime@5.8.25
core-js@1.1.4

Creating a ready to use bundle with Jspm

Jspm not only installs dependencies, but it also knows about module loading and bundling. This might seem odd at first, as those tasks are usually handled by different tools. But the result is very powerful: we can create a ready to use javascript bundle with one command:

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 src/main.js. Jspm will follow the imports on that file and recursively bundle all the needed Javascript files.

The result is a ready to use bundle that can be used on a web page simply like this:

<script src="bundle.min.js"></script>

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

Having said all that, the tendency is that npm becomes more and more the package manager for all Javascript in general, including for the frontend.

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!

Conclusions

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.

Related Links

We will be publishing soon a course on SystemJs and the SystemJs Builder at the Angular University.