浏览器的缓存机制
缓存是性能优化的关键手段,可以大大的减少网络延迟,大大提高性能
image
memory cache 和 disk cache
memory cache
是内存中的缓存,主要包含当前页面下载的资源,图片、样式、脚本等等。读取内存上的资源比读取硬盘上的更快;但是内存缓存的时间短,当前 tab 也关闭时内存也会被释放
因为内存有限所以并不是所有的资源都可以存放在内存当中,一般存放的都是 preloader 相关的资源
disk cache
所有的资源都可以存放在硬盘上,读取速度比内存慢一点
浏览器会根据 http 请求的响应头决定哪些资源需要缓存,哪些需要向服务器重新发送请求
浏览器是如何知道缓存哪些文件的
响应头中与缓存相关的字段
-
Expires
-
Cache- Control
-
Last-Modified/If-Modified-Since
-
Etag/If-None-Match
前两者是强缓存,后两者是协商缓存
强缓存
强缓存是不需要向服务器发送请求的,可以直接返回 200,使用浏览器的缓存,返回的状态码有 from memory cache/from disk cahce.
通过 Expires 和 Cache-Control 来实现,Cache-Control的优先级更高
Expires
是 http1.0 中提出的,值是 GMT 时间,是一个绝对时间,在该时间之前表示缓存有效,可以直接使用浏览器总的缓存,不需要向服务器请求资源
缺点
和本地时间有关,如果调整了本地时间那么缓存就有可能会失效,所以就有了 Cache-Control
Cache-Control
http1.1 中提出的用于控制资源缓存的首部
值
- public
表示资源可以被任意地方缓存,CDN、代理服务器、浏览器
- private
表示资源只能被浏览器所缓存,私人缓存
- max-age
相对时间,单位是秒
相对于资源返回的时间(浏览器记录了这个时间)而言,在这个时间范围之内,缓存都有效
- max-stale
能容忍的最大过期时间,表示浏览器可以接受已经过期的资源,但是过期的时间不能超过我们设置的时间,单位是秒,如果不设置,表示可以接受任意过期的资源
- no-cahce
不是代表资源不缓存,资源也可以被缓存,只不过浏览器不会直接使用缓存,而是会使用协商缓存来验证资源是否有效,然后来决定是否使用缓存中的资源
- no-store
所请求的资源不会被缓存,每次都去服务器请求最新的资源
- s-maxage
和 max-age 相同,只不过设置的是代理服务器缓存的有效时间
- max-fresh
表示资源的最小新鲜度,所请求的资源在我们设置的时间内有效
- must-revalidate
表示只有校验缓存中的文件是最新的才会使用缓存中的资源
协商缓存
协商缓存指的是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识来决定是否使用缓存
缓存有效
返回 304 和空的响应体,表示使用缓存中的资源
image缓存失效
返回200和新的资源以及缓存标识
image
协商缓存使用的是【Last-Modified、If-Modified-Since】和【Etag、If-None-Match】这两对http header来进行管理的
Last-Modified
http1.0中提出
浏览器第一次请求资源的时候,返回该资源时,会在响应头中添加一个Last-Modified首部,表示该资源的最后修改时间。浏览器下次请求该资源的时候,会自动在请求头中添加一个If-Modified-Since的头部,只为Last-Modified的值,服务器收到这个请求的时候会取出If-Modified-Since的值和所请求的资源的最新修改时间相比较,如果一直则返回304和空的响应体,表示使用缓存中的资源,如果小于最新修改时间,则返回200+最新的资源以及缓存标识
缺点
- 只能精确到秒,有些资源可能会在一秒中修改了多次,此时就会导致浏览器使用的还是旧的资源
- 我们可能只是打开了文件,但是并没有修改,即使是这样Last-Modified的值还是会发生改变,导致缓存失效
针对Last-Modified的缺点,就出现了Etag
Etag
http1.1中提出
服务器根据指定资源的内容生成的唯一标识,优先级高于Last-Modified,只要资源的内容发生改变,Etag就会重新生成。浏览器在下一次请求资源的时候就会将该资源的Etag放入request header中的If-None-Match首部中。服务器会比较客户端传递过来的If-None-Match的值和服务器上该资源的Etag是否一致,就可以很好的判断该资源是不是最新的。如果服务器发现 ETag 匹配不上,那么直接以常规 GET 200回包形式将新的资源(当然也包括了新的 ETag)发给客户端;如果 ETag 是一致的,则直接返回304知会客户端直接使用本地缓存即可。
缓存机制总结
强缓存优先于协商缓存,强缓存有效则直接使用缓存中的资源,不会发送请求到服务器,否则则使用协商缓存。然后根据协商结果判断返回304还是200+新的资源
没有设置缓存的时候浏览器默认的缓存策略
缓存时长 = (访问时间 - 最后一次修改时间) / 10
用户行为对浏览器缓存的影响
-
刷新浏览器:强缓存失效,协商缓存有效,浏览器携带Cache-Control: max-age=0以及协商缓存相关首部去请求服务器,看是否可以使用本地资源
-
强制刷新:协商缓存和强缓存都失效,浏览器携带Cache-Control: no-cache首部请求服务器(为了兼容还会设置Pragma: no-cache)
缓存的缺点
可能由于缓存导致用户看到的是旧的页面,无法看到在缓存有效期间开发者更新的功能
解决方式:
- 每次版本更新手动修改引用的脚本文件的版本号
- 使用打包工具,给生成的静态资源的文件名添加hash值
网友评论