概念引出
浏览器会对最近请求过的资源进行缓存,下次访问时就会直接从缓存中加载,是浏览器的缓存机制,cache-control则是缓存策略中的一个配置。
为什么要进行浏览器缓存?浏览器缓存的优点?
- 减少了冗余的数据传输,节省了网络成本
- 减少了服务器的负担,大大提升了网站的性能
- 加快了客户端加载网页的速度
浏览器缓存的分类
1、强缓存
强缓存是利用http的返回头中的Expires或者Cache-Control两个字段来控制的,用来表示资源的缓存时间。
Expires
该字段是http1.0时的规范,它的值为一个绝对时间的GMT格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。
这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。
Cache-Control
Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如
- Cache-Control:max-age=3600,代表着资源的有效期是3600秒。
cache-control 除了该字段外,还有下面几个比较常用的设置值:
- no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
注意:Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高
2、协商缓存
协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问,通过ETag/If-None-Match和Last-Modify/If-Modify-Since两组参数控制。
Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。
当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回304,并且不会返回资源内容,也不会返回Last-Modify。
ETag/If-None-Match
服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。If-None-Match:发现资源具有Etage声明,则再次向服务器请求时带上头If-None-Match (Etag的值)。服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定是否命中协商缓存。
与 Last-Modified 不一样的是,当服务器返回304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。
ETag和Last-Modify的区别:
- Etag要优于Last-Modify。Last-Modify的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modify其实并没有体现出来修改,但是Etag每次都会改变确保了精度;
- 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值;
- 在优先级上,服务器校验优先考虑Etag。
浏览器缓存过程
1.浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存;
2.下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modify-Since的请求
3.服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;;
4.如果服务器收到的请求没有Etag值,则将If-Modify-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modify和文件并返回200;
缓存存储位置
内存缓存(memory cache)和硬盘缓存(disk cache)
| 区别 | 内存缓存 | 硬盘缓存 |
|---|---|---|
| 存储内容 | JS,字体,图片等 | CSS等 |
| 读取速度 | 快 | 慢 |
| 时效性 | 进程关闭则清空 | 可以缓存较长时间 |
| 空间 | 空间小 | 空间大 |