关于缓存和 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保存即可. 那么这个选 ...
随机推荐
- 《精通Spring+4.x++企业应用开发实战》读后感
引言 还记得大三时上培训班的是时候,当时的培训老师说自己是本地讲解spring最好的讲师,但是后来等我实习了看了<Spring 3.x 企业应用开发实战>以及后续版本<精通Sprin ...
- ThreadLocal的使用及原理分析
文章简介 ThreadLocal应该都比较熟悉,这篇文章会基于ThreadLocal的应用以及实现原理做一个全面的分析 内容导航 什么是ThreadLocal ThreadLocal的使用 分析Thr ...
- 错误ERROR datanode.DataNode (DataXceiver.java:run(278)) - hadoop07:50010DataXceiver error processing unknown operation src:127.0.0.136479 dst:127.0.0.150010
原因: Ambari 每分钟会向datanode发送"ping"连接一下去确保datanode是正常工作的.否则它会触发alert.但是datanode并没有处理空内容的逻辑,所以 ...
- flink window的early计算
Tumbing Windows:滚动窗口,窗口之间时间点不重叠.它是按照固定的时间,或固定的事件个数划分的,分别可以叫做滚动时间窗口和滚动事件窗口.Sliding Windows:滑动窗口,窗口之间时 ...
- js 设备判断(移动端pc端 安卓ios 微信)
苹果安卓判断 $(function () { var u = navigator.userAgent, app = navigator.appVersion; var isAndroid = u.in ...
- slice()和splice()区别
1.slice(start,end):方法可从已有数组中返回选定的元素,返回一个新数组,包含从start到end(不包含该元素)的数组元素. 注意:该方法不会改变原数组,而是返回一个子数组,如果想删除 ...
- Loj #2495. 「AHOI / HNOI2018」转盘
Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...
- pytorch Debug —交互式调试工具Pdb (ipdb是增强版的pdb)-1-在pytorch中使用
参考深度学习框架pytorch:入门和实践一书第六章 以深度学习框架PyTorch一书的学习-第六章-实战指南为前提 在pytorch中Debug pytorch作为一个动态图框架,与ipdb结合能为 ...
- zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- Jenkins持续集成实践之java项目自动化部署
关于Linux安装Jenkins可以参考我的这篇博文Ubuntu16.04环境安装jenkins 1.安装部署插件 进入插件管理,并搜索该插件Deploy to container Plugin进行安 ...

