关于缓存和 Chrome 的“新版刷新”
在读本文前你要确保读过我的上篇文章《扼杀 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 的“新版刷新”的更多相关文章
- chrome最新版49跨域问题
chrome最新版49跨域问题 一.最新版49要用新的参数 加--user-data-dirwindows:"C:\Program Files\Google\Chrome\Applica ...
- vue的组件缓存(返回页面不刷新)
每次使用返回是页面总是会刷新 导致了一些体验上的不愉快 现在 发现vue中的一个很方便的方法还可以用来优化性能就是: keep-alive缓存组件 <router-view v-if=" ...
- 关于如何刷新清除某个特定网站的缓存---基于Chrome浏览器
今天工作时又发现了一个小技巧 1.打开一个网站如:百度 2.打开F12开发者模式 3.右键浏览器的刷新按钮,会出现三个选项:正常重新加载,硬性重新加载,清空缓存并硬性重新加载 正常重新加载 Ctrl+ ...
- [Web前端] mac chrome 浏览器强制刷新,清除浏览器缓存
本文链接:https://blog.csdn.net/zeroyulong/article/details/79806156 mac 强制刷新:command+shift+r mac 普通刷新:com ...
- 【原创】Chrome最新版(53-55)再次爆出BUG!
前言 今年十月份,我曾发布一篇文章<Chrome53 最新版惊现无厘头卡死 BUG!>,不过那个BUG在最新的 Chrome 54 中已经修正. 而今天即将发布的Chrome弱智BUG: ...
- Sublime3和Chrome配置自动刷新网页【实测可用】
SublimeText2下的LiveReload在SublimeText3下无法正常使用,本文整理SublimeText3安装LiveReload的方法.win7下实测可用! 安装成功后,就不需要再手 ...
- 清除IE中Ajax缓存,Chrome不需要
做项目的时候,会遇到这种情况,通过ajax从后台获取的数据在chrome上显示的是最新的,而在IE上却是以前的数据,这是为什么呢,在我百般调试下终于发现原来是因为IE的ajax缓存的原因,于是加上这段 ...
- 用Meta 取消流量器缓存实现每次访问都刷新页面方便调试
如果想禁止浏览器从本地缓存中调阅页面,可以设置网页不保存在缓存中,每次访问都刷新页面,下面是Meta在这方便的用法,需要的朋友可以参考下: <!-- 禁止浏览器从本地缓存中调阅页面.--> ...
- IE/firefox/chrome 每次都刷新
IE FIREFOX 1.在firefox的地址栏上输入about:config回车2.找到browser.cache.check_doc_frequency选项,双击将3改成1保存即可. 那么这个选 ...
随机推荐
- Django的认证系统
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- asp.net webapi中helppage
今天研究了下webapi,发现还有自动生成接口说明文档提供测试的功能 参考:https://docs.microsoft.com/en-us/aspnet/web-api/overview/getti ...
- gulp 自动ftp至服务器时,处理开发 测试服务器地址问题
var gulp=require('gulp'), babel = require('gulp-babel'), gulpSequence = require('gulp-sequence'), ht ...
- EasyUI datagrid formatter 属性
easyui的formatter属性可以帮助我们更加灵活的显示数据库中的数据. 比如,我有一个启用禁用字段,使用数字表示,1表示启用,2表示禁用,展示给客户的时候我当然希望是中文的形式. 只需要写这么 ...
- Firefox 中出现的 “Network Protocol Error”怎么办
Mozilla Firefox 多年来一直是我的默认 Web 浏览器,我每天用它来进行日常网络活动,例如访问邮件,浏览喜欢的网站等.今天,我在使用 Firefox 时遇到了一个奇怪的错误.我试图在 R ...
- vue应用或者是项目其实就是 实例(完成基本逻辑) + 组件(单文件组件,全局组件,局部组件,内置组件)来完成 ;
以上! 组件里面包含HTML,css, js,也就是一个完整的功能!
- @Valid注解的使用(转)
原文地址:http://blog.csdn.net/xzmeasy/article/details/76098188 @Valid注解用于校验,所属包为:javax.validation.Valid. ...
- LDOOP ADD_PRINT_TEXT多页项
纯文本打印(ADD_PRINT_TEXT)项超过宽度且高度不够的情况下,不会隐藏后面的内容,而是会分到下一页.分页数量和每页显示内容多少 和设置的纯文本打印项高度有关.LODOP.SET_PRINT_ ...
- Vivado中VIO核使用
前言 使用场景:在使用In system debug时需要使用按键触发查看相关信号,但不想用板子上的按键. VIO:Virtual input output,即虚拟IO. 主要用作虚拟IO使用:VIO ...
- rest framework 解析器,渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 请求体相关字段: Accept:指定了接收的数据类型 Conte ...

