非常感谢Mattias Buelens 为我指明了正确的方向。
Here's a working example.
项目结构为:
dist
-
src
generic-tsconfig.json
-
main
-
dedicated-worker
-
service-worker
src/generic-tsconfig.json
这包含每个项目通用的配置:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"moduleResolution": "node",
"rootDir": ".",
"outDir": "../dist",
"composite": true,
"declarationMap": true,
"sourceMap": true
}
}
我故意避免称它为tsconfig.json,因为它本身不是一个项目。根据您的需要调整上述内容。以下是重要部分:
-
outDir - 这是转换后的脚本、声明和源映射的位置。
-
rootDir - 通过将其设置为src 目录,每个子项目(main、dedicated-worker、service-worker)将作为子目录出现在outDir 中,否则它们将尝试共享相同目录并相互覆盖。
-
composite - 这是 TypeScript 保持项目之间引用所必需的。
不要在此文件中包含references。由于一些未记录的原因,它们将被忽略(这是我卡住的地方)。
src/main/tsconfig.json
这是“主线程”项目的配置,如将有权访问文档的 JavaScript。
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "dom"],
},
"references": [
{"path": "../dedicated-worker"},
{"path": "../service-worker"}
]
}
-
extends - 这指向我们上面的通用配置。
-
compilerOptions.lib - 此项目使用的库。在这种情况下,JS 和 DOM。
-
references - 由于这是主项目(我们构建的那个),它必须引用所有其他子项目以确保它们也被构建。
src/dedicated-worker/tsconfig.json
这是专用工作人员的配置(您使用 new Worker() 创建的那种)。
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
你不需要在这里引用其他子项目,除非你从中导入东西(例如类型)。
使用专用的工作器类型
TypeScript 不区分不同的工作上下文,尽管它们具有不同的全局变量。因此,事情变得有些混乱:
postMessage('foo');
这很有效,因为 TypeScript 的“webworker”类型会为所有专用的 worker 全局变量创建全局变量。然而:
self.postMessage('foo');
...这失败了,因为 TypeScript 为 self 提供了一个不存在的类型,它是一种抽象工作者全局。
要解决此问题,请将其包含在您的源代码中:
declare var self: DedicatedWorkerGlobalScope;
export {};
这会将self 设置为正确的类型。
除非文件是模块,否则declare var 位不起作用,并且虚拟导出使 TypeScript 将其视为模块。这意味着您在模块范围内声明 self,该范围目前不存在。否则,您会尝试在全局上声明它,它确实已经存在。
src/service-worker/tsconfig.json
同上。
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
使用服务工作者类型
如上所述,TypeScript 的“webworker”类型为所有专用工作全局变量创建全局变量。但这不是一个专门的worker,所以有些类型是不正确的:
postMessage('yo');
TypeScript 不会抱怨上述问题,但它会在运行时失败,因为 postMessage 不在 service worker 全局中。
不幸的是,您无法修复真正的全局,但您仍然可以修复self:
declare var self: ServiceWorkerGlobalScope;
export {};
现在您需要确保通过 self 访问每个对 Service Worker 而言特殊的全局变量。
addEventListener('fetch', (event) => {
// This is a type error, as the global addEventListener
// doesn't know anything about the 'fetch' event.
// Therefore it doesn't know about event.request.
console.log(event.request);
});
self.addEventListener('fetch', (event) => {
// This works fine.
console.log(event.request);
});
其他工作器类型也存在相同的问题和解决方法,例如工作集和共享工作器。
建筑
tsc --build src/main
就是这样!