vlambda博客
学习文章列表

前端应该懂的浏览器缓存策略

浏览器的缓存规则是在 http 协议头和 html 页面的 meta 标签中定义的。主要分为两部分:强缓存和协商缓存。

强缓存是指缓存的副本在有效期内,浏览器直接获取这个副本并渲染。

强缓存主要涉及的 http 协议报头有:Expires,cache-control。

强缓存的过程:浏览器发起 http 请求,浏览器缓存中查找该请求的结果以及缓存标识,缓存副本在有效期内,该请求返回状态码 200,从 disk cache 或 memory cache (size 中显示 from disk cache 或 from memory cache)中返回。如果缓存副本并不在有效期内,浏览器将发起 http 请求到服务端,服务端返回请求结果和缓存规则,并将请求结果和缓存标识存在浏览器缓存中。

时间

浏览器发送第一次请求:不缓存,服务端根据设定的缓存策略返回相应的header,如:cache-control,expires,last-Modified,ETag。

浏览器发送第二次请求:

1.是否:有cache-control且不过期。是的话返回本地磁盘缓存,状态值200(from cache);否的话

2.是否:有expires且不过期。是的话返回本地磁盘缓存,状态值200(from cache);否的话

3.是否:有Etag。是的话请求头添加If-None-Match,值就是上次返回的Etag值,然后发送给服务端。服务端对比If-None-Match与现有的Etag值是否一样;一样的话只返回header,状态码304,浏览器从本地磁盘获取缓存信息;不一样走正常流程,返回header+body,状态码200。没有Etag的话

4.是否:有last-Modified。是的话添加请求头If-Modified-Since,值是上次返回的last-Modified,然后发送给服务端。服务端对比If-Modified-Since与现有的是否一样;一样的话返回只返回header,状态码304,浏览器从本地磁盘获取缓存信息;不一样走正常流程,返回header+body,状态码200。没有last-Modified的话:

5.没有缓存,正常请求

其中1,2阶段称为强缓存策略,它的特点是不需要和服务端通信就决定是否使用缓存,cache-control优先级大于expires。3,4阶段称为协商缓存策略,它的特点是需要和服务端通信决定是否用缓存,Etag优先级大于last-Modified。

协商缓存

协商缓存是在强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。

协商缓存的过程:浏览器发起 http 请求,浏览器缓存返回缓存标识(请求的缓存结果失效),浏览器携带该资源的缓存标识,向服务器发起 http 请求,如果服务器返回 304 和 not modified,浏览器向浏览器缓存获取该请求的缓存结果,浏览器环迅返回该请求结果。如果服务器返回 200 和请求结果(该资源更新了,重新返回请求结果),浏览器将该请求结果和缓存标识存入浏览器缓存中。

协商缓存主要涉及的 http 协议报头有:Last-Modified 和 ETag。

Last-Modified:浏览器在第一次访问资源时,服务器返回响应头Last-Modified,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;再次请求资源,浏览器检测有 Last-Modified 就会添加请求头 If-Modified-Since,值是Last-Modified 的值。服务器接收请求会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化返回 304 和空的响应体,直接从缓存读取。如果 If-Modified-Since 时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和 200。

Etag 和 If-None-Match:Etag返回的是资源文件的唯一标识,只要文件有变化吗Etag就会重新生成。浏览器在下次加载资源时带上 If-None-Match,值是ETag。服务器比较跟资源文件的ETag是否一致。如果一致,则直接返回 304 。

如果 ETag 和 Last-Modified 同时存在,ETag 优于 Last-Modified.Last-Modified 的时间单位是秒,秒级别的修改,不能保证精度。如果是负载均衡的服务器各个服务器生成的 Last-Modified 也有可能不一致。在性能上,ETag 要逊于 Last-Modified,ETag 需要服务器通过算法计算一个hash值。

协商缓存是无法减少请求数的开销的,但是可以减少返回的正文大小。一般来说,对于勤改动的html文件,使用协商缓存是一种不错的选择。

F5 刷新,Expires/cache-control 无效了,Last-Modified/ETag 还是有效的。

Ctrl + F5 强制刷新,Expires/cache-control,Last-Modified 都无效。

不被缓存的请求:

包含cache-control:no-cache,pragma:no-cache 或者 cache-control:max-age=0等。

需要根据cookie,认证信息等决定输入内容的动态请求是不能被缓存的。post 请求。

基于缓存策略:

同一个url保证稳定性。

给 css 、js 、图片等资源增加 HTTP 缓存头(对于不常修改的静态资源,设置一个较长的时间),入口 html 不建议设置缓存。

减少对 cookie 的依赖,每次 get 和 post 请求,都带上 cookie 增加网络传输流量,导致增长交互时间,同时cache 是很难缓存的。

最后附上浏览器缓存策略分析图:

- END -


结伴同行前端路