不使用Webpack时如何让转译后的TypeScript代码在Worker中运行?
根本原因
Worker的运行上下文和主页面完全隔离,你主页面加载的SystemJS、CommonJS运行时在Worker里默认不存在:
- 转ESNext模块时,默认Worker以普通脚本模式加载,不支持
import语法,所以报语法错误 - 转CommonJS时,Worker里没有全局
exports、require变量,所以报引用错误 - 转System/AMD格式时,Worker里没有对应的
System/define全局变量,自然也报错
你之前的简单Worker能正常运行,是因为代码里没有导入导出语句,转译后没有模块相关的依赖逻辑,所以不会触发报错。
解决方案(无Webpack,纯底层配置)
方案1:用原生ES模块模式(推荐,零额外依赖)
现在主流浏览器都支持ES Module类型的Worker,只需修改两处配置即可:
- 修改Worker子目录的
tsconfig.json:
{ "extends": "../generic-tsconfig.json", "compilerOptions": { "strict": true, "target": "ES6", "module": "ESNext", // 输出ES模块格式 "moduleResolution": "NodeNext", // 匹配ES模块的路径解析规则 "outDir": "../../dist", "lib": [ "ES6", "WebWorker" ], }, "include": [ "../worker/*", "../shared/*" ] }
- 调用Worker时增加模块类型声明:
let worker = new Worker("../worker/simulator.js", { type: "module" });
注意:TS代码中导入其他模块时,需要明确写
.js后缀(比如import { Foo } from '../shared/foo.js'),符合ES模块的导入规范。
方案2:兼容旧浏览器,复用SystemJS格式
如果需要兼容不支持ES模块Worker的旧浏览器,可以把Worker代码转成System格式,在Worker内先加载SystemJS运行时再执行业务代码:
- 把tsconfig的
module字段改成System - 新增一个Worker启动脚本
worker-bootstrap.js,放在静态资源目录下:
// 先加载SystemJS运行时(提前把SystemJS的UMD文件存到本地静态资源目录) self.importScripts('/static/system.js'); // 加载转译后的System格式Worker业务代码 System.import('/worker/simulator.js');
- 调用Worker时加载这个启动脚本即可:
let worker = new Worker("../worker/worker-bootstrap.js");
内容的提问来源于stack exchange,提问作者Fuhrmanator
相关产品推荐
相关产品推荐

