假如缓存没有过期则不向浏览器发出请求了,但是抓包的时候还是返回200 ok,但是留意了,会有Provisional headers are shown 的提示,说明就是浏览器并未发出请求, 缓存依然有效。
(这坑很大啊,明明没有向浏览器发起请求,还显示200来吓唬人-.-)
这时在Chrome里面会出现200(from disk cache)和200(from memory cache)的情况。官方解释如下:
Chrome employs two caches — an on-disk cache and a very fast in-memory cache. The lifetime of an in-memory cache is attached to the lifetime of a render process, which roughly corresponds to a tab. Requests that are answered from the in-memory cache are invisible to the web request API. If a request handler changes its behavior (for example, the behavior according to which requests are blocked), a simple page refresh might not respect this changed behavior. To make sure the behavior change goes through, call handlerBehaviorChanged() to flush the in-memory cache. But don't do it often; flushing the cache is a very expensive operation. You don't need to call handlerBehaviorChanged() after registering or unregistering an event listener.
http学习笔记——浏览器缓存机制
前言
作为前端开发,我们在web开发的过程中需要调用后端接口,用node搭建服务器或者写一些中间件对数据进行封装处理等等,必不可少地会和http打上交道,所以我们都要掌握http各方面的知识。
说到性能优化问题,一定会提到http缓存,如何利用好http缓存机制,理解http缓存的整个过程和http如何设置缓存,把这些都弄懂后会对我们以后在项目实践中都会有很大帮助。本篇文章将会和大家分享一下笔者对http缓存机制的一些知识整理和总结。
与缓存相关的http头部字段
我们先看看http头部中与缓存相关的一些字段的基本概念和用法。
该字段来自http1.0时代,当其设置为
no-cache
的时候和Cache-Control: no-cache
效果一样,意为无缓存,客户端不会读取缓存,直接向服务器发起请求。因为是http1.0留下的遗物,仅为了做向后的兼容。该字段也是来自http1.0时代,用于控制缓存时间。例如设置了
Thu, 18 Jul 2019 08:43:30 GMT
,即告诉浏览器如果没有超过这个时间,将不会向服务器发起请求。Expires存在两个缺点:
http1.1新增了 Cache-Control 字段,用来定义缓存过期时间,若报文中同时出现了 Pragma、Expires 和 Cache-Control,会以 Cache-Control 为准。(网上也有Pragma优先级高于Cache-Control的说法,但是一般设置了
Pragma: no-cache
的话也会设置Cache-Control: no-cache
的吧-.-)先看看cache-control的常用设置值
cache-control字段可以包含以上多个值,但是最终会选择最为保守的方案。
当客户端第一次发起请求时,服务端会返回状态码200以及客户端请求的资源,同时响应头部会带有Last-Modified字段,标记此文件在服务器最后修改的时间。
而下次客户端再次发起请求的时候,请求头部就会带有If-Modified-Since或者If-Unmodified-Since的字段,他们的值是上一次响应头部Last-Modified字段的值,用于校验资源是否过期。
若使用If-Modified-Since则服务端会判断此时间后此文件是否修改过,如果没有修改过则使用缓存资源,返回304,否则将获取资源返回200.
若使用If-Unmodified-Since,则是相反的情况,若资源未修改过则获取资源,否则返回412(Precondition Failed)响应。它常用于两个场景:
当遇到下面情况时,If-Unmodified-Since 字段会被忽略:
Last-Modified存在的问题
为了解决以上Last-Modified存在的问题,http1.1还提出另外一个字段——Etag。Etag,实体首部字段,服务器资源的唯一标识符, 客户端可以根据ETag值缓存数据, 节省带宽。因此Etag的优先级高于Last-Modified。
服务器会通过某种算法,给资源计算得出一个唯一标志符(比如md5标志),在把资源响应给客户端的时候,会在实体首部加上“ETag: 唯一标识符”一起返回给客户端。
当再次向服务器发起请求时,请求头部会发送If-Match或者If-None-Match字段,服务器收到请求后则将其与被请求资源的唯一标识进行比对。
If-None-Match,若不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;若相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
If-Match,若不同,则返回412(Precondition Failed) 状态码给客户端。否则服务器直接忽略该字段。其应用场景是客户端走PUT方法向服务端请求上传/更替资源,这时候可以通过 If-Match 传递资源的ETag。
使用Etag注意两点:
http缓存策略
做好前期的知识铺垫,马上扔个流程图上来
我们看到图中不同阶段有不同的缓存策略,我们逐一看看。
过期策略主要是通过Expires和CacheControl来判断缓存是否已经过期,若两者都没有设置的话,则使用浏览器默认的一套‘10%’算法来进行判断,通常会取响应头的Date_value - Last-Modified_value值的10%作为缓存时间。
假如缓存没有过期则不向浏览器发出请求了,但是抓包的时候还是返回200 ok,但是留意了,会有Provisional headers are shown 的提示,说明就是浏览器并未发出请求, 缓存依然有效。
(这坑很大啊,明明没有向浏览器发起请求,还显示200来吓唬人-.-)
这时在Chrome里面会出现200(from disk cache)和200(from memory cache)的情况。官方解释如下:
意思大概就是Chrome会使用磁盘缓存和内存缓存,内存缓存是直接从内存中读取的,所以速度更快。内部具体的规则还不大了解,估计是根据渲染刷新方式和文件大小决定的。
假如缓存过期了则走下一步协商策略。
协商策略是通过Last-Modified和Etag字段向服务器发起验证能否使用缓存资源,若验证通过,则返回304状态码,根据响应头更新缓存,使用缓存资源。
若没有通过校验,则向服务器获取资源,返回200,并将响应内容存进缓存。
这没啥好说的,就是将响应内容存入缓存或者根据响应内容更新缓存。
综上,再看回这个流程图,我们梳理一下整个过程。
参考文章