You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在popstate事件与fetch场景下利用浏览器Back-Forward Cache(BF-cache)

问题解答

你当前的实现场景下,没有办法让浏览器自动调用BF-cache来加载pushState对应的历史页面内容。

原因说明

BF-cache(往返缓存)是浏览器为「完整跨页面导航」设计的缓存机制:只有当用户在不同的完整页面之间跳转时,浏览器才会将离开的页面的完整DOM、JS运行状态、滚动位置等信息快照存入BF-cache,后退时直接恢复整个页面上下文。
而你现在用的是单页前端路由方案,全程都在同一个页面上下文里运行,所有通过pushState添加的历史条目都属于当前页面的内部状态,浏览器不会为这些条目生成独立的BF-cache快照,自然也没办法在popstate触发时自动调用BF-cache加载内容。

替代实现方案

你可以自己实现轻量状态缓存,达到和BF-cache一致的使用体验:

  • 方案1:复用History API的state存储
    你当前pushState的第一个参数是空值,可以直接把路由对应的页面内容、滚动位置等状态存在这个参数里,popstate触发时直接读取状态渲染,不需要重新发起请求:
// 点击跳转时存储状态
window.history.pushState(
  {
    pageContent: json.html, // 你要替换的页面 markup 内容
    scrollPos: window.scrollY // 当时的滚动位置等其他状态
  },
  '',
  t.href
);

// popstate 时直接读取缓存状态
window.addEventListener('popstate', function(e) {
  if (e.state) {
    // 直接用缓存的内容替换页面
    document.querySelector('#content-container').innerHTML = e.state.pageContent;
    // 恢复滚动位置
    window.scrollTo(0, e.state.scrollPos);
    return;
  }
  // 没有state的话再走 fallback 逻辑,比如发起请求加载对应页面内容
});
  • 方案2:自建内存缓存池
    如果需要缓存的内容较多、或者要跨会话缓存,可以用一个全局Map对象做缓存,key为路由URL,value为对应的页面状态:
const pageCache = new Map();

// 点击跳转加载完成后存缓存
pageCache.set(t.href, {
  pageContent: json.html,
  scrollPos: window.scrollY
});

// popstate 时先查缓存
window.addEventListener('popstate', function(e) {
  const currentUrl = window.location.href;
  if (pageCache.has(currentUrl)) {
    const cacheData = pageCache.get(currentUrl);
    // 渲染缓存内容、恢复状态
  }
});

补充说明

如果你一定要使用原生BF-cache,只能放弃当前的单页路由方案,让每个路由都走完整的页面跳转流程,浏览器会自动处理BF-cache的存储和恢复,但这样就不符合你当前渐进增强单页路由的需求了。


内容的提问来源于stack exchange,提问作者Hal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 15:06:05