Webpack vs JSPM

This is a just an overview of two of the most commonly used tools for writing code using ECMAScript2015 modules. They also work if you want to use CommonJS (Node.js modules) or AMD (RequireJS).

Paulo Esteves
8 min readMay 24, 2016

Browserify has been the go-to tool for bundling modular JS for quite a while. However, in the past couple of years, two different tools have been gaining a lot of traction, Webpack and JSPM.

Here’s a summarized version of what lead me to modular JS, in the first place:

I started with Bower and people all went “You know what? You should just use Browserify”. So I started checking Browserify out and people all went “Guess what? Webpack is better than Browserify”. And so I started checking out Webpack and people be like “Sup, son? Those tools are too messy, you should try JSPM”. Maybe they didn’t actually talk like that. Memory is a tricky thing.

Just to be clear, most of these tools work very differently:

  • Bower/Gulp are used for the typical script concatenation workflow.
  • Browserify and Webpack are bundlers that take modules of JS and create a giant JS file while keeping each module’s namespace separate.
  • JSPM simulates the common way browsers will work in a few years. Modules are loaded in browser, as necessary.

Needless to say, the changes in how the web works will be pretty revolutionary.

There is a lot of info about browserify, so I’ll leave that one out. Let’s start with JSPM, which was the first one that I tried out.

JSPM

JSPM did seem like it was the ideal tool. You could start almost immediately, there was no build step, and the code would be ready for when browsers support ES2015 modules.

JSPM is actually a bunch of tools put together that constitute a framework for building web apps with modular JS. It’s clear that the goal of its creator, Guy Bedford, is to make it as simple as possible, so that developers don’t have to worry about configuration and actually develop their apps.

So, the actual framework is:

  • JSPM — a package manager that uses npm and github to install external packages (replaces bower).
  • SystemJS — a library (from the same author) that loads the modules when the page is opened and, from then on, loads new modules as required. This works without a build step, so you don’t actually have to create a giant Javascript file. The code is also transpilated in browser.
  • It also has a bundler (like Webpack/Browserify), that ends up being optional (or is it? More on that below)

Now, if JSPM already loads everything in browser, then why the bundler? This is why this really cool tool ends up being not as useful as it originally sounds.

Being able to skip a build tool is incredibly cool (feel free to use this slogan, Mr. Bedford). However, it comes at a cost, and it’s pretty steep: loading a page is really slow.

There are 2 causes for the slowness:

  • There aren’t many servers using HTTP 2, which allows multiple HTTP requests to happen concurrently without any problem. With the current version, HTTP 1.1, each extra file being loaded at the same time, will increase loading times. With complex apps, this will mean that you can quickly start having dozens of files that will open in the beginning, which ends up being very problematic. However, this is a problem that will go away eventually as HTTP 2 becomes more prevalent.
  • Transpilation — A lot of ES6 features aren’t supported by current browsers, including modules. And even if they were, converting would still be required to allow compatibility with older browsers, at least for several years. To solve this, JSPM ends up transpiling everything in browser.

The convenience of skipping a build tool, means that usually you would have to wait at least a 2 or 3 seconds to load the page. That is usually tolerable in development, but with increasing complexity, loading times also increase. That and the fact that you wouldn’t actually know how long your page takes to load may feel weird during development, since you probably would prefer to always experience the closest to the actual user experience while coding.

So, JSPM has a bundler to make the app load fast in production. However, during development, a lot of people also end up using it with incremental builds with either a plugin or the watcher feature that is available in JSPM 0.17.

Webpack

Webpack is just a bundler, similar to Browserify. But a very powerful one. Apart from bundling, it also has some pretty cool features like hot module replacement. A really cool thing about it is that it can almost completely replace gulp as well. You can use it to import css written in sass or less, you can use linting tools, move files, etc. The main downside of it is that, to use these things, you’re gonna have to be really patient. Webpack configuration can be traumatizing.

Which to use?

Like everything, it will depend on the situation, however I do feel like there is a clear winner for the vast majority of cases and that is Webpack.

It was a bit hard to admit this to myself, because JSPM is a really cool and smart tool, and I love the fact that clearly, one of its goals is to make things really simple for developers, so that they can actually develop.

So, like many people, I started with JSPM, but ended up migrating to Webpack.

So here’s how it went:

Basically I started building a small app that used ES6 (obviously), Angular 1.x, SASS, jshint, PostCSS, Autoprefixer and Bootstrap. Some of these things were total overkill given the simplicity of the app, but it was a good way to test how well JSPM/Gulp and Webpack worked with them.

I checked out both tools, choose JSPM and started learning it. JSPM’s documentation is very clear and easy to read. Try reading a couple of documentation pages for Webpack and you’ll feel like an idiot.

I then started building the app and I didn’t really mind the 2/3 second loading time all that much. I felt that everything was working pretty well. And indeed, I built most of the app using JSPM and Gulp without a problem.

Now, in production I really had to bundle everything. So I did. But then I realized that would have to configure some extra things to use bootstrap properly so that the fonts would be loaded from the bundle.js file. Then I started using the bundler’s watch mode during development and everything was running smoothly and I was happy.

