一、bfcache 基本概念

现代浏览器在根据历史记录进行前进/后退操作时,会启用缓存机制,名为“bfcache”(back-forward cache,往返缓存),它使页面导航非常快。直到用户关闭浏览器,这个缓存状态才会被删除。

从 MDN 上得知,支持 bfcache 特性的 Firefox 浏览器,对于一个简单的浏览器会话,会缓存全部页面到内存中,包括他们的JavaScript状态。直到用户关闭浏览器,这个缓存状态才会被删除。bfcache 是一种浏览器优化,但是 HTML 标准中并未指定浏览器如何进行缓存,因此不同的浏览器的缓存策略也与 Firefox 的不同。

MDN 上还指出一些Firefox不会缓存页面的情况,如下:

  • 页面绑定了 unload 或 beforeunload 事件;
  • 页面设置“cache-control: no-store”;
  • 站点是HTTPS且页面至少存在一个如下设置:
    • “Cache-Control: no-cache”
    • “Pragma: no-cache”
    • “Expires: 0”或赋予“Expires”一个相对于“Date”的过去日期(除非“Cache-Control: max-age=”也定义了)
  • 当用户导航离开页面时,该页面没有完全加载,或因为其他原因等待网络(例如,XMLHttpRequest);
  • 页面执行IndexedDB事务;

二、不同浏览器中的不同策略

1. 测试设计

