前端开发中的资源缓存详解
资源缓存用于缓存静态资源,良好的缓存策略可以减少资源重复加载进而提高网页的整体加载速度。
通常浏览器缓存策略分为两种:强缓存和协商缓存,当然还包括 service worker。
-
浏览器在资源加载时,根据请求头中的 expires 和 cache-control 值来判断是否命中强缓存,命中则直接从本地缓存中读取资源,这一过程不需请求服务器。
-
如果未命中强缓存,浏览器则会发送请求到服务器,服务器通过 last-modified 和 etag 值来验证资源是否命中协商缓存,若命中,则服务器会将这个请求返回,但是不会返回这个资源的数据,浏览器接收到该请求响应后依然从本地缓存中读取资源。
-
若强缓存和策略缓存都未命中,那么浏览器将请求服务器获得资源并加载。
强缓存和策略缓存如果命中,都是直接从客户端缓存加载对应资源。但不同点是:强缓存自比较开始至缓存命中不会请求服务端,而策略缓存的是否使用本地缓存这一决定是需要服务端参与的,换言之策略缓存需要请求服务端来完成的。
1. 强缓存
强缓存通过 Expires 和 Cache-Control 响应头实现。两者详细说明如下:
1.1. Expires
中文释义为:到期,表示缓存的过期时间。expire 是 HTTP 1.0 提出的,它描述的是一个绝对时间,该时间由服务端返回。因为 expire 值是一个固定时间,因此会受本地时间的影响,如果在缓存期间我们修改了本地时间,可能会导致缓存失效。
通常表示如下:
Expires: Wed, 11 May 2018 07:20:00 GMT
1.2. Cache-Control
中文释义为:缓存控制。cache-control 是 HTTP 1.1 提出的,它描述的是一个相对时间,该相对时间由服务端返回。
通常表示如下:
Cache-Control: max-age=315360000
该属性还包括访问性及缓存方式设置,列举如下:
-
no-cache 存储在本地缓存取中,只是在与服务器进行新鲜度再验证之前,缓存无法使用。
-
no-store 不缓存资源到本地。
-
public 可被所有用户缓存,多用户进行共享,包括终端或 CDN 等中间代理服务器。
-
private 仅能被浏览器客户端缓存,属于私有缓存,不允许中间代理服务器缓存相关资源。
缓存与使用缓存流程说明如下:
2. 协商缓存
浏览器加载资源时,若强缓存未命中,将发送资源请求至服务器。若协商缓存命中,请求响应返回304状态码。
协商缓存主要使用到两对请求响应头字段,分别是:
-
Last-Modified 和 If-Modified-Since
-
Etag 和 If-None-Match
2.1. Last-Modified 与 If-Modified-Since
Last-Modified 由上一次请求的响应头返回,且该值会在本次请求中,通过请求头If-Modified-Since传递给服务端,服务端通过 If-Modified-Since与资源的修改时间进行对比,若在此日期后资源有更新,则将新的资源发送给客户端。
不过,通过文件的修改时间来判断资源是否更新是不明智的,因为很多时候文件更新时间变了,但文件内容未发生更改。
这样一来,就出现了 ETag 与 If-None-Match。