Asset Bundling in Express
Including so many static assets has undesirable consequences. First, it increases page load times because each asset needs to be downloaded separately.1 Each request incurs the overhead of HTTP, TCP, and the limitations of the speed of light as it travels over the wire.
We need a way to bundle our assets. If the assets are bundled then we reduce the overhead of 24 total requests to 4: global CSS file, global JS file, page-specific CSS file, and page-specific JS file.
The main reason why we’ve been avoiding a build or bundle system is that it’s a big commitment; you have to buy into a specific workflow and hope it scales well into the future with your code base. Does it support minifying of JS and CSS? Does it have a development mode where you can include unbundled and unprocessed versions of your assets (very helpful for debugging)? Does it require bundled and processed files to be committed to your repository? Does bundling occur when the app is started? Does the app need to be restarted when source files are changed?
Since we’re using Express, middleware was our first thought but all we could find were BundleUp and Pound (which is built on BundleUp). We have successfully integrated bundle-up but we know it’s not a long-term solution since it’s not being maintained and its dependencies are way out of date.
What we like about BundleUp is that bundles are configured inside of the app itself. This makes it easier to figure which assets are included in which views and makes the development mode possible where assets are included directly instead of bundled. If you use an external bundling system and you want a development mode then bundles need to be configured both internally and externally which can be a mess.
One downside of BundleUp is that it runs when the app starts so it slows startup time. The documentation also leaves a lot to be desired. We noticed it was touching our source files and causing Nodemon to consistently restart the app. It turns out that it’s written to “compile” all assets, even if they’re not being processed (such as SASS or CoffeeScript) or minified. The default compile behavior for vanilla JS and CSS is to copy but our paths were configured such that it was writing over the originals with an exact copy.
We don’t like Bower because of it’s reliance on manifest files and how you can only exclude files in the manifest as opposed to marking only a few for inclusion. Besides, Bower is designed to handle and bundle external dependencies. All of the assets we want to bundle are already installed locally and committed to the repo. We just want to process local files and bundle them all together.
Duo is a new kid on the block and fits our development style a little better, but again it’s likely much more than we need.
In the future we hope to create our own middleware for Express. All it needs to do is allow for bundles to be configured and then process and minify them. It can’t be too hard, and we can’t believe BundleUp is the only thing out there like it.