I am using webpack to bundle all my assets files so I get something like this.
bundle.7fb44c37b0db67437e35.js
vendor.495e9142a1f8334dcc8c.js
styles.bc5b7548c97362b683f5582818914909.css
I use chunkhash in the name so when browser caches something it doesnt cache again until hash has changed. For example if I change something in styles, bundle the files and deploy, only the hash from styles will change, others wont so browser will request from the server again just the styles file and the rest will use from memory cache.
In response header I also have Etag and Last-Modified and they change every time I deploy app for every file. Should I remove them from response? Can that confuse the browser to contact the server and see if files have changed even though hash is still the same?
Great question. This depends largely on how the back-end is implemented and how it calculates the header values. Are the files served from our server, or something else like s3? Are we using a CDN? Are we using a framework for our application server? Who calculates these headers, the web server or the application server?
For the purposes of this answer and to keep things simple let's assume we are using the popular server framework Express with no CDN or 3rd party hosting. Like most application servers, Express calculates ETag
and Last-Modified
based on the content of the file being served - not the name of the file.
The first time a browser requests one of our files, it will receive the the ETag
and Last-Modified
for the resource. The next time the same resource is requested the browser will send the cached ETag
and Last-Modified
headers to the server. The server then decides based on these headers whether the browser needs to download a new version of the resource or if the cached version is current. If the cached resource is current, the server responds with a 304 - Not Modified
status code. The status code is the key to this whole caching system - it is how the browser decides if it should use the cached resource.
To generate the ETag
header, Express passes a binary Buffer
representation of the response body to the etag
module which calculates a SHA-1 hash based on the contents of the Buffer (source: generating ETag header and source: generating hash). To generate the Last-Modified
header, Express uses the file system's last modified time (see lastModified
in docs).
When webpack builds a new bundle the file's binary will change even if the chunkhash is the same. This causes Express to output a different Etag
and Last-Modified
, which means it will not respond with a 304
the next time the resource is requested. Without the 304
status code, the browser will unnecessarily re-download the bundle.
I think the best thing to do here is disable ETag
and Last-Modified
headers for these assets and instead use the Expires
or Cache-Control: max-age
header set to a date far in the future (usually 1 year). This way the browser will only re-download a bundle if it is expired or if it simply does not exist in the cache.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With