In my last post about my side project I have mentioned that I have extracted 2 shared bundles to increase my build speed, and one downside of that is that now have two more requests for every page, and this week I have implemented a small tweak that will compensate to that: indefinite caching.

As fancy as it may sound, it turned out to be a small tweak in my case, partly because I already had it implemented before for the vendor bundles, and partly because I have dreamed it a couple of nights already and had it almost coded in my head. šŸ™‚

For the vendor bundles it looked like this: to be able to serve them with a maximum max-age in the Cache-Control header, I just added their NPM version number in the file name. For example, here is the path for the React module:

/vendor_modules/react-16.13.0.js

This will allow me not to worry about it getting cached when I upgrade it. There is one nuance that Iā€™d like to mention: I donā€™t bundle the vendor modules at all, I just serve them from the node_modules directory. Bundling them all into a ā€œvendorā€ bundle would only increase the build time without much added value.

For the app bundles I use the Git revision as the version, so I have paths like this:

/home/bundle-21f11a9c3f6037c1b80372ad7b3aa8d36cd9e1c9.js
/shared/bundle-21f11a9c3f6037c1b80372ad7b3aa8d36cd9e1c9.js
/frontend/shared/bundle-21f11a9c3f6037c1b80372ad7b3aa8d36cd9e1c9.js

In production, Heroku exposes the Git revision in the HEROKU_SLUG_COMMIT env var, and locally I just set it to development.

All of this gives me a efficient and reliable caching model: the browser loads the JS files only once per change, both for the vendor and app bundles. Which means that after the first page load, the two additional bundles donā€™t make a significant difference, because the browser will not request any JS file twice, and the result is visible with the naked eye.

I am glad I could get this working with a tiny slice of code without an ā€œasset pipelineā€ or an additional ā€œmodule bundlerā€ of any sort.