动态 import() 在哪些场景可用
先抛开打包工具不谈,平台层面的规则如下:
| 场景 | 运行时支持动态 import() |
|---|---|
| Service worker(background) | 否,规范不允许 |
| 扩展页面(popup、options、新标签页、side panel) | 是 |
| Offscreen 文档 | 是 |
| Content scripts | 是,但需要多一步处理 |
import()。worker 顶部的静态 import 语句是没问题的(Extension.js 会把它们打进 bundle),但你没法把某个 chunk 的加载推迟到事件触发时再做。
模式 1:按界面拆分,而不是按 chunk 拆分
service worker 应该负责调度,而不是亲自做计算。让它的静态 import 只包含粘合代码(路由消息、注册监听器),并把所有重活搬到能用按需加载的地方:- 跟 UI 紧密相关的工作放到真正需要它的页面里。一个用来格式化代码的 popup,应该在 popup 里 import 格式化器,而不是在 worker 里。
- 只有 background 才会做的重型工作(解析、编码、推理)放到 offscreen 文档里,按需创建、用完即关。worker 保持成一个轻量的消息路由器。
background.ts
import() 那个重型库,开销就摊到了每个文档的生命周期里一次,而不是每次 worker 唤醒都来一次。
模式 2:在扩展页面里按需 import
在任何扩展页面里,普通的动态 import 都能用,打包工具会自动把 chunk 拆出来:popup.ts
模式 3:在 content scripts 里按需 import
Content scripts 是在页面里执行的,所以它们按需加载的 chunk 必须能被那个页面 fetch 到。两步走:- 通过
web_accessible_resources暴露这些 chunk 的路径。 - 用
chrome.runtime.getURL来 import,让 URL 解析到你的扩展 origin:
content.ts
哪些东西干脆不要放进 worker
- 任何跟 DOM 相关的(
DOMParser、canvas、音频):worker 根本没有 DOM,请用 offscreen 文档。 - 几兆大的 wasm:在 offscreen 文档或者一个额外页面里实例化,并把结果缓存到
chrome.storage,这样重启的代价就很低。 - 一次性工具(导入、迁移、导出):放到
pages/下的一个独立页面里,免得它出现在每条启动路径上。

