The Great Bundler Debate

Phoenix 1.4 ships with webpack - but that doesn’t mean you are stuck with it (but there certainly are reasons to stick with it).

If bundling puzzles you have a look at Modern JavaScript Explained For Dinosaurs.

Apart from all the other benefits that bundling can give you - the one that sticks out the most for me is: Modules.

Over the past years I’ve cooled on classes in general because of their typical association with mutability but some form of code organization is needed for any non-trivial codebase.

In the absence of an official module system for JavaScript, Node.js adopted the CommonJS module system. In 2011 Browserify made (appropriately designed) Node modules usable in the browser.

Before, there was always the danger of polluting the browser window’s global namespace with many errand, potentially conflicting global values/objects as they were loaded through the various <script> elements scattered throughout the web page. One could (though some libraries wouldn’t) resort to the Module Pattern but that required a lot of discipline.

Ultimately Browserify, as a bundler, made it a lot easier to use modules to organize code within a web page’s code base (apart from properly isolating the libraries implementations from the client code base).

Modules became an official part of ECMAScript with ES2015 (import/export), however it did not adopt the CommonJS spec.

To make matters worse browser native module support (type="module") doesn’t quite align with the established use of ES2015 modules in asset bundlers (for one the browser needs the “.js” file extension and other file path details; bundlers assume that a simple name (no path or extension) refers to a package managed by npm). Meanwhile Node.js introduced a new file extension.mjs” to accommodate plain, i.e. non-transpiled ES2015 modules. Otherwise Babel is used to transpile ESNext code (with ES2015 modules) to CommonJS modules with some target specific JavaScript “flavour” (be it a range of versions or a specific version of Node or browsers).

Back to bundlers. My primary impression:

The front end technology you (choose to) use will often dictate which bundler you have to use and have to become familiar with. If you choose to disregard the established “norm” of that particular front end development community then you have to be prepared to be the “salmon swimming up stream”, potentially cutting yourself off from valuable community contributions and support.

Phoenix is the back end - it ultimately doesn’t care which bundler you use.

Becoming competent with the bundler (if any) that supports your particular choice of front end tools is your responsibility.

That being said, my personal view at this time:

  • webpack - This bundler currently seems to dominate - which is probably due to it’s widespread adoption in the React.js and Vue.js communities. Since version 4, webpack is “zero configuration” at the entry level. That is the point when Phoenix adopted it. But ultimately there will be something that you want do differently with webpack and that is where the fun starts. Expect to spend a significant amount of time grappling with the comprehension of webpack’s “architecture”. But - if you are using React.js/Vue.js (or plan to use it some time in the future) - grin and bear it, otherwise you might be cutting yourself off from other “goodies” that the community can provide you with.

  • parcel - Extremely attractive at the entry level as you can simply point it to an existing HTML page and parcel figures out everything else from there. There seems to be a decent range of CLI options. For anything more complicated and you are going to have to get your hands dirty with (Node.js style) JavaScript and the API. People seem primarily attracted to it due to its almost non-existent time-to-initial-success - but I remain skeptical about what amount of intervention (and tradeoffs) will be needed for more challenging projects - but that is just a subjective gut feeling on my part.

  • rollup - unlike the others this doesn’t have a “zero configuration mode” but in my (limited) experience the learning curve for rollup is smooth enough and certainly a lot gentler than the jarring experience that webpack can be. I even found it fairly easy to get started with the API. Would I use it for a React.js/Vue.js project? No. But otherwise it seems to have a lot going for it. Some of my bias is based on the fact that designed around ES2015 modules - but it can handle CommonJS modules.

See this article Rollup v. Webpack v. Parcel for just a bit more detail.

I’ve had my say - what are your opinions?


Paul Lewis: My LIGHTWEIGHT build tooling setup (YouTube: October 2018) uses rollup.js.

His opinion on Parcel:

It’s great. It’s also magical, and I like magic when it works. When I need to go custom it is less good for me personally.

I’ve used Webpack since version 2 and it has improved very well, but I see two big cons to all those JavaScript’s world of tooling:

It’s JavaScript

I don’t hate JavaScript, but let’s be real: JavaScript’s ecosystem is a madness, having the largest number of packages available to you is not a good thing. I understand that people find JavaScript easy to learn for building things in a short amount of time, but what triggers me is that… like every three months a new wild JavaScript library appears, arguing that’s better, faster, stronger than X where X is the most hyped library at that time. Instead, people should try to help maintaining the current ecosystem we have, it’s large and good enough.

Large projects take a lot of time building (and this is getting worse)

Since people wants both, performance and extra features, the actual speed of JavaScript isn’t bad at all, but you can’t ask for performance in JavaScript when you’re processing hundreds of files, bundling assets, parsing templates to strip unused CSS, and many more.

OSS project idea: Build Webpack / Rollup / Parcel in Rust, people will pay for it.


Dredging up and old thread, but this is what I’ve been using on a recent project:

It’s a Rust based JS bundler. Very easy to use, does pretty much what it says on the tin. Do note however that it doesn’t do any transpiling so you may end up with issues when using newer syntax (static was a problem for me).

It’s very fast and works well when you want to import a few things from npm packages and divide your JS into a few different files. I’m using it in conjunction with make and inotifywatch to round out the other frontend assets.


There’s now also Snowpack. Not a bundler per-se, so it’s here to put an end to this debate (at last).

Build web applications with less tooling and 10x faster iteration. No bundler required.

TL;DR - With Snowpack you can build modern web apps (using React, Vue, etc.) without a bundler (like Webpack, Parcel, Rollup). No more waiting for your bundler to rebuild your site every time you hit save. Instead, every change is reflected in the browser instantly.