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.