Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we need Etag and Last-Modified header when using CommonsChunkPlugin in webpack

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?

like image 716
Igor-Vuk Avatar asked Oct 30 '22 05:10

Igor-Vuk


1 Answers

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.

Answer

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.

like image 164
ross Avatar answered Nov 15 '22 08:11

ross