Open axuebin opened 7 years ago
在前端开发中,我们在提到性能优化的时候总会提到一点:合理设置缓存。我们该如何从这方面入手来考虑提高网站性能呢?
我们都知道 HTML5 引入了应用程序缓存,可以在没有网络的情况下进行访问,同时,HTML5 还引入了 storage 本地存储。这些都属于应用缓存。
本篇文章主要内容是和浏览器缓存相关的,也可以说是 HTTP 缓存。
MDN 上是这样解释浏览器缓存的:
A browser cache holds all documents downloaded via HTTP by the user ... without requiring an additional trip to the server.
意思就是,浏览器缓存保存着用户通过 HTTP 获取的所有资源,再下一次请求时可以避免重复向服务器发出多余的请求。
HTTP
通俗的说,就是在你访问过一次某个网站之后,这个站点的文字、图片等所有资源都被下载到本地了,下次再访问该网站时判断是否满足缓存条件,如果满足就不用再花费时间去等待资源的获取了。
一般来说浏览器缓存可以分为两类:
我们需要知道的是,浏览器在加载资源时,会先判断是否命中强缓存再验证是命中协商缓存。
其它的的具体细节,稍后会展开来说。
浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。
header
从图中可以看出,强缓存一般是这样一个流程:
Expire
Cache-control
所以我们主要就是关注 Expire 和 Cache-control 这两个字段。
同样地,我们看看MDN中如何解释这个字段:
The Expires header contains the date/time after which the response is considered stale.
这个字段包含了一个时间,过了这个时间,响应将会失效。
也就是说,Expire 这个字段表示缓存到期时间,我们来打开一个网站并查看 Response Header 看看这个字段:
Response Header
Expires:Fri, 27 Oct 2017 07:55:30 GMT
可能在你查看这的时候发现时间不对啊,怎么都已经是过去了 ~
GMT 表示的是格林威治时间,和北京时间相差8小时。
GMT
上面的这个时间表示的是 2017年10月27日15:55:30。
2017年10月27日15:55:30
通过设置 Expire 来设置缓存有一个致命缺点:
可以看出,这个是个绝对时间,也就是说,如果我修改了客户端的本地时间,是不是就会导致判断缓存失效了呢。
既然不能设置绝对时间,那我就设置个相对时间呗。
在 HTTP/1.1 中,增加了一个字段 Cache-Control ,它包含一个 max-age 属性,该字段表示资源缓存的最大有效时间,这就是一个相对时间。
HTTP/1.1
Cache-Control
max-age
Cache-Control:max-age=600
这个表示的就是最大有效时间是 600s ,对的,它的单位是秒。
600s
Cache-Control 除了 max-age 属性之外还有一些属性:
现在基本上都会同时设置 Expire 和 Cache-Control ,Cache-Control 的优先级别更高。
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据请求头中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。
304
从图中可以看出,协商缓存一般是这样一个流程:
If-Modify-Since
Etag
Not Modified
浏览器第一次请求资源的时候,服务器返回的 header 上会带有一个 Last-Modified 字段,表示资源最后修改的时间。
Last-Modified
Last-Modified: Fri, 27 Oct 2017 07:55:30 GMT
同样的,这是一个 GMT 的绝对时间。
当浏览器再次请求该资源时,请求头中会带有一个 If-Modified-Since 字段,这个值是第一次请求返回的 Last-Modified 的值。服务器收到这个请求后,将 If-Modified-Since 和当前的 Last-Modified 进行对比。如果相等,则说明资源未修改,返回 304,浏览器使用本地缓存。
If-Modified-Since
well,这个方法也是有缺点的:
所以,后来又引入一个 Etag。
Etag 一般是由文件内容 hash 生成的,也就是说它可以保证资源的唯一性,资源发生改变就会导致 Etag 发生改变。
hash
同样地,在浏览器第一次请求资源时,服务器会返回一个 Etag 标识。当再次请求该资源时, 会通过 If-no-match 字段将 Etag 发送回服务器,然后服务器进行比较,如果相等,则返回 304 表示未修改。
If-no-match
Last-Modified 和 Etag 是可以同时设置的,服务器会优先校验 Etag,如果 Etag 相等就会继续比对 Last-Modified,最后才会决定是否返回 304。
当浏览器再次访问一个已经访问过的资源时,它会这样做:
浏览器缓存知识小结及应用
从图中可以看出的图 在哪里
在前端开发中,我们在提到性能优化的时候总会提到一点:合理设置缓存。我们该如何从这方面入手来考虑提高网站性能呢?
前言
我们都知道 HTML5 引入了应用程序缓存,可以在没有网络的情况下进行访问,同时,HTML5 还引入了 storage 本地存储。这些都属于应用缓存。
本篇文章主要内容是和浏览器缓存相关的,也可以说是 HTTP 缓存。
什么是浏览器缓存
MDN 上是这样解释浏览器缓存的:
意思就是,浏览器缓存保存着用户通过
HTTP
获取的所有资源,再下一次请求时可以避免重复向服务器发出多余的请求。通俗的说,就是在你访问过一次某个网站之后,这个站点的文字、图片等所有资源都被下载到本地了,下次再访问该网站时判断是否满足缓存条件,如果满足就不用再花费时间去等待资源的获取了。
浏览器缓存的分类
一般来说浏览器缓存可以分为两类:
我们需要知道的是,浏览器在加载资源时,会先判断是否命中强缓存再验证是命中协商缓存。
其它的的具体细节,稍后会展开来说。
强缓存
浏览器在加载资源时,会先根据本地缓存资源的
header
中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。从图中可以看出,强缓存一般是这样一个流程:
header
头中的Expire
和Cache-control
来判断是否满足规则;所以我们主要就是关注
Expire
和Cache-control
这两个字段。Expire
同样地,我们看看MDN中如何解释这个字段:
这个字段包含了一个时间,过了这个时间,响应将会失效。
也就是说,
Expire
这个字段表示缓存到期时间,我们来打开一个网站并查看Response Header
看看这个字段:可能在你查看这的时候发现时间不对啊,怎么都已经是过去了 ~
GMT
表示的是格林威治时间,和北京时间相差8小时。上面的这个时间表示的是
2017年10月27日15:55:30
。通过设置
Expire
来设置缓存有一个致命缺点:可以看出,这个是个绝对时间,也就是说,如果我修改了客户端的本地时间,是不是就会导致判断缓存失效了呢。
Cache-Control
既然不能设置绝对时间,那我就设置个相对时间呗。
在
HTTP/1.1
中,增加了一个字段Cache-Control
,它包含一个max-age
属性,该字段表示资源缓存的最大有效时间,这就是一个相对时间。这个表示的就是最大有效时间是
600s
,对的,它的单位是秒。Cache-Control
除了max-age
属性之外还有一些属性:现在基本上都会同时设置
Expire
和Cache-Control
,Cache-Control
的优先级别更高。协商缓存
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据请求头中的部分信息来判断是否命中缓存。如果命中,则返回
304
,告诉浏览器资源未更新,可使用本地的缓存。从图中可以看出,协商缓存一般是这样一个流程:
If-Modify-Since
或Etag
发送到服务器,确认资源是否更新;304
并且会显示一个Not Modified
的字符串,告诉浏览器使用本地缓存;Last-Modified,If-Modified-Since
浏览器第一次请求资源的时候,服务器返回的
header
上会带有一个Last-Modified
字段,表示资源最后修改的时间。同样的,这是一个
GMT
的绝对时间。当浏览器再次请求该资源时,请求头中会带有一个
If-Modified-Since
字段,这个值是第一次请求返回的Last-Modified
的值。服务器收到这个请求后,将If-Modified-Since
和当前的Last-Modified
进行对比。如果相等,则说明资源未修改,返回304
,浏览器使用本地缓存。well,这个方法也是有缺点的:
Last-Modified
并不会发生变化;Last-Modified
可不这样认为。所以,后来又引入一个
Etag
。Etag
Etag
一般是由文件内容hash
生成的,也就是说它可以保证资源的唯一性,资源发生改变就会导致Etag
发生改变。同样地,在浏览器第一次请求资源时,服务器会返回一个
Etag
标识。当再次请求该资源时, 会通过If-no-match
字段将Etag
发送回服务器,然后服务器进行比较,如果相等,则返回304
表示未修改。Last-Modified
和Etag
是可以同时设置的,服务器会优先校验Etag
,如果Etag
相等就会继续比对Last-Modified
,最后才会决定是否返回304
。总结
当浏览器再次访问一个已经访问过的资源时,它会这样做:
304
告诉浏览器使用本地缓存;