前端之缓存
浏览器缓存机制
有缓存查找优先级。
缓存位置
Service worker
- 浏览器独立线程,要求必须使用HTTPS协议保证安全性
- 缓存持续性。
- 步骤:
- 注册service worker,监听install事件缓存需要的文件
- 再次访问时,拦截请求并检查缓存,如果存在就直接读取,否则去请求数据。
Memory Cache
- 内存缓存,包含页面中抓取的资源。关闭页面就释放。
- 读取速度快。
preloader相关指令(页面优化)
Disk Cache
- 硬盘缓存,读取慢
- 容量,存储时效长
Push Cache
推送缓存http2。
session中存在,会话结束时释放。
缓存过程
浏览器判断资源缓存方式:根据第一次请求资源时返回的响应头确定
- 浏览器每次请求都会先查找浏览器缓存,缓存没有再去请求服务器。
- 每次拿到响应结果都会将缓存标识和资源存入浏览器缓存。
缓存策略
缓存策略由HTTP header实现。
强缓存
- 不向服务器发送请求,从缓存中读取。
- 设置http header:Cache-control或者Expires
- Cache-control(Http 1.1,优先级大于expires)
参数 | 含义 |
---|---|
public | 响应可被任意中间节点缓存 |
private | 只能被客户端缓存 |
no-cache | 不用强缓存机制(缓存资源但立即失效) |
no-store | 不缓存,不用强缓存和协商缓存 |
max-age=xxx | 缓存内容在xxx秒后失效(普通缓存),需重新请求 |
s-maxage | 和max-age一样,但只在代理中有效(代理缓存,优先级高) |
max-stale | 表示接受过期缓存,可以设置时限 |
min-fresh | 最小新鲜度 |
- Expires(http 1.0)
指定资源到期时间。
强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容
协商缓存
过程:
- 浏览器向浏览器缓存请求,失效就返回缓存标识
- 浏览器向服务器发起携带缓存标识的请求
- 服务器告诉浏览器是否需要更新缓存
- (304表示不用更新)浏览器向浏览器缓存请求获取缓存。
- (200表示已更新)服务器返回更新的资源,浏览器将资源存入浏览器缓存
- 根据文件修改时间:
设置http header
:Last-Modified
和If-Modified-Since
- 第一次访问资源时,响应头中有
Last-Modified
值为资源在服务器上的最后修改时间。 - 下次请求时,将
If-Modified-Since
的值改为Last-Modified
的值,发给服务器做对比。
Last-Modified 的弊端
- 本地打开缓存文件,就会造成 Last-Modified 被修改
- 只能以秒计时
- 根据文件是否修改:
设置http header
:Etag
和If-None-Match
-
Etag
: 资源文件唯一标识,文件修改就会重新生成。 -
请求时将
Etag
放到If-None-Match
中,让服务器对比 -
对比(Etag 和 Last-Modified):
- Etag 精确度更高
- Etag 性能略差
- Etag 优先级高
缓存机制
先强缓存再协商
实际缓存场景
-
经常变化的资源
Cache-Control: no-cache
使浏览器每次都请求服务器,配合 Etag 或者 Last-Modified 验证资源有效。 -
万年不变
Cache-Control: max-age=31536000
强制命中缓存,时间设置为(一年)。
更新的问题:在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)
用户行为
- 打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
- 普通刷新 (F5):标签页面没有关闭,memory cache 可用,其次才是 disk cache。
- 强制刷新 (Ctrl + F5):浏览器不使用缓存,Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache), 服务器返回 200 和最新内容。