← 返回题目列表

什么是 bfcache?如何让页面更容易命中浏览器前进后退缓存?

高频 中等 第 8 / 29 题 更新于 2026/07/29
性能优化bfcache导航性能浏览器缓存

简化版

bfcache 是浏览器在前进/后退导航时保存页面完整快照的缓存,命中后可几乎瞬间恢复页面状态。优化关键是避免阻止缓存的行为,比如不必要的 unload 监听、敏感页面错误缓存策略、未关闭的连接或页面生命周期处理不当。

详细版

bfcache 不同于 HTTP 缓存。HTTP 缓存缓存资源文件,bfcache 缓存整个页面状态,包括 DOM、JS 堆和滚动位置。用户从列表进详情再返回列表时,bfcache 命中能显著改善体验。

页面要监听 pageshowpagehide,通过 event.persisted 判断是否从 bfcache 恢复或进入缓存。离开页面时应暂停计时器、视频、连接和敏感任务,恢复时重新校验必要数据。

面试回答要强调:不要用 unload 做清理,优先使用 pagehide;同时用 Chrome DevTools bfcache 测试工具检查阻塞原因。

完整版教学

一、bfcache 优化的是返回体验

很多网站只优化首次进入,却忽略“列表页 -> 详情页 -> 返回列表页”这个高频路径。bfcache 命中时,浏览器可以恢复之前页面快照,而不是重新请求 HTML、重新执行 JS、重新渲染列表。

普通返回:请求 HTML -> 下载资源 -> 执行 JS -> 恢复列表
bfcache:恢复快照 -> 几乎立即可交互

记忆钩子:HTTP 缓存存资源,bfcache 存页面快照。

二、bfcache 和 HTTP 缓存不是一回事

HTTP 缓存关注单个资源响应,比如 JS、CSS、图片或接口;bfcache 关注整个页面的内存状态。即使 JS 文件都命中 HTTP 缓存,页面仍要重新执行脚本和恢复状态。

维度HTTP 缓存bfcache
缓存对象资源响应完整页面快照
典型场景静态资源复用前进后退导航
恢复状态需要应用自己恢复DOM/滚动/JS 状态可恢复
失效原因缓存头、版本页面生命周期和安全限制

如果列表页重建需要 1.5 秒,bfcache 命中可能让返回体感接近 0.1 秒。对电商、内容流、搜索结果页,这个收益很真实。

三、页面生命周期事件要用对

unload 事件不可靠,也常使页面不适合进入 bfcache。更推荐使用 pagehidepageshow,并根据 persisted 判断缓存状态。

window.addEventListener('pagehide', (event) => {
  pauseRealtimeWork()
})

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    refreshIfNeeded()
  }
})

pagehide 表示页面正在被隐藏或离开,可能进入 bfcache;pageshow 在页面首次显示和从 bfcache 恢复时都会触发。恢复后可以轻量校验数据,而不是无脑整页刷新。

四、哪些行为会降低 bfcache 命中

浏览器会避免缓存可能不安全或无法正确恢复的页面。不同浏览器规则会演进,但一些高风险行为长期值得注意。

行为问题建议
unload 监听阻碍缓存且不可靠改用 pagehide/visibilitychange
未关闭连接状态难冻结pagehide 暂停,pageshow 恢复
敏感页面返回可能暴露数据明确缓存策略和重新校验
打开的锁或设备状态不可恢复离开时释放

例如聊天页保持 WebSocket 并不一定永远不能缓存,但需要在页面隐藏时处理连接和状态。工程上要看 DevTools 给出的具体阻塞原因。

五、从 bfcache 恢复后要处理数据新鲜度

bfcache 恢复的是旧页面快照。对静态内容这是优点;对订单状态、余额、权限等页面,旧数据可能不合适。正确做法不是禁用 bfcache,而是恢复后做必要校验。

window.addEventListener('pageshow', (event) => {
  if (event.persisted && Date.now() - lastFetchAt > 30000) {
    refetchSummary()
  }
})

比如 30 秒内返回列表直接恢复,超过 30 秒再轻量刷新数据。这样既保留快速返回体验,又避免长时间旧数据误导用户。

六、如何测试和监控 bfcache

Chrome DevTools 的 Application 面板提供 Back/forward cache 测试,可以列出页面是否可缓存以及阻塞原因。真实用户侧也可以通过 pageshow.persisted 统计恢复比例。

window.addEventListener('pageshow', (event) => {
  report('pageshow', { bfcacheRestore: event.persisted })
})

假设详情返回列表每天 10 万次,bfcache 命中率从 20% 提到 70%,就有 5 万次返回体验从重建变成快照恢复。这个指标适合和页面跳出、转化路径一起观察。

七、常见误区与追问

  • 误区:bfcache 就是 HTTP 强缓存。 它保存完整页面快照,不只是资源文件。
  • 误区:返回时必须重新加载才能保证数据新鲜。 可以恢复后按条件轻量校验,不必牺牲所有返回体验。
  • 误区:unload 是最适合做离开清理的事件。 它不可靠且可能阻碍 bfcache,应优先使用 pagehide。
  • 追问:如何判断页面从 bfcache 恢复?pageshow 事件里检查 event.persisted
  • 追问:哪些页面不适合缓存? 高敏感信息、状态难恢复或安全要求明确禁止恢复的页面要谨慎。
  • 追问:如何提升命中率? 移除 unload、正确处理连接和生命周期、用 DevTools 修复阻塞原因。

八、加强记忆

bfcache 按“快照、生命周期、新鲜度、命中率”记:它让前进后退恢复完整页面状态,不等同于 HTTP 缓存;页面用 pagehide/pageshow 管暂停和恢复,用条件刷新处理数据新鲜度,再通过 DevTools 和 RUM 统计命中率。