应判断event.request.destination === 'document',因浏览器对文档请求有特殊渲染要求,仅对此类请求启用HTML缓存fallback,其他类型需按资源分流处理。

怎么判断一个请求该走 HTML 路由兜底
SPA 离线时点链接跳转空白,根本原因不是缓存没生效,而是 fetch 事件里压根没识别出这是个 HTML 导航请求。浏览器对 destination === 'document' 的请求有特殊处理逻辑:它必须返回一个可渲染的 HTML 响应,否则直接白屏。
常见错误是把所有请求都丢给 caches.match(event.request),结果匹配到带 cookie 的 POST 请求或带 token 的 API 请求,导致登录态异常或表单静默失败。
- 只对
event.request.destination === 'document'的请求启用 HTML fallback - 其他类型(
'script'、'style'、'image'、'font')按资源类型分流处理 - 用
new URL(event.request.url)解析路径后,再结合destination判断,比单纯看pathname更可靠
为什么 /about 离线打不开,但 / 能打开
因为 cache.addAll(['/', '/app.js']) 只缓存了根路径的 HTML 文件,而浏览器访问 /about 时发出的是一个新请求,其 URL 是完整字符串 https://example.com/about —— 缓存中没有这个 key,caches.match() 必然返回 undefined。
SPA 的路由是前端控制的,/about 这个路径在服务端并不存在,所以不能指望缓存“所有可能的路由”。正确做法是统一 fallback 到已缓存的 /index.html 或 /。
- install 阶段必须显式缓存
'/'(即index.html),且路径必须是绝对路径 - fetch 阶段对
destination === 'document'的请求,固定caches.match('/')或caches.match('/index.html'),不依赖请求 URL 匹配 - 不要缓存带查询参数的 HTML 请求,如
/post?id=123,这类无法预加载,也不该进 Cache API
如何让 SW 正确处理 history 模式下的跳转
Vue Router、React Router 的 history 模式下,所有路由都指向同一份 index.html,但 SW 不会自动理解这个语义。它只认 URL 字符串,不认前端路由规则。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
如果你只缓存了 '/',却在 fetch 中写 caches.match(event.request),那 /user/profile 就永远查不到缓存 —— 因为缓存里根本没有这个 key。
- 缓存阶段:只缓存
'/'和它直接依赖的资源('/app.js'、'/main.css'等) - 拦截阶段:对
destination === 'document'的请求,一律caches.match('/'),然后return response - 避免在 install 阶段缓存动态路径(如
'/about'、'/contact'),它们不是真实存在的文件,缓存无效
SW 路由匹配容易被忽略的兼容性细节
destination 属性在部分旧版浏览器(如 Safari 15.4 之前)不支持,直接读取会 undefined;另外,某些构建工具生成的 sw.js 如果没放在根目录,或注册时没设 scope: '/',也会导致拦截范围失效。
更隐蔽的问题是:如果页面首次加载时 SW 还没激活,用户点击链接触发的导航请求不会被拦截 —— 直到下一次刷新或跳转才生效。这就是为什么有些用户反馈“第一次离线不行,第二次就好了”。
- 做兼容判断:
if (event.request.destination === 'document' || !event.request.destination),后者覆盖旧浏览器 - 注册时必须指定
scope: '/',确保能拦截全站请求 - 激活阶段调用
self.clients.claim(),让新 SW 立即接管已有页面,避免首屏漏拦截
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










