-
Notifications
You must be signed in to change notification settings - Fork 0
Description
浅谈HTTP缓存原理
为什么要缓存,缓存有什么作用?
显而易见,缓存当然是为了加快资源获取速度,并且有提升用户体验,而且节约了网络资源,缓解了服务器的压力等好处。
浏览器缓存原理的过程
首先缓存分为强缓存和协商缓存。这里用几句话概括下整个过程。首先默认先走强缓存,如果没超时失效,就不请求到服务器,直接采用浏览器的缓存。如果超时失效,再走协商缓存,后端会进行比对。比对的是资源文件有没有修改,如果没修改的话,那么就返回304,告诉浏览器文件没有修改直接采用缓存。如果文件发生改变,那么返回最新文件。之后请求同个资源还是这么走,如此反复。这边直接引用一张图,来自政采云前端团队博客:<a href="https://juejin.cn/post/6844904153043435533" target="_blank"图解 HTTP 缓存>。
强缓存
直接从浏览器缓存中读取资源,而不会向服务器发送请求,请求返回状态码为200,并且在浏览器的Network的Size列会显示memory cache或者from disk cache,这个是由浏览器控制的。
怎么配置强缓存?
可以由Expires、Cache-Control和Pragma这3个Header属性来控制。三者的优先级是 Pragma > Cache-Control > Expires。
Pragma
只有一个属性值,就是 no-cache,效果和Cache-Control配置no-cache一致,即不使用强缓存,需要走协商缓存。
Cache-Control
Cache-Control主要用于控制强缓存。它是HTTP/1.1的重要规则,可以在请求头或者响应头中设置,并且可以组合使用多种指令,如下图所示:
Expires
指的是缓存过期时间,是1个具体时间点,而且是在响应头配置的。
Expires是HTTP/1的规范,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
Expires和Cache-Control对比
两者都是控制强缓存,区别是 Expires 是HTTP/1的产物,Cache-Control是HTTP/1.1的产物,如果两者同时配置,Cache-Control优先级高于Expires。在某些不支持HTTP/1.1的环境下,Expires就会发挥作用。
协商缓存
强缓存只关心是否超出某个时间或者时间段,而不关心资源文件是否更改。那如果服务器的资源文件发生了更改,如果还使用强缓存的话,显然浏览器就无法获得最新的文件。此时就需要用到协商缓存策略了。
协商缓存是在强缓存失效后,由服务器通过浏览器携带的缓存标识进行比对判断,如果失效则返回最新资源文件和状态码200,反之则返回状态码304和Not Modified。
协商缓存可以通过设置两种HTTP Header实现:Last-Modified 和 ETag。
Last-Modified 和 If-Modified-Since
浏览器第一次请求资源时,服务器返回资源的同时,如果响应头配置了Last-Modified,表示资源最后修改时间,浏览器就会缓存这个资源和Header。
然后在下次请求这个资源时,浏览器会在请求头上带上If-Modified-Since,值就是之前Last-Modified的值。
服务器在收到请求后,将If-Modified-Since的值与资源最后修改时间对比。如果一致,则返回304,通知浏览器直接读取缓存中的资源。反之,则返回200和最新的资源。
ETag 和 If-None-Match
ETag的值相当于资源文件的指纹,是由某种算法得到唯一标识,只要文件改变了,值就会变。
这样的话,浏览器第一次请求资源时,服务器返回资源的同时,如果响应头配置了ETag,浏览器也会缓存这个资源和Header。
然后在下次请求这个资源时,浏览器会在请求头上带上If-None-Match,值就是之前ETag的值。
服务器在收到请求后,将If-None-Match的值与资源的ETag值对比,来判断文件是否改变。如果一致,则返回304,通知浏览器直接读取缓存中的资源。反之,则返回200和最新的资源。
ETag和Last-Modified对比
-
精确度上,ETag优于Last-Modified。
Last-Modified有两个缺陷:1.只精确到秒级; 2.如果文件没变,修改时间变了呢 -
性能上,Last-Modified优于ETag,前者只需获取修改时间,而ETag则需要通过算法计算出有一个hash值。
-
优先级上,服务器优先使用ETag
实际使用场景缓存策略
频繁变动的资源
这种场景先配置Cache-Control: no-cache,然后再结合ETag或者Last-Modified来验证资源是否有效。
不常变动的资源
这种一般设置强缓存即可,比如Cache-Control配置一个很大的max-age=31536000 (一年)。如果需要解决更新问题,则需要在资源路径后添加hash或者版本号等。