在webpack中使用CommonsChunkPlugin时,我们是否需要Etag和Last-Modified标头

时间:2017-07-05 22:04:34

标签: caching nginx webpack header

我正在使用webpack捆绑所有资产文件,所以我得到类似的东西。

bundle.7fb44c37b0db67437e35.js
vendor.495e9142a1f8334dcc8c.js
styles.bc5b7548c97362b683f5582818914909.css

我在名称中使用了chunkhash,因此当浏览器缓存某些内容时,它会再次缓存,直到哈希值发生变化。例如,如果我更改样式中的某些内容,捆绑文件并进行部署,则只有样式的哈希值会发生变化,其他浏览器不会再次从服务器请求样式文件,其余的将从内存缓存中使用。

在回复标题中,我还有 Etag Last-Modified ,每次我为每个文件部署应用时,它们都会更改。我应该从响应中删除它们吗?这可能会混淆浏览器与服务器联系并查看文件是否已更改,即使哈希仍然相同?

1 个答案:

答案 0 :(得分:2)

好问题。这在很大程度上取决于后端的实现方式以及计算标头值的方式。这些文件是从我们的服务器提供的,还是像s3这样的其他东西?我们使用的是CDN吗?我们是否为我们的应用服务器使用框架?谁计算这些标题,Web服务器或应用程序服务器?

就本答案而言,为了简单起见,我们假设我们使用的流行服务器框架Express没有CDN或第三方托管。与大多数应用程序服务器一样,Express 根据所服务文件的内容计算ETagLast-Modified,而不是文件名

首次浏览器请求我们的某个文件时,它会收到资源的ETagLast-Modified。下次请求相同的资源时,浏览器会将缓存的ETagLast-Modified标头发送到服务器。然后,服务器根据这些标头决定浏览器是否需要下载新版本的资源,或者缓存版本是否为最新版本。如果缓存的资源是最新的,则服务器将使用304 - Not Modified状态代码进行响应。状态代码是整个缓存系统的关键 - 它是浏览器决定是否应该使用缓存资源的方式。

要生成ETag标头,Express会将响应正文的二进制Buffer表示传递给etag模块,该模块根据缓冲区的内容计算SHA-1哈希值( source: generating ETag headersource: generating hash)。要生成Last-Modified标头,Express会使用文件系统的上次修改时间(see lastModified in docs)。

当webpack构建新的bundle时,即使chunkhash相同,文件的二进制文件也会改变。这会导致Express输出不同的EtagLast-Modified,这意味着下次请求资源时它不会以304响应。如果没有304状态代码,浏览器将不必要地重新下载该软件包。

答案

我认为在这里做的最好的事情是禁用这些资产的ETagLast-Modified标头,而是使用ExpiresCache-Control: max-age标头设置到远处的日期未来(通常为1年)。这样,如果捆绑包过期或者缓存中根本不存在,浏览器将只重新下载捆绑包。