BFcache是什么东西


扯点闲

作为一个前端,居然是最近才知道这个东西,真的是老了,好奇心也降低了。

BFCache简介

BFCache(Back-Forward Cache)可以翻译成往返缓存。这是火狐用来加速前进后退操作 时页面展示时使用的一种技术。

阻止BFCache

MDN里里说到有下面几种方式可以阻止,同时我们也可以看出是从火狐1.5开始,它有这个技术的

  • 页面监听了 unload 或者 beforeunload 事件;
  • 页面设置了 “cache-control: no-store”.
  • 网站使用 HTTPS 同时页面至少满足以下一个条件:
    • “Cache-Control: no-cache”
    • “Pragma: no-cache”
    • 设置请求头 “Expires: 0” 或者 “Expires” 的值为 “Date” 之前的值 (除非 “Cache-Control: max-age=” 也被设置了);
  • 页面在用户前进后退的时候还没有完全加载完或者它有正在进行的网络请求,比如 XMLHttpRequest;
  • 页面正在进行IndexedDB操作;
  • 顶层的页面包含有frame,并且这些frame由于这里列的任何一条原因而不能被缓存;
  • 页面在一个frame内,并且用户在这个frame内跳转到了一个新的网页,这里将被缓存的是新载入的网页

怎么查看

在firebug的net选项卡,点击那个向下的小箭头,会有一个show BFCache Response选项,选中它即可。在这个任意页面点击链接,然后点击导航栏的前进后退,你就能看到net下面的请求列表里类似“200 OK (BFCache)”这样的请求, then u got it。

书上说,网上说

《Javascript高级程序设计》这本书里讲到这个缓存不仅保存页面数据,还保存了DOM和JS的状态,整个页面会保存在内存中。

同时如果页面是位于BFCache中,那么再次打开该页面时不会触发load事件

火狐的MDN里说到如果页面是从BFCache里取到的,Dom和js对象以及setTimeout,setInterval这些都是上一次访问时的状态。

也就是说如下的代码在前进后退页面时,这个i会不停的增加, 同时“I am loaded”这句只会出现一次。

;(function () {
  var i = 0

  window.addEventListener('pageshow', function () {
    alert(i++)
    alert('I am loaded')
  })

  window.addEventListener('load', function () {
    alert('I am loaded')
  })
})

那么事实是这样么?

访问这个页面,在火狐(14.0.1 Mac)下i始终都是0,同时每次都会触发load事件,在firebug里看确实是从BFCache里取的,最奇葩的是persisted始终都是false。

同时书上说safari、opera、chrome都是支持这个的,但是从这个简单的页面上来看,最新的opera(12.02 Mac)压根没有pageshow/pagehide这两个事件,safari和chrome和支持这个事件,但是跟火狐的效果是一样的。

真相是什么?

毁了三观么,还没有 :),我猜测是火狐在开发过程中发现,保存js和Dom状态这事有点像是热心办了坏事,还弄得开发者多加些逻辑,后来就索性,不再保存js和Dom状态,只是存资源(html内容,css,js…),这样呢,开发者只要还继续用load/unload事件就能万事大吉。至于《Javascritp高级程序设计》的错误,书始终是前端界的好书,出书的时候这玩意还是正常的。

参考链接们:


推荐文章