内容出自前端性能优化原理与实践,我作为笔记简单记录下。
浏览器缓存机制有四个方面,
Memory Cache
Service Worker Cache
HTTP Cache
Push Cache
HTTP 缓存机制探秘
HTTP 缓存分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的情况下,才会走协商缓存。
强缓存的特征
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的。浏览器会根据其中的 expires 和 cache-control 判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
命中强缓存的情况下,返回的 HTTP 状态码为 200 (如下图)。
强缓存的实现:从 expires 到 cache-control
实现强缓存,过去我们一直用 expires 。
当服务器返回响应时,在 Response Headers 中将过期时间写入 expires 字段。像这样:
expires: Wed, 11 Sep 2019 16:12:18 GMT
expires 是一个时间戳,试图再次向服务器请求资源,浏览器就会先对比本地时间和 expires 的时间戳,如果本地时间小于 expires 设定的过期时间,那么就直接去缓存中取这个资源。
expires 是有问题的,它最大的问题在于对“本地时间”的依赖。如果服务端和客户端的时间设置可能不同,或者我直接手动去把客户端的时间改掉,那么 expires 将无法达到我们的预期。
考虑到 expires 的局限性,HTTP1.1 新增了 Cache-Control 字段来完成 expires 的任务。
给 Cache-Control 字段一个特写:
cache-control: max-age=31536000
max-age 是 31536000 秒,它意味着该资源在 31536000 秒以内都是有效的
Cache-Control 相对于 expires 更加准确,它的优先级也更高
协商缓存:浏览器与服务器合作之下的缓存策略
协商缓存依赖于服务端与浏览器之间的通信。
协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。
如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304(如下图)。
协商缓存的实现:从 Last-Modified 到 Etag
Last-Modified 是一个时间戳,如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回:
Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT
使用 Last-Modified 存在一些弊端,这其中最常见的就是这样两个场景:
1.我们编辑了文件,但文件的内容没有改变。
2.当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的
这两个场景其实指向了同一个 bug——服务器并没有正确感知文件的变化。为了解决这样的问题,Etag 作为 Last-Modified 的补充出现了。
Etag 是由服务器为每个资源生成的唯一的标识字符串,这个标识字符串是基于文件内容编码的
Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准。
MemoryCache
MemoryCache,是指存在内存中的缓存。它是浏览器最先尝试去命中的一种缓存。
其他缓存自行百度
网友评论