However, after a while I realized something: to have a nice workflow with JSPM, I ended up not using the features that make it so special. That’s when I realized I shouldn’t be using JSPM, when I noticed that I was doing exactly what I would be doing with Webpack, expect that Webpack has some extra features, like the ones that replace Gulp and works with a less amount of files and folders.

So I moved to Webpack. And boy, that was frustrating. I tried to make everything work without Gulp, but that was really, really tough. Making it work with bootstrap was a nightmare, because it also had to load the fonts.

The problem is that the configuration is very confusing, definitely not intuitive and the documentation if pretty bad as well. However, there is a pretty good community, that makes up for that.

Here’s my config file for that project:

var autoprefixer = require(‘autoprefixer’);
var ExtractTextPlugin = require(“extract-text-webpack-plugin”);
var path = require(‘path’);
module.exports = {
entry: ‘./app/main.js’,
devtool: ‘source-map’,
output: {
path: path.join(__dirname, ‘./dist’),
filename: ‘bundle.js’
},
module: {
preLoaders: [{
test: /\.js$/, // include .js files
exclude: /node_modules/, // exclude any and all files in the node_modules folder
loader: “jshint-loader”,
}],
loaders: [{
test: /.js$/,
exclude: /node_modules/,
loader: ‘babel-loader’,
query: {
presets: [‘es2015’]
}
}, {
test: /\.css$/,
loader: ExtractTextPlugin.extract(‘style’, ‘css!postcss’)
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract(‘style’, ‘css!postcss!sass’)
}, {
test: /\.woff(2)?(\?v=\d+\.\d+\.\d+)?$/,
loader: “url?limit=10000&mimetype=application/font- woff&name=fonts/[name].[ext]”
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: “url?limit=10000&mimetype=application/octet-stream&name=fonts/[name].[ext]”
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: “file?name=fonts/[name].[ext]”
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: “url?limit=10000&mimetype=image/svg+xml&name=fonts/[name].[ext]”
}
]
},
postcss: function() {
return [autoprefixer];
},
jshint: {
esversion: 6,
emitErrors: false,
failOnHint: false,
},
plugins: [
new ExtractTextPlugin(“./bundle.css”)
]
};

What this does:

  • Bundles JS modules
  • Does JS linting
  • Converts ES6 JS to ES5 using Babel
  • Creates source maps
  • Allows .scss imports, converting them to css
  • Uses css autoprefixer in the css imports
  • Bundles css into one file
  • Imports fonts (for bootstrap)

Now, the important thing is: it works. And it does a bunch of stuff that JSPM wouldn’t be able to do (JSPM also has a few plugins, but they are more limited). However, the configuration file is horrendous. Although part of it comes from poor design, a lot of it is just to allow Webpack to be highly customizable. Webpack feels Frankensteinish. It looks like crap and may be scary, but it is nonetheless very powerful.

You have to be willing to spend some painful hours setting everything up. Most of what you need, you can just copy from the plugins’ docs or tutorials. After a while you can pretty much always use the same config file.

By the way, one thing that bothered me a lot with Webpack, was the fact that at first, the incremental build feature didn’t work, because I had a parenthesis in my file path. I had to edit the name of a folder to make it work. This happened to me with Windows 10. Now, I do know that Webpack is not all that optimized for windows, but that’s the kind of bug that could make some people waste several hours (like me) trying to figure out the problem while assuming it’s related to the configuration.

Once everything is set up, with the watcher on, you could almost forget that a tool is being used in the first place. That doesn’t happen with JSPM unless, like previously mentioned, you use workarounds that pretty much make it do the same thing that Webpack would do anyway.

One pretty good advantage of JSPM is that the bundler uses Rollup. Rollup is also a bundling tool that optimizes files better than Webpack and Browserify, by ditching a lot of unused code that they wouldn’t. However, the smaller file size, doesn’t really make it up for JSPM’s flaws.

The future

As of the moment of writing, both of these tools have beta versions with a lot of new features coming up.

JSPM introduced incremental builds (currently, you have to use a plugin to have that), which is awesome, but again, it serves the ironic purpose of allowing you to avoid using what makes JSPM so special.

Webpack introduced, among other things, reading ES6 modules natively aaaaaand SystemJS support, which again, seems to mean that Webpack will always be a bit ahead. Also, even when browsers support ES6 modules natively, conversion to ES5 will still be required for a few years, due to browser compatibility.

With a much larger community supporting Webpack, it’s not only a safer choice, but clearly the best one for all but a few use cases.

When would JSPM be a better choice?

You should use JSPM if you want to start experimenting with ES6, if you want to write a quick prototype of a project or if your app is really simple and quick to build. Even then, if you start having webpack config files for common situations ready, it would actually be faster using Webpack.

I don’t like the way webpack neglects the importance of intuitive configuration and clear documentation and I deeply admire the work that has been done with JSPM, but if you actually just want to work and write code, chances are, you will end up needing to use Webpack sooner or later.

Anyway let’s see how these tools will evolve over time.

You found this article useful, feel free to clap so others will find it.

--

--