在读本文前你要确保读过我的上篇文章《扼杀 304,Cache-Control: immutable》,因为本文是接着上文写的。上文说到,在现代 Web 上,“条件请求/304 响应”绝大多数都是浪费资源,因为绝大多数静态资源都是永恒不变的,因此 Firefox 实现了 Cache-Control: immutable 来让开发者们控制用户浏览器的刷新行为,即在刷新时不要对这些资源文件进行条件请求(缓存不过期的前提下)。

Chrome 至今迟迟没有实现 Cache-Control: immutable,难道 Chrome 不想让自己的网页在刷新时展现的更快?不是的,其实 Chrome 的开发人员也早已注意到了这个问题。早在 2015 年底,他们就开发出了一种新的刷新行为,称之为 new reload/faster reload/non-validating reload,这种新的刷新和以前传统的刷新有个区别,那就是在刷新页面时,只对页面本身的资源文件进行条件请求(如果缓存了的话),页面里引用的各种子资源文件,只要缓存不过期,就直接读取缓存。也就是说,“你们开发者压根不用去加什么 Cache-Control: immutable 响应头了,我 Chrome 直接改成刷新不发条件请求就得了”。

Chrome 在 2015 年底只针对安卓端的 Chrome for Android 中的下拉刷新开启了这种新的刷新,下面是当时的 commit log

Make pull to refresh not perform regular reload (with cache revalidation)

