浏览器缓存分为强缓存和协商缓存。
- 对于强缓存,浏览器在第一次请求的时候,会直接下载资源,然后缓存在本地,第二次请求的时候,直接使用缓存。
- 对于协商缓存,第一次请求缓存且保存缓存标识与时间,重复请求向服务器发送缓存标识和最后缓存时间,服务端进行校验,如果没有过期则使用缓存。
缓存的作用
缓存对于前端性能优化来说是个很重要的点,良好的缓存策略可以降低资源的重复加载提高网页的整体加载速度
当客户端请求某个资源时获取缓存的流程如下
- 先根据这个资源的一些
http header判断它是否命中强缓存,如果命中,则直接从本地获取缓存资源,不会发请求到服务器; - 当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些
request header验证这个资源是否命中协商缓存,称为http再验证,如果命中,服务器将请求返回,但不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就会从缓存中获取资源; - 强缓存和协商缓存共同之处在于,如果命中缓存,服务器都不会返回资源; 区别是,强缓存不对发送请求到服务器,但协商缓存会。
- 当协商缓存也没命中时,服务器就会将资源发送回客户端。
- 当
ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存; - 当
f5刷新网页时,跳过强缓存,但是会检查协商缓存;
强缓存
Expires(该字段是http1.0时的规范,值为一个绝对时间的GMT格式的时间字符串,代表缓存资源的过期时间)Cache-Control:max-age(该字段是http1.1的规范,强缓存利用其max-age值来判断缓存资源的最大生命周期,它的值单位为秒)
协商缓存
Last-modified/If-Modified-Since
- 第一次请求的时候服务端返回
Last-modified表明请求的资源上次的修改时间,- 第二次请求的请求头
If-Modified-Since上带着Last-Modified的值,表示资源上次的修改时间,- 服务端拿到这个字段进行对比。
Last-Modified:值为本地资源最后更新时间,随服务器response返回。If-Modified-Since:If-Modified-Since会将Last-Modified的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。
但是如果在本地打开缓存文件,就会造成 Last-Modified被修改,所以在 HTTP / 1.1 出现了 ETag,并且 ETag 优先级比 Last-Modified 高。
If-None-Match/ETag:
- 第一次请求的时候,服务端会返回该ETag给客户端
- 第二次请求的时候客户端会通过
If-None-Match带上该标识ETag- 服务端对
If-None-Match携带的ETag表示进行对比。
ETag:表示资源内容的唯一标识,对比缓存时使用它来标识一个缓存,随服务器response返回。If-None-Match:If-None-Match会将当前ETag发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。
选择合适的缓存策略
对于大部分的场景都可以使用强缓存配合协商缓存解决
但是在一些特殊的地方可能需要选择特殊的缓存策略
- 对于某些不需要缓存的资源,可以使用
Cache-control: no-store,表示该资源不需要缓存 - 对于频繁变动的资源,可以使用
Cache-Control: no-cache并配合ETag使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新。 - 对于代码文件来说,通常使用
Cache-Control: max-age=31536000并配合策略缓存使用,然后对文件进行指纹处理,一旦文件名变动就会立刻下载新的文件