使用 ETag 以利用浏览器缓存,节省带宽

ETag 可以理解为服务端的一个资源标识,当两次请求相同的 URL,且 URL 对应的资源没有变化时 ETag 的值应该相同。合理使用 ETag 可以有效利用浏览器缓存,降低服务器的带宽压力。

原理分析

用户第一次通过 URL 请求资源时,服务器将为该资源生成 ETag(其值一般为MD5摘要),并通过响应头返回给浏览器,浏览器会将资源进行缓存。下次相同 URL 被请求时,浏览器将在请求中附加 If-None-Match 请求头,其值为上次请求返回的 ETag 的值,服务端收到该请求后仍需要对当前版本的资源取 MD5 摘要,然后与 If-None-Match 头的值进行比较,相同就表示资源未更改,浏览器可以使用缓存,无需再次下载该资源(服务器将返回不带任何内容的 304未修改状态)。

ETag 头往往需要与 Cache-Control 缓存指令配合使用,从上面的描述我们可以知道即使浏览器拿到了 ETag 且已经缓存了资源,再次请求资源时也需要由原始服务器进行检查,以验证资源是否被修改,因此 Cache-Control 响应头的值应包含 no-cache 以使浏览器采用协商缓存验证。另外为了避免任何中间人(代理,CDN 等)的干扰,Cache-Control 响应头的值应包含 private 私有缓存,即 "private, no-cache"。

参考:

  1. Cache-Control
  2. ETag

注意事项

ETag 可视为对资源是否改动进行验证的验证器,ETag 分为强验证器和弱验证器,一些 HTTP 中间代理服务(如 nginx)可能会对资源进行压缩或处理,致使强验证器被修改为若验证器,甚至验证器被移除,解决办法是一开始就让原服务器生成弱验证器。