Pull-to-refresh action on Android is currently handled as a
regular reload, which causes revalidation of cached contents,
however the action would usually imply that the user wants to
refresh the 'contents' rather than reloading everything (e.g.
to reset the page contents when something's screwed up).

这段话中说到,用户刷新一个页面通常都不是为了重新请求每个资源文件看是不是过期了,而仅仅是为了重置一下页面的状态,所以要做这个优化。下面是当时测试效果的对比演示,左旧右新:

 

可以看到,左侧有明显的加载白屏阶段,而右侧没有。

在 16 年 5 月份,Chrome 把该刷新行为应用到了 PC 端,从 Chrome 54 开始默认启用。我写了一个测试 demo,在 Chrome 54 之前,刷新这个 demo 后效果是这样的:

所有的资源都会被发起条件请求从而返回 304 响应,而在 Chrome 54 里,刷新这个 demo 后效果成了:

只有页面本身被发起了条件请求,所有引用的子资源都直接读取了缓存,也就是说,实际上刷新这个页面只触发了一个 HTTP 请求。

额外小技巧

从 Chrome 56 开始,你可以通过网络面板新增的 is:from-cache 过滤条件来过滤出直接读取缓存的请求(即没有发送真实的 HTTP 请求的请求),还可以利用它的反向过滤找出发送了真实请求的请求,像下面这样(还是上面的 demo):

这个过滤条件是我向 Chrome 提议的。

不知道你们注意过没有,除刷新外,常规加载一个网页的途径有两种,最常见的一种是通过点击其他页面的超链接(包括浏览器书签)进入当前页面,还有一种是在浏览器地址栏上输入网址并回车(高级用户),这两者在发送请求上也是有区别的。前者是不会发起任何条件请求的(除非缓存过期),而后者是会为页面资源本身发起条件请求的(你可以用上面的 demo 做测试),Chrome 新的这个刷新机制其实就是把刷新改得和在地址栏回车一样了。鉴于现如今的大多页面都是动态页面(没有 Cache-Control/Expires/Last-modified 响应头),不会被缓存,所以如今这三者在 Chrome 上的差别已经很小了。

如果你已经升级到了 Chrome 的最新版,没法找到 Chrome 54 之前的版本来做对比测试,可以试试通过停用 chrome://flags/#enable-non-validating-reload-on-normal-reload 选项来切回老版的刷新,不过这个选项在 Chrome 56 里已经被彻底删除了:

读到这里,有同学就想问了,“难道 Chrome 这样做不违反 HTTP 协议吗?”。并没有,HTTP 协议只会规定客户端应该怎么发一个条件请求,服务器应该怎么响应这个条件请求,但不会规定应用程序何时应该发送条件请求。

那 location.reload() 呢,也会改成新版刷新吗?从 Chrome 56 开始 location.reload() 也会使用新版刷新。HTML 规范并没有明确的说明 location.reload() 应该如何对待缓存,只略略提到了一句:

User agents may allow the user to explicitly override any caches when reloading.

这句话应该是给 Firefox 的 location.reload(true) 准备的。

那对用户来说,这个改动向后兼容吗?从我注意到 Chrome 的这个改动后,一直以为这是 Chrome 的 bug,但提 bug后被告知这是有意的。我当时觉的这个改动太激进了,毕竟打破了二十年多年的浏览器传统,一定会有用户反馈不兼容问题的。但直到这个改动进入稳定版后,也没有一个人反馈。。。仿佛全世界只有我一个人注意到了这个改动。

但对开发者来说,其实这个改动的确是有点不向后兼容的。比如某个带有特定版本号的资源在发布到 daily 环境后,是可以不换版本号(URL)反复覆盖式更新的,但你在浏览器里刷新却看不到效果,只能借助于开发者工具的 Disable cache 功能。不过最终用户是没这个问题的,因为线上是无法覆盖式发布的。

所以现在我的看法变了,Firefox 和其他浏览器应该变的像 Chrome 一样,Cache-Control: immutable 已经几乎没有价值了(除非我漏掉了某个点),能让所有的网页变的更快,为什么不呢。

俗话说的好,“前端有三宝,清缓存、清 cookie、换个浏览器”。以后在 Chrome 里单纯的刷新是真的不行了,要教用户怎么“强制刷新/跳过缓存刷新”了。

可以看到自己公司 CDN 日志的同学们,可以看看最近 304 响应的占比有没有大幅减少,不过国内的话也许需要等国产浏览器的内核更新后才行。

关于缓存和 Chrome 的“新版刷新”的更多相关文章

  1. chrome最新版49跨域问题

    chrome最新版49跨域问题   一.最新版49要用新的参数 加--user-data-dirwindows:"C:\Program Files\Google\Chrome\Applica ...

  2. vue的组件缓存(返回页面不刷新)

    每次使用返回是页面总是会刷新 导致了一些体验上的不愉快 现在 发现vue中的一个很方便的方法还可以用来优化性能就是: keep-alive缓存组件 <router-view v-if=" ...

  3. 关于如何刷新清除某个特定网站的缓存---基于Chrome浏览器

    今天工作时又发现了一个小技巧 1.打开一个网站如:百度 2.打开F12开发者模式 3.右键浏览器的刷新按钮,会出现三个选项:正常重新加载,硬性重新加载,清空缓存并硬性重新加载 正常重新加载 Ctrl+ ...

  4. [Web前端] mac chrome 浏览器强制刷新,清除浏览器缓存

    本文链接:https://blog.csdn.net/zeroyulong/article/details/79806156 mac 强制刷新:command+shift+r mac 普通刷新:com ...

  5. 【原创】Chrome最新版(53-55)再次爆出BUG!

    前言 今年十月份,我曾发布一篇文章<Chrome53 最新版惊现无厘头卡死 BUG!>,不过那个BUG在最新的 Chrome 54 中已经修正. 而今天即将发布的Chrome弱智BUG: ...

  6. Sublime3和Chrome配置自动刷新网页【实测可用】

    SublimeText2下的LiveReload在SublimeText3下无法正常使用,本文整理SublimeText3安装LiveReload的方法.win7下实测可用! 安装成功后,就不需要再手 ...

  7. 清除IE中Ajax缓存,Chrome不需要

    做项目的时候,会遇到这种情况,通过ajax从后台获取的数据在chrome上显示的是最新的,而在IE上却是以前的数据,这是为什么呢,在我百般调试下终于发现原来是因为IE的ajax缓存的原因,于是加上这段 ...

  8. 用Meta 取消流量器缓存实现每次访问都刷新页面方便调试

    如果想禁止浏览器从本地缓存中调阅页面,可以设置网页不保存在缓存中,每次访问都刷新页面,下面是Meta在这方便的用法,需要的朋友可以参考下: <!-- 禁止浏览器从本地缓存中调阅页面.--> ...

  9. IE/firefox/chrome 每次都刷新

    IE FIREFOX 1.在firefox的地址栏上输入about:config回车2.找到browser.cache.check_doc_frequency选项,双击将3改成1保存即可. 那么这个选 ...

随机推荐

  1. for循环和foreach循环遍历集合的效率比较

    先上代码 package com.test; import java.util.ArrayList; import java.util.LinkedList; import java.util.Lis ...

  2. ASP+中文显示之两种解决方法

    作者刚開始写ASP+程序时候碰到的第一个比較大的问题就是中文显示问题,执行后发现ASP+从数据库中读  取出来的中文所有变成了?????,有点相似jsp中的这个频率出现最高的中文显示问题了,查了资料发 ...

  3. Push rejected: Push to origin/master was rejected错误解决方案

    解决方案如下: 1.切换到自己项目所在的目录,右键选择GIT BASH Here,Idea中可使用Alt+F12 2.在terminl窗口中依次输入命令: git pull git pull orig ...

  4. K8S集群技术

    1.快速部署K8S环境 k8s-m :10.0.0.11   k8s-n1 :10.0.0.12   k8s-n2 :10.0.0.13 2.所有节点安装docker环境及依赖 2.1 上传docke ...

  5. 英特尔关闭PC计算卡项目—插个卡片就能升级个人电脑

    在 2017 年的美国国际消费电子展上,电脑芯片巨头英特尔公司曾经推出一个名为“计算卡”的新产品,相当于把个人电脑的重要零部件整合到了一张信用卡大小的卡片设备中,未来用户升级个人电脑,只需要拔下旧卡片 ...

  6. 微服务领域是不是要变天了?Spring Cloud Alibaba正式入驻Spring Cloud官方孵化器!

    引言 微服务这个词的热度自它出现以后,就一直是高烧不退,而微服务之所以这么火,其实和近几年互联网的创业氛围是分不开的. 与传统行业不同,互联网企业有一个特点,那就是市场扩张速度非常之快,可能也就是几天 ...

  7. PHP获取项目所有控制器方法名称

    PHP获取项目所有控制器方法名称 //获取模块下所有的控制器和方法写入到权限表 public function initperm() { $modules = array('admin'); //模块 ...

  8. c选择排序算法

    void selectsort(int *a,int len) { int i,j; int temp; for(i=0;i<len-1;i++) { for(j=i+1;j<len;j+ ...

  9. static与final区别

    1. final   final类不能被继承,没有子类,final类中的方法默认是final的 final方法不能被子类的方法复盖,但可以被继承 final成员变量表示常量,只能被赋值一次,赋值后不能 ...

  10. Shell命令-系统信息及显示之dmesg、uptime

    文件及内容处理 - dmesg.uptime 1. dmesg:显示开机信息 dmesg命令的功能说明 dmesg 命令用于显示开机信息.kernel 会将开机信息存储在 ring buffer 中. ...