前言
一个http请求中会有headers,它包含了请求头Request Headers和响应头Response Headers。
headers前后端都是可以自定义的
Request Headers
记住常用的如下:
内容 | 含义 |
---|---|
accept | 浏览器可接收的数据格式 |
accept-encoding | 浏览器可接收的压缩算法,例如gzip |
accept-languange | 浏览器可接收的语言,例如zh-CN |
connection | 例如keep-alive;一次TCP连接重复使用 |
cookie | cookie |
host | 请求的域名 |
user-agent | 简称ua,浏览器信息 |
content-type | 发送数据的格式,例如application/json |
if-modified-since | 协商缓存相关,对应相应头的last-modified |
if-none-match | 协商缓存相关 对应相应头的etag |
Response Headers
记住常用的如下:
内容 | 含义 |
---|---|
content-type | 返回数据的格式,例如application/json |
content-length | 返回数据的大小,多少字节 |
content-encoding | 返回数据的压缩算法,例如gzip |
set-cookie | 设置浏览器的cookie |
cache-control | 控制强制缓存的逻辑,后面有单独说明 |
last-modified | 资源最后修改时间(协商缓存相关) |
etag | 资源的唯一标识,一个字符串(协商缓存相关) |
强制缓存
一般由服务端返回的响应头决定,通过cache-control告知浏览器。
cache-control的值一般有:
- max-age:缓存最大时间
- no-cache:服务端不搞缓存了
- no-store:客户端服务端都不搞缓存(不常见)
- private 不常见不用记
- public 不常见不用记
控制强制缓存的逻辑,例如返回的响应头中cache-control:max-age=232323
(单位为秒)表示这个请求的返回资源可以放在浏览器缓存中这么久(浏览器会自动做好这个动作),下次直接请求本地缓存拿对应的资源,不需要再次请求服务端。
我们在控制器中的网络里可以找到用到强缓存的请求,可以在size中看到(disk cache)
,说明就是使用了强缓存策略。
原来负责缓存的是expires,现在被cache-control代替。
协商缓存
也叫对比缓存,是一种服务端与浏览器之间的缓存策略,浏览器初次请求时,服务端首次把资源返回并在相应头中加上一个标识etag和资源最后修改时间last-modified,浏览器心领神会把资源放入缓存中。
如果下次需要这个资源还需要带上这个标识(在request headers中叫if-none-match)和修改时间(在request headers中叫if-modified-since)继续请求,服务端接收到,如果该标识和服务端现对应资源一致,且最后修改时间和服务端一致,说明资源没有改变,浏览器还是可以用本地缓存的资源,于是就返回304,大大节省了接口大小。如果服务端发现标识不一致了,就正常返回最新的文件并且更新标识和修改时间。
etag与last-modified:优先使用etag,因为last-modified只能精确到秒级,且如果资源被重复生成,而内容不变etag也不会改变,但last-modified变了。
强缓存和协商缓存的配合
一般强缓存之间协商缓存都会配合。
一般来说,正常的页面跳转强制缓存和协商缓存都是不会失效的,但是在手动刷新(例如右键刷新)的时候,强制缓存就会失效,协商缓存还生效。只有在强制刷新的时候,两者才会失效。
在开发过程中如果不想让缓存影响资源的获取,可以在控制台中的网络勾上禁止缓存即可。
为什么需要缓存
接口请求时间远远大于计算机计算的时间,且还有可能不稳定。对于可以缓存的数据,缓存起来下次使用能够大大提升页面加载过程。
一般需要做缓存机制的接口主要是静态资源(js/css/img)的获取。
很多时候强缓存和协商缓存是默认开启的,这点你可以看你上线后项目的静态资源的获取求证。
例如我开发的一个静态网站部署到gitte后:
这些静态资源都是从缓存中获取的,拿出mainfest.json文件的响应头就可以看到对应缓存相关的字符:
至于为啥有的缓存到磁盘有的缓存到内存,就不太清楚了。待我后续研究研究。
webpack的hash文件字符
你会发现webpack配置了打包文件的hash值后,每次打包如果目标文件有代码变动会生成新的hash值,例如index.html引入个a.js,上次部署的时候是a.123.js,下次部署变成a.456.js,这时两次的请求资源地址就不一样了,新的请求也就没有强缓存协商缓存这一说。
等到下一次再重新请求a.456.js文件时,强缓存协商缓存又开始工作。