The beauty of bundling

Bundling, as it relates to web applications, is the packaging together of resources needed to serve a website. It’s sometimes often referenced as compiling a site, although this definition is not entirely suitable.

Bundling is somewhat of a strange requirement in web projects. In theory, you don’t need to compile, transpile, convert, or optimize anything to create a website. After all, the way the web was designed, the final production files are supposed to be one and the same as your source files. Sites used to be proudly Made with Notepad, after all.

But that theory does not match the reality of modern web development. Given all we can do inside a browser, web projects are more complex now than ever. This means serving unchanged source files is a disservice to your visitors. It is often better not just to bundle files together, but to pre-process them to perform certain optimizations that would be cumbersome or time-wasting if done during the development process. Adding support for older browsers, compressing assets, concatenating files together, dropping unused code, making sure your code confirms to more strict analysis, and many more: these are all steps better taken by a computer, rather than developers themselves.

Hence why every serious web project needs a bundling process where the original, human-editable source files (and assets) are transformed into bundle of files that browsers and slow internet connections can more easily digest.

Bundling is nothing new. However, I think we’re at a point where our understanding of what makes good web bundling is changing somewhat.

I used to think of bundling (or compilation or transpilation or optimization or any number of different descriptions) of a website as a mere process of optimizing for discrete types of resources. Something like this:

As a result, I’ve used a number of different tools to help me bundle my web projects together. It started with Grunt, which, tellingly, is not exactly a bundler, but a task runner. This means it performs certain separate tasks when creating a website. In that vein, things like “compressing images” is a task; “transpiling JavaScript” another task; and so on and so forth.

After a while I switched to Gulp. I enjoyed it a lot more than Grunt; the ability to create linear tasks using standard JavaScript code made it a great replacement to Grunt’s often confusing configuration-based tasks and plugins. But it was still following on the idea of running tasks, that is, having different routes that your site’s resources have to go through before it was put together.

It’s only when I started using Browserify, and later Webpack, that I realized I had got it all wrong. Creating a website is not supposed to handled by a sequence of discrete tasks; it’s supposed to be one single task. Something like this:

This is something that took a while for me to understand. What prompted that understanding was analyzing a pretty advanced Webpack configuration created by another team at work. I got a lot of ideas from there, and decided to replace my use of Gulp in a personal project with a full-fledged Webpack workflow.

Ironically, I was coming out of Gulp – a tool I still love – back to a monstrous config file, Grunt-style. But I wanted to see what it was about.

Several videos also helped me get it. This is one of them:

The magic of Webpack is not that it is a better task runner. Heck, you can’t use it for arbitrary tasks. Instead, it does one task – bundling – very well. It does so by taking a more higher level approach at what constitutes a web application. Suddenly, you’re not treating your code, styles, and other resources as separate entities; they are part of the same magical, mysterious soup that gets mixed together to produce a well-balanced website.

Consider these examples. I used to write CSS files using Less. Less supports (via Gulp) a good number of plugins for minification, auto-prefixing, and any number of tasks as you might need to run on your CSS. But it is still seen as a separate entity from the image files it uses, or the HTML files it is used in. I had to write url references that matched the final structure of my website, and I had to include the style files in my HTML by using the filename I knew were going to be the location of my final compiled files. Then, of course, I needed a separate task to just copy the referenced image files to the correct destination.

In Webpack, everything is a module, so my CSS simply references files using their existing (local) path name. When bundling, Webpack will automatically identify those as needed resources, process them the way I want them to be processed, move them to their final destination, and change the file path references as needed. It’s a more holistic way of looking at it.

In that context, certain features that are confusing or cumbersome to implement somewhere else – say, embedding images as Base64 resources in your style sheet if they below of a certain size – come for free.

The same happens, of course, when dealing with your code. Suddenly, having your code import CSS styles is trivial, since they’re all part of the same thing. Images can also be inlined where used, if you wish.

HTML output is also simpler. Since your bundle is aware of where all files are, writing tags to your HTML that make reference to the correct files is just automatic.

In essence, much of the guesswork of file referencing is taken out of the developer’s work, and handled by the bundler. A file is missing? Webpack will give you an error message. A file is not referenced and as such not needed? It will not be included in the bundle.

These are just examples that come to my mind of the advantages of Webpack’s more harmonious approach to website development. Still, many more exist. It’s not that these are not possible somewhere else; it’s that they’re a core part of what makes Webpack. And this is reflected in many of its features, including its incredible development-time watcher/server.

In my own personal project tests, the results couldn’t be better, both as my development workflow goes, and in the final result. The final files are as tightly packed as can be: small images are embedded in code, stylesheets, or HTML; all optimizations (including image optimizations) are done at bundling time; both CSS auto-prefixing and code auto-polyfilling (based on target supported browsers) is performed automatically; and project structure is as high level as it can be.

More than being yet another JavaScript development tool, Webpack is a more mature way of looking at how we create websites efficiently. Little surprise that newcomers like FuseBox are following on the footsteps of the concepts started by Webpack.

  • Leonardo Hessel

    Thanks for the tips, I’ll try on my projects.