离线环境下动态导入按需加载的关键是service worker预缓存构建后的chunk文件,并拦截import()请求返回缓存资源;路径须为字面量,不可动态拼接,且需在sw中显式缓存带hash的产物路径(如/auth.e8f2a12d.js),配合cachefirst策略与try/catch兜底。

离线环境下实现动态导入的按需加载,关键不在于“重新下载”,而在于让浏览器提前把核心模块缓存进 Service Worker 控制的 Cache Storage,并在运行时通过 import() 正常触发、由 SW 拦截并返回已缓存资源。动态导入本身不感知缓存,但它的网络请求可被 Service Worker 拦截复用。
确保模块路径可被 Service Worker 缓存识别
动态导入的路径必须是确定的、可预知的字符串(不能是拼接的非常量表达式),否则构建工具无法静态分析生成 chunk,Service Worker 也无法预先声明缓存规则。
- ✅ 推荐写法:使用字面量路径,如
import('./features/chart.js')或import('./core/auth.js') - ❌ 避免写法:
import(`./features/${type}.js`)(路径动态拼接)、import(modulePath)(变量路径)——这类写法在离线时会因 SW 无对应缓存键而失败 - 构建工具(Vite/Webpack)会自动为合法的
import()生成独立 chunk 文件(如chart.abc123.js),这些文件名带 hash,需在 SW 缓存清单中包含
在 Service Worker 中预缓存核心模块 chunk
使用 workbox-precaching 或手动 caches.open().add(),把构建后生成的核心功能模块(如登录、设置、基础 UI 组件)纳入 precache 列表。注意:不是缓存源码路径(./core/auth.js),而是缓存构建产物路径(如 /assets/auth.e8f2a12d.js)。
- Vite 项目可配合
vite-plugin-pwa,在pwa.manifest或self.__WB_MANIFEST中自动注入动态 import 生成的 chunk - Webpack 用户需确认
optimization.splitChunks已启用,并在 SW 中显式添加import('./core/xxx.js')对应的输出文件 - 缓存策略建议用
CacheFirst:优先读缓存,离线时直接命中;在线时仅在缓存未命中或失效时回源
运行时调用 import() 并处理离线异常
即使模块已缓存,import() 仍可能因网络判断逻辑或 SW 未就绪而抛错。需主动兜底:
- 用
try/catch包裹await import(),捕获NetworkError或TypeError: Failed to fetch - 若失败,可尝试从
caches.match()手动读取模块脚本并eval()(不推荐)或更安全地——提前在安装阶段将模块内容存为文本,运行时new Function()构造模块(需自行处理导出模拟) - 更实用的做法:对真正核心的功能(如登录、离线表单提交),不依赖动态导入,而是用
importScripts()在 SW 安装时预加载并暴露全局函数,主页面直接调用
验证与调试要点
离线按需加载是否生效,不能只看控制台有没有报错,要检查三处:
- 浏览器 Application → Cache Storage:确认目标 chunk 文件(如
auth.xxx.js)已存在于 precache 缓存中 - Network 面板 → 离线模式下点击触发按钮,查看该 JS 请求的状态码是否为
from cache或200 (from ServiceWorker) - Service Worker 的
fetch事件监听中加日志,确认是否成功event.respondWith(caches.match(...))
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











