最近在学习前端优化的问题,正好看到浏览器缓存。看别人的感觉都会,等到自己说出个所以然来可能就有卡壳了。好记性不如烂笔头,记录下来加深下印象。
前端缓存
一个数据流程:前端请求、后台处理、浏览器响应。第二步后台数据处理等,前端无法控制,那么在第一步 请求,第三步 响应,就是前端可以多发挥的地方。
- 常用缓存位置
- 缓存缓存策略分类
- 常用浏览器操作下的缓存表现
常用缓存位置
操作系统的常理是:先读取内存,再读取磁盘,所以按优先级来介绍。
- from memory Cache
顾名思义: 这是储存在内存中的缓存。但是内存的容量一般相对于磁盘是很小的。 所以它的存储注定是“暂时性的”。每个浏览器的 tab 页关闭,那么内存中的缓存也将被清了。当然极端情况某个 tab 页占据过多它的内存空间,那么它的缓存可能也会失效。内存中的缓存空间分配、原理等暂时超出我理解范围的事情暂不讨论。 - from disk cache
顾名思义:这是硬盘储存,是把文件储存在本地磁盘上的,是一种永久存储。而且它允许相同的资源 跨会话、站点情况下使用。 disk cache 会严格按照 http 头部字段来判断是否缓存及缓存时间的问题。当然缓存持续增加,必然涉及到清理的问题。清理的问题基本都是浏览器一些神奇的代码解决。所以这也是超出我这个酸菜鱼的理解范围。 - 不常使用的缓存 Service Worker
看资料,只能由HTTPS承载,这个优先级是最高的,这个缓存是永久性的,即关闭 TAB 或者浏览器,下次打开依然还在(而 memory cache 不是)。有两种情况会导致这个缓存中的资源被清除:手动调用 API cache.delete(resource) 或者容量超过限制,被浏览器全部清空。Chrome浏览器:Application -> 左边Cache Storage模块。 MDN 地址.
常用缓存策略分类
先说下浏览器第一次请求过程分析:
-
强缓存
不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。-
expires
Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。现在基本使用第二种 cache-control,所以不多介绍,可以百度。 -
cache-control
在HTTP/1.1中,增加了一个字段Cache-control,该字段表示资源缓存的最大有效时间,在该时间内,客户端不需要向服务器发送请求。- max-age:即最大有效时间,在上面的例子中我们可以看到
- must-revalidate:如果超过了 max-age 的时间,浏览器必须向服务器发送请求,验证资源是否还有效。
- no-cache:虽然字面意思是“不要缓存”,但实际上还是要求客户端缓存内容的,只是是否使用这个内容由后续的对比来决定。
- no-store:真正意义上的“不要缓存”。所有内容都不走缓存,包括强制和对比。
- public:所有的内容都可以被缓存 (包括客户端和代理服务器, 如 CDN)
- private:所有的内容只有客户端才可以缓存,代理服务器不能缓存。默认值。
这些值可以混用,混用规则。
Cache-control 的优先级高于 Expires,为了兼容 HTTP/1.0 和 HTTP/1.1,实际项目中两个字段我们都会设置。
-
-
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
主要通过两组字段来控制:- Last-Modified & If-Modified-Since
- 后台通过 last-Modified 告知前端,资源最后一次修改时间。
- 浏览器缓存值与内容。
- 下一次请求相同资源时,浏览器将 last-Modified 值写入头部字段 If-Modified-Since 。
- 服务器比对两个值是否相等,如果相同则未修改返回 304,否则重新请求资源,返回 200.
- 缺陷:以秒为单位,秒以下变动监测不到;服务器动态生成文件,更新时间永远是生成的时间,生效不了。
- ETag和If-None-Match
- Etag是服务器响应请求时,返回的唯一文件标识。
- 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match 。
- 服务器同样进行比较,命中返回 304, 不命中返回新资源和 200。
Etag 的优先级高于 Last-Modified
- Last-Modified & If-Modified-Since
我们借用 前辈 的流程 总结下整个缓存流程:
当浏览器要请求资源时:
- 调用 Service Worker 的 fetch 事件响应
- 查看 memory cache
- 查看 disk cache。这里又细分:
- 如果有强制缓存且未失效,则使用强制缓存,不请求服务器。这时的状态码全部是 200。
- 如果有强制缓存但已失效,使用对比缓存,比较后确定 304 还是 200。
- 发送网络请求,等待网络响应
- 把响应内容存入 disk cache (如果 HTTP 头信息配置允许)
- 把响应内容 的引用 存入 memory cache (无视 HTTP 头信息的配置)
- 把响应内容存入 Service Worker 的 Cache Storage (如果 Service Worker 的脚本调用了 cache.put())
常用浏览器操作下的缓存表现
-第一次输入网址:
-关闭 tab 页重新打开:
知识就放在那,看你去不去取了。 参考来源:
深入理解浏览器的缓存机制
一文读懂前端缓存
彻底理解浏览器的缓存机制