Hashing assets when server-side rendering
Webpack can generate hashes for every bundle that it outputs. If you use that hash in your bundle filenames, it gives you a way to safely serve your bundles with long-term cache headers. This is something the Rails world has done for many years to avoid some of the issues around long-term caching:
If there are no digests in the filenames, and far-future headers are set, remote clients will never know to refetch the files when their content changes.
Adding hashes to filenames requires a single-line configuration change to your Webpack config. In the output
section, instead of:
Webpack Configuration
output: {
filename: "[name].js",
}
use:
output: {
filename: "[name].[chunkhash].js",
}
You could use [hash]
instead, but generally that has some caveats around unexpected hash changes - a big problem if you're trying to avoid expiring all of your assets each time you build.
What about providing a map of bundle names to their hashed counterparts? That can be useful on the server when trying to match a route to a specific bundle. There are a few different options out there, but I like the "Manifest Plugin". Use it like this:
Webpack Configuration
...
const ManifestPlugin = require('webpack-manifest-plugin');
...
module.exports = {
...
plugins: [
new ManifestPlugin({
map(file) {
file.name = file.chunk.name;
return file;
}
})
],
...
};
That will output a file named "manifest.json" in the bundle output directory, with contents similar to:
JSON
{
"homepage": "homepage.98ead8bdd620bf142c80.js"
}
Now if you import
that JSON file into your server code, you'll be able to determine the compiled asset name for any bundle.