WebBundle 目前无法用于离线分发大型 Web 应用,因其仍处实验阶段:Chrome 仅支持通过 file:// 或拖入方式加载本地 .wbn 文件,需启用 flag,且不支持 Service Worker 拦截、动态 import()、跨 origin 解析等关键能力。

WebBundle 目前无法用于离线分发大型 Web 应用——它仍处于实验阶段,Chrome 仅支持加载本地 .wbn 文件(需启用 flag),且不支持 Service Worker 拦截后注入、动态 import() 加载、或跨 origin 资源解析。所谓“完整分发”在当前实现中并不存在。
Chrome 中加载本地 WebBundle 的实际限制
Chrome 117+ 支持通过 response = await fetch(new Request('app.wbn')) 加载本地 bundle,但前提是:
-
app.wbn必须由开发者手动拖入浏览器窗口(或通过file://协议打开),不能通过fetch()从页面脚本发起跨 origin 请求 - 必须启用
--enable-features=WebBundles启动参数,且禁用site-per-process - bundle 内所有资源的 URL 必须与声明的
source_map完全匹配;哪怕路径末尾多一个/,Response.url就会变成about:blank,导致 CSS/JS 无法正确解析上下文 - 不支持
importScripts()或Worker构造函数加载 bundle 内脚本
Service Worker 无法拦截并返回 WebBundle 响应
你不能在 fetch 事件中 return new Response(bundleResponse.body, { headers: bundleResponse.headers }) 来“模拟”资源返回——因为:
-
Response.body是ReadableStream,而 WebBundle 解析器只接受完整ArrayBuffer或Blob输入 - Chrome 的
WebBundleParserAPI(new WebBundleParser())是内部接口,未暴露给页面脚本 - 即使你用
await response.arrayBuffer()读取完 bundle,也无法在 SW 中调用解析逻辑;目前唯一可用的解析入口是fetch('app.wbn')自身,且它不接受Response实例作为输入
替代方案:用传统方式达成类似效果
如果目标是离线部署大型应用(如 Electron 替代、内网交付、PWA 离线包),更可行的路径是:
- 用
zip打包全部静态资源 + 一个轻量index.html,解压后用file://打开(注意:现代 Chrome 默认禁用file://下的fetch,需加--allow-file-access-from-files) - 用
Electron或Tauri封装,通过main.js注入protocol.handle('app', ...)提供虚拟 HTTP 服务 - 构建时生成完整
manifest.json+precacheManifest,配合workbox-webpack-plugin预缓存所有 chunk 和 asset,再用npx serve -s build启动本地 server —— 这才是当前最稳定、可调试、可更新的离线方案
WebBundle 的设计初衷是解决 HTTP/3 的服务器推送和跨站子资源复用,不是替代打包工具或离线分发机制。现在强行用它做离线包,等于拿锤子拧螺丝——不是不行,是每颗螺丝都要先打磨锤头。

















