浏览器的缓存机制
浏览器的缓存机制
在前端开发中,性能一直是一个非常重要的部分,其中一个非常重要的判断标准就是一个网页打开的速度,其中一个提高网页反应速度的非常重要的方式就是利用浏览器的缓存机制,良好的缓存策略可以降低资源的重复加载提高网页的整体加载速度,减少请求的延迟,降低网络负荷。
通常浏览器缓存策略分为两种:强缓存和协商缓存
基本原理
- 浏览器在加载资源时,根据请求头的
Expires
和cache-control
判断是否命中强缓存,如果命中则直接从缓存读取资源,不会向服务器发起请求。 - 如果强缓存没有命中,浏览器一定会向服务器发起请求,通过
last-modefied
和Etag
去判断资源是否命中协商缓存,如果命中代表资源没有更新,服务器会返回304,读取缓存中的资源,如果没有命中,则代表资源有更新,服务器会返回200,从服务器加载资源。
强缓存和协商缓存的异同
- 同: 如果两种缓存方式都未命中,则都需要从服务端加载资源
- 异:强缓存命中不会向服务器发起请求,协商缓存需要向服务器发起请求
强缓存
强缓存通过
Expires
和Cache-Control
两种响应头实现。
1. Expires
Expires: Wed, 22 Oct 2018 08:41:00 GMT
Expires
出现于 HTTP / 1.0 ,表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT
后过期,需要再次请求。并且受限于本地时间,如果修改了本地事件,如果修改了本地时间,可能造成缓存失效。
2. Cache-Control
Cache-Control 出现于 HTTP / 1.1,优先级高于 Expires ,表示的是相对时间。
Cache-Control: max-age=315360000
协商缓存
协商缓存是利用的是【Last-Modified,If-Modified-Since】
和【ETag、If-None-Match】
来管理的。
1. Last-Modefied & If-Modified-Since
Last-Modefied
代表服务器端文件的最后修改时间,当浏览器发起请求时,会向服务端发送If-modefied-Since
报头,询问在Last-Modefied
之后有没有被修改过。如果没有修改过,则返回304使用缓存,如果修改过,则向服务器请求资源,返回200。
但是如果本地打开缓存文件,会导致Last-Modefied
被修改,所以在 HTTP/1.1中引入 Etag
.
2. Etag & & If-None-Match
Etag
是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。当发送请求是If-None-Match
会将上次的Etag
发送给服务器进行判断是否有更新,如果有更新,则会请求新的资源。
ETag
的优先级比Last-Modified
更高
具体为什么要用ETag
,主要出于下面几种情况考虑:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
- 某些服务器不能精确的得到文件的最后修改时间。
如何选择合适的缓存策略
大致的顺序
- Cache-Control —— 请求服务器之前
- Expires —— 请求服务器之前
- If-None-Match (Etag) —— 请求服务器
- If-Modified-Since (Last-Modified) —— 请求服务器
协商缓存需要配合强缓存使用,如果不启用强缓存的话,协商缓存根本没有意义
大部分web服务器都默认开启协商缓存,而且是同时启用【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】