mosaic101 / blog

my blog (keep running~~~)
https://github.com/mosaic101/blog/issues
39 stars 6 forks source link

浏览器缓存策略 #12

Open mosaic101 opened 3 years ago

mosaic101 commented 3 years ago

浏览器缓存策略

1. 前言

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。这样带来的好处有:缓解服务器端压力,提升性能(获取资源的耗时更短了)。对于网站来说,缓存是达到高性能的重要组成部分。缓存需要合理配置,因为并不是所有资源都是永久不变的:重要的是对一个资源的缓存应截止到其下一次发生改变(即不能缓存过期的资源)。

缓存的种类有很多,其大致可归为两类:私有与共享缓存。共享缓存存储的响应能够被多个用户使用。私有缓存只能用于单独用户。本文将主要介绍浏览器与代理缓存,除此之外还有网关缓存、CDN、反向代理缓存和负载均衡器等部署在服务器上的缓存方式,为站点和 web 应用提供更好的稳定性、性能和扩展性。--- 摘自《MDN - HTTP 缓存》

本文主要介绍浏览器缓存(即私有缓存)。在大多数场景下,缓存是最常见的优化手段,简单高效~

缓存的优势特点:

2. 缓存机制

常见的 HTTP 缓存只能存储 GET 响应,对于其他类型的响应则无能为力。缓存的关键主要包括request method和目标URI(一般只有GET请求才会被缓存),流程图如下:

cache

2.1 强缓存

强缓存:如果命中强缓存,浏览器发送的请求不会到达服务器,而是直接从浏览器缓存中读取数据,在chrome network中size显示为 disk cache 或者 memory cache,HTTP 状态码为200。

diskcache

强缓存的字段:Expires(HTTP/1.0)、Cache-Control(HTTP/1.0)、Pragma (HTTP/1.0,效果同Cache-Control: no-cache,主要为了兼容,不做赘述)

2.1.1 Expires

是一个绝对的时间,指定资源到期时间是服务器的具体时间点,该字段存在于服务器响应头, 即在此时间之前,直接读取浏览器缓存数据。如果值为 0, 代表着过去的日期,即该资源已经过期。

expires

Expires的优点:

Expires的缺点:

2.1.2 Cache-Control

已知Expires的缺点之后,在HTTP/1.1中,新增了一个字段Cache-control,该字段表示资源缓存的最大有效时间(相对时间),在该时间内,客户端不需要向服务器发送请求。

cachecontrol

Cache-control常用值如下:

常用值 字段说明
private 默认值,所有内容只有客户端才可以缓存,代理服务器不能缓存
public 所有的内容都可以被缓存 (包括客户端和代理服务器, 如 CDN)
max-age 表示资源能够被缓存(保持新鲜)的最大时间,单位为s
must-revalidate 如果超过了max-age的时间,浏览器必须向服务端发送请求,验证资源是否还有效
no-cache 不使用强缓存,浏览器在使用缓存数据时,需要与服务器验证缓存是否新鲜
no-store 真正意义上的“不要缓存”,所有内容都不走缓存,包括强制和对比
s-maxage 设置共享缓存,比如CDN。会覆盖max-age和Expires
max-stale 能容忍的最大过期时间,表示客户端愿意接收一个已经过期的资源
min-fresh 能够容忍的最小新鲜度。标示了客户端不愿意接受新鲜度不多于当前的age加上min-fresh设定的时间之和的响应

Cache-Control的优点:

Cache-Control的缺点:

2.2 协商缓存

当强缓存失效or没设置时,由客户端与服务器通过某种标识来判断(协商)资源是否可用,所以字段是成对出现的。请求头If-Modified-Since和响应头Last-Modified配对,请求头If-None-Match和响应头ETag配对。如果命中,HTTP 状态码为304。

2.2.1 Last-Modified和If-Modified-Since

是一个绝对的时间 ,表示服务器的资源最后一次修改的时间,在请求头中将上次的 Last-Modified 的值写入到请求头的 If-Modified-Since 字段,对比该次请求响应头Last-ModifiedIf-Modified-Since 时间,若时间一致,返回304状态码。

lastmodified

Last-ModifiedIf-Modified-Since优点:

Last-ModifiedIf-Modified-Since缺点:

2.2.2 Etag和If-None-Match

为了解决Last-ModifiedIf-Modified-Since的缺点 ,在HTTP/1.1 新增了EtagIf-None-Match字段,存储的是文件的特殊标识(一般由Hash生成),例如 Nuxt.js 服务端渲染页面时自带 Etag。 同样在请求头中将上次的 Etag 的值写入到请求头的 If-None-Match 字段,对比该次请求响应头EtagIf-None-Match 值,若一致,返回304状态码。

etag

EtagIf-None-Match优点:

EtagIf-None-Match缺点:

3. 用户行为对浏览器缓存的影响

用户操作 Expires/Cache-Control Last-Modied/Etag
地址栏回车
页面链接跳转
新开窗口
前进、回退
F5刷新 X
Ctrl+F5强制刷新 X X

5. Vary

Vary HTTP 响应头决定了对于后续的请求头,如何判断是请求一个新的资源还是使用缓存的文件。当缓存服务器收到一个请求,只有当前的请求和原始(缓存)的请求头跟缓存的响应头里的Vary都匹配,才能使用缓存的响应。

vary

简而言之,可以通过Vary字段来通知缓存哪些请求头字段用于区分相同的URL请求,服务端存在不同内容的响应。

6. CDN(公有缓存)

在大多数前端项目中,静态资源都会使用CDN加速用户访问。CDN缓存策略因为服务商的不同而不同,但一般会根据源站响应头中的Cache-ControlExpires 字段来设置节点缓存时间。因此,CDN缓存返回的Cache-ControlExpires 一般源自服务器或者Nginx配置。

7. 总结

8. 参考