什么是浏览器缓存
简单的来说,浏览器缓存就是把一个已经请求过的资源拷贝一份副本存储在浏览器中,当再次请求服务器时,如果请求的资源已经存在缓存中了,就会直接从缓存中读取,而不是重新去向服务器请求
缓存都是通过设置HTTP Header来实现的,浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
浏览器每次拿到返回的结果都会将该结果和缓存标识存入浏览器缓存中
为什么要使用缓存
(1)减少网络带宽消耗
当Web缓存副本被使用时,只会产生极小的网络流量,可以有效的降低运营成本。
(2)降低服务器压力
给网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。同时,搜索引擎的爬虫机器人也能根据过期机制降低爬取的频率,也能有效降低服务器的压力。
(3)减少网络延迟,加快页面打开速度
对于用户来说,缓存的使用能够明显加快页面打开速度,达到更好的体验。
浏览器的缓存分为:强缓存和协商缓存
强缓存
强缓存不会向服务器发送请求,直接从缓存中读取资源,可以通过设置两种HTTP Header 实现:Expires 和 Cache-Control,两者的作用是一致的,都是指当前的有效期。
1.Expires(了解) 缓存过期时间,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存中取数据,而无需再次请求。 缺点:Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它现在有些过时了,现阶段它的存在只是一种兼容性的写法。Expires受限于本地时间,如果修改了本地时间,可能会造成缓存失败
2.Cache-Control(重点)
Cache-Control 常见的取值有private、public、no-cache、max-age,no-store,默认为private。
private: 客户端可以缓存
public: 客户端和代理服务器都可缓存
max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 需要使用对比缓存来验证缓存数据
no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发
3. Expires和Cache-Control两者对比 两者的差别不大,两者同时存在的话,Cache-Control优先级高于Expires
总结:
强缓存判断是否缓存的依据来自于是否超出当前有效期,而不关心服务器端文件是否已经更新,可能会导致加载文件不是服务器端最新的内容,那我们如何得知服务器端内容是否已经发生了更新呢? 这时候就需要用到协商缓存策略。
协商缓存
协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识决定是否使用缓存过程,主要有以下两种情况:
协商缓存生效,返回304和Not Modified 协商缓存失效,返回200和请求结果
协商缓存可以通过设置两种HTTP Header实现:Last-Modified 和 ETag 。
1. Last-Modified/If-Modified-Since
Last-Modified:
- 浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加
Last-Modified字段,Last-Modified的值就是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和Last-Modified的值。
If-Modified-Since:
- 浏览器下一次请求这个资源,检测到有 Last-Modified这个值,于是添加If-Modified-Since字段,值就是Last-Modified中的值
- 服务器再次收到请求,会根据If-Modified-Since中的值与服务器中这个资源的最后修改时间对比
- 如果没有变化,返回304,告诉浏览器直接从缓存中读取即可
- 如果有变化,说明文件有更新,于是返回新的资源文件和200
缺点:如果本地打开缓存文件,即使没有对文件进行修改,还是会造成Last-Modified被修改,服务器不能监听到缓存,导致发送相同的资源
2. ETag / If-None-Match
ETag是服务器响应请求时,返回当前资源文件的唯一标识(由服务器生成),只要资源有变化,ETag就会重新生成
If-None-Match:
- 浏览器再次向服务器发送请求时,会将上一次返回的ET ag值放到request header里的
If-None-Match字段里 - 服务器只需要比较
If-None-Match跟自己服务器上该资源的ETag是否一致 - 如果发现ETag匹配不上,那么直接以200的形式将新的资源(当然也包括了新的ETag)发给客户端
- 如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
两者对比
- 在精度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度
- 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
- 在优先级上,服务器校验优先考虑Etag
总结
强缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)。协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
一般情况下,使用Cache-Control/Expires会配合Last-Modified/ETag一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销。