测试页面有两个,代码分别如下。

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Page 1</title>
</head>
<body>
<img src="//static.symind.top/images/fruit.png">
<p>Page 1.</p>
<a href="page2.html">Go to page 2.</a>
<script>
var p = document.createElement('p');
document.body.appendChild(p); var i = 0;
var time = setInterval(function () {
p.innerText = i++;
}, 1000); window.onload = function () {
alert('onload...');
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Page 2</title>
</head>
<body>
<p>Page 2.</p>
<a href="javascript:goback()">后退</a>
<script>
function goback () {
window.history.back();
}
</script>
</body>
</html>

2. 测试结果

浏览器 版本 是否缓存 DOM 是否缓存页面中的静态资源 是否缓存 js 执行状态 是否触发 load 事件
Desktop Chrome 60.0.3112.101(正式版本)(64 位)
Desktop Firfox 58.0.2(64位)
QQ浏览器 8.2.0.3950(安卓版)

注意:缓存 js 执行状态表示离开当前页面时,js 将停止执行,返回后会继续执行。现在的很多手机浏览器并非使用 bfcache 特性来提高页面导航速度,而是将每个页面都封装成类似于一个 WebView 的形式,如,小米手机浏览器。而使用这种方式的浏览器,即使离开页面后,js 仍会继续执行,且不会触发下面介绍的 pageshow 与 pagehide 事件。

备注:在 Desktop Chrome 触发了“往返缓存”时,在开发者工具中能看到 HTTP 请求的状态码(Status Code)为 200 OK (from disk cache),如下图。

 三、新的事件

尽管由于内存中保存了整个页面的状态,不触发load事件也不会导致什么问题,但为了更形象地说明 bfcache 的行为,浏览器还提供了一些新事件 pageshow 和 pagehide。

1. pageshow 事件

该事件与 load 事件相似,但是它在页面的每次加载时都会触发(当页面触发 bfcache 特性使用缓存加载时 load 事件不会被触发)。页面第一次加载时,pageshow 事件紧随着 load 事件之后触发。pageshow 使用一个布尔类型属性名为 persisted,在初始化加载时它的值为 false。当页面并非初始化加载时,它的值为 true(话句话说,当页面被缓存时它的值为 true)。

2. pagehide 事件

如果你想在用户导航离开页面时定义一些行为,但你不想使用 unload 事件(这会导致页面不会被缓存),你可以使用新的 pagehide 事件。与 pageshow 事件相同,pagehide 事件也使用一个布尔类型属性名为 persisted。如果页面没有被缓存,该属性的值为 false,如果页面被缓存,该属性的值为 true。当该属性的值为 false 时,unload 事件处理器进行处理,反之,pagehide 事件会在 unload 事件触发后立即触发。

四、实际业务相关

1. 业务背景简述

第一个网页提供根据城市提供服务种类列表,假定为 catePage。点击其中一种服务种类将跳转至该服务种类下的详细服务列表,假定为 servicePage。其中在 servicePage 中可以切换城市,业务要求在 servicePage 切换城市返回到 catePage 时要求刷新该页面的城市信息。如下图所示。

2. 解决方案

解决的思路很简单,当页面处于非初始化加载时,进行相关的进行更新城市信息的操作。

对于使用 bfcache 的浏览器可以添加 pageshow 事件,并结合该事件中的 persisted 属性在对于非初始化加载的情况下进行对城市信息的相关处理。

而对于小米浏览器这样,将每个页面都封装成类似于一个 WebView 的形式的手机,使用 visibilitychange 事件。该事件配合 load 事件能够判断是否为初始化加载,配合 document.hidden 属性能够判断页面显示状态。

参考文章

1. Using Firefox 1.5 caching:https://developer.mozilla.org/en-US/Firefox/Releases/1.5/Using_Firefox_1.5_caching

2. 浏览器前进/后退缓存(BF Cache): http://harttle.land/2017/03/12/backward-forward-cache.html

3. Can I use:https://caniuse.com/#search=pageshow

浏览器的 bfcache 特性的更多相关文章

  1. 浏览器对HTML5特性检測工具Modernizr

    近期在做公司移动端运营的项目,需求中多处地方都会涉及动画. 相信非常多前端开发都会有这样的感触,对CSS3中的动画属性非常熟悉,可是因为对动画运动过程的理解不深入,经常仅仅能望而止步.CSS3中动画这 ...

  2. [转]JavaScript快速检测浏览器对CSS3特性的支持

    转自:https://yuguo.us/weblog/detect-css-support-in-browsers-with-javascript/ ------------------------- ...

  3. 第四节:教你如何快速让浏览器兼容ES6特性

    写在正文前,本来这一节的内容应该放在第二节更合适,因为当时就有同学问ES6的兼容性如何,如何在浏览器兼容ES6的特性,这节前端君会介绍一个抱砖引玉的操作案例. 为什么ES6会有兼容性问题? 由于广大用 ...

  4. 解决浏览器兼容ES6特性

    为什么ES6会有兼容性问题? 由于广大用户使用的浏览器版本在发布的时候也许早于ES6的定稿和发布,而到了今天,我们在编程中如果使用了ES6的新特性,浏览器若没有更新版本,或者新版本中没有对ES6的特性 ...

  5. 解决让浏览器兼容ES6特性

    为什么ES6会有兼容性问题? 由于广大用户使用的浏览器版本在发布的时候也许早于ES6的定稿和发布,而到了今天,我们在编程中如果使用了ES6的新特性,浏览器若没有更新版本,或者新版本中没有对ES6的特性 ...

  6. JavaScript快速检测浏览器对CSS3特性的支持情况

    项目中使用动画效果在IE9下不支持,所以写了个判断浏览器是否支持动画的函数,进而扩展到下面判断浏览器支持任一特定CSS3属性的函数. function supportAnimation(){ var ...

  7. JS-让浏览器兼容ES6特性

    babel:将 ES6 翻译为 ES5 PS:ie 还不支持 import 和 export 还是用 gulp 打包一下吧

  8. 前端工具-让浏览器兼容ES6特性

    babel:将ES6翻译为ES5 问题: 可以处理import和export么? 不能,还是用Rollup或者webpack打包一下吧 可以处理Promise么? 不能,还是使用babel-plugi ...

  9. 各大浏览器内核特性及对应的Browserhacks举例

    1.浏览器内核指的是什么? 简化的浏览器=用户界面+渲染引擎+js解析引擎+数据存储+网络部件 而通常所说的浏览器内核指的是页面渲染引擎(rendering engine). 2.渲染引擎 The r ...

随机推荐

  1. 译-BMC Remedy Action Request System权限控制概述

    原文链接:Access control overview 说明: BMC Remedy Action Request System是BMC ITSM产品平台,简称AR 或者Remedy,可实现基于IT ...

  2. jQuery-niceScroll滚动条错位问题

    虽然niceScroll插件很好用,毕竟它不依赖css,只是单纯的js就可以设置出好看的滚动条了. 最近在项目中使用到niceScroll,而且在表格里有横滚动条,竖滚动条时很容易错位,就是滚动条会悬 ...

  3. 04_Javascript初步第三天

    事件 内联模型.脚本模型,DOM2级模型 <!--内联模型--> <input type="button" value="bt1" oncli ...

  4. PHP获取字符串编码与转码

    (⊙o⊙)-编辑器保存的是utf8的文档取出来的字符串是gbk编码?问题很多,字符串转换为utf8的话在浏览器输出乱码 $e=mb_detect_encoding($d,array('GB2312', ...

  5. dos2unix和unix2dos

    dos2unix将windows格式的文件转换为linux格式的文件. unix2dos将linux格式的文件转换为windows格式的文件. dos2unix和unix2dos会转换windows和 ...

  6. FTP工具

    上传本地资源到FTP服务器,可以使用LeapFTP软件.左侧为本地资源,右侧为FTP资源.输入用户名,密码,连接后直接拖动即可. 为本地资源建立FTP,可以方便进行设备升级.文件传输等.

  7. BZOJ 2882: 工艺 [后缀自动机+map]

    Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工 ...

  8. POJ1741Tree [点分治]【学习笔记】

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 20098   Accepted: 6608 Description ...

  9. element ui 1.4 升级到 2.0.11

    公司的框架 选取的是 花裤衩大神开源的 基于 element ui + Vue 的后台管理项目, 项目源码就不公开了,记录 分享下 步骤 1. 卸载 element ui 1.4的依赖包 2. 卸载完 ...

  10. Netty(一):入门篇

    匠心零度 转载请注明原创出处,谢谢! 说在前面 上篇文章对Netty进行了初探:Netty初探,主要介绍了下我们为什么需要学习netty.netty介绍等:本篇文章接着上篇文章的内容.本篇为了方便大家 ...