一、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. cookie sessionStorage localStorage 之间的关系

    先说一个cookie 因为HTTP是无状态的 所以cookie诞生 用于保存会话信息 大小 4096b 一般在4095b以内 数量限制 20 -50 根据浏览器不同 操作的是一个字符串 可以设置参数 ...

  2. string用法总结

    要想使用标准C++中的string类,必须要包含#include <string> 注意是<string>而不是<string.h>,带.h的是C语言中的头文件 s ...

  3. CRC检验

    CRC(循环冗余检验码) 基本原理:在K位信息码后面加上R位校验形成N位编码(即CRC码),事先需要约定一个生成多项式G(x),校验码生成过程:将K位信息码向左移动R位然后mol(其实就是按位异或)上 ...

  4. tp5命令行基础

    命令行工具需要在命令行下面执行,请先确保你的php.exe已经加入了系统环境变量Path. 要执行命令,首先进入命令行,并切换当前目录到应用的根目录(也就是think文件所在目录)下面,执行: php ...

  5. C#基础(五)--枚举的含义及其应用

    本章讲解如下枚举的如下几个知识点:    1.什么是枚举?    2.枚举是值类型还是引用类型?    3.如何定义枚举?    4.枚举的好处?    5.枚举在实际系统开发过程中的用处?    一 ...

  6. Redis服务启动失败,提示:redis-server:command not found

    今天我开始做主从复制的集群模式的测试,所以需要再装一个Linux操作系统,我在虚拟机里已经安装了一个Linux操作系统,Redis也已经配置好了.今天打算再安装一个Linux操作系统,Linux系统的 ...

  7. 在ubtunu使用apt-get安装和配置freeradius

    安装freeradius之前先要确保已经安装了mysql.因为后来要用到.没有安装使用apt-get来安装 apt-get install mysql-server 然后就是安装freeradius的 ...

  8. 浏览器通过file://访问文件和通过http://访问文件有什么区别

    1.file协议用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件一样,注意它是针对本地(本机)的,简单来说,file协议是访问你本机的文件资源.http访问本地HTML,是在本地 ...

  9. ffmpeg转码使用硬件加速

    需求源于手机拍摄的视频,默认参数码率较大,拍摄的文件体积较大,不便于保存和转发.手机默认拍照的720P视频,默认码率达到4M,实际上转成1M就差不多了.FFmpeg默认的转码是使用软件解码,然后软件编 ...

  10. 使用jvisualvm来远程观察Java程序及jvisualvm插件[转]

    jvisualvm是JDK自带的监控JVM运行状况的工具,利用jvisualvm可以查看JVM的运行.GC情况:线程的运行情况:内存中类及实例的情况等. 使用jvisualvm来远程观察Java程序, ...