Jaf*_*ake 29 web-worker typescript service-worker
我应该如何构建一个包含主线程(DOM)脚本和工作程序的项目?例如:
// This file must have DOM types, but not worker types.
const worker = new Worker('worker.js');
worker.onmessage = (event) => {
// Ideally, I should be able to reference types from the worker:
const data = event.data as import('./worker').HelloMessage;
console.log(data.hello);
};
Run Code Online (Sandbox Code Playgroud)
// This file must have worker types, but not DOM types.
// The global object must be one of the worker globals (how do I pick which?)
const helloMessage = {
hello: 'world',
};
export type HelloMessage = typeof helloMessage;
postMessage(helloMessage);
Run Code Online (Sandbox Code Playgroud)
每当我过去尝试过此操作时,我都会感觉自己一直在与TypeScript对抗:
tsconfig.json
同时具有worker和DOM类型的对象。但这当然不是准确的类型。tsconfig.json
。但是项目边界使它们之间的类型引用变得困难。另外,如何在工作程序中声明全局变量?以前我曾经使用过declare var self: DedicatedWorkerGlobalScope
,但是有没有一种方法可以实际设置全局(而不只是设置self
)?
Jaf*_*ake 28
非常感谢Mattias Buelens向我指出了正确的方向。
项目结构为:
dist
src
generic-tsconfig.json
main
tsconfig.json
dedicated-worker
tsconfig.json
service-worker
tsconfig.json
src/generic-tsconfig.json
这包含每个项目通用的配置:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"moduleResolution": "node",
"rootDir": ".",
"outDir": "../dist",
"composite": true,
"declarationMap": true,
"sourceMap": true
}
}
Run Code Online (Sandbox Code Playgroud)
我故意避免调用this 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"}
]
}
Run Code Online (Sandbox Code Playgroud)
extends
-这指向我们上面的通用配置。compilerOptions.lib
-该项目使用的库。在这种情况下,使用JS和DOM。references
-由于这是主要项目(我们构建的项目),因此它必须引用所有其他子项目以确保它们也已构建。src/dedicated-worker/tsconfig.json
这是专用工作程序(您使用创建的工作程序new Worker()
)的配置。
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
Run Code Online (Sandbox Code Playgroud)
除非您从其他子项目中导入内容(例如类型),否则您无需在此处引用其他子项目。
尽管TypeScript具有不同的全局变量,但它们不会在不同的工作程序上下文之间进行区分。因此,事情变得有些混乱:
postMessage('foo');
Run Code Online (Sandbox Code Playgroud)
这是可行的,因为TypeScript的“ webworker”类型会为所有专用的工作人员全局变量创建全局变量。然而:
self.postMessage('foo');
Run Code Online (Sandbox Code Playgroud)
…这失败了,因为TypeScript给出self
了不存在的,类似于全局抽象工作程序的类型。
要解决此问题,请将其包括在您的源代码中:
declare var self: DedicatedWorkerGlobalScope;
export {};
Run Code Online (Sandbox Code Playgroud)
设置self
为正确的类型。
declare var
除非文件是模块,否则该位不起作用,并且伪导出使TypeScript将其视为模块。这意味着您要self
在模块范围中声明,该范围当前不存在。否则,你要声明它在全球,它确实存在。
src/service-worker/tsconfig.json
同上。
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
Run Code Online (Sandbox Code Playgroud)
如上所述,TypeScript的“ webworker”类型为所有专用工作程序全局变量创建全局变量。但这不是专门的工作人员,因此某些类型不正确:
postMessage('yo');
Run Code Online (Sandbox Code Playgroud)
TypeScript不会抱怨以上内容,但是它将在运行时失败,postMessage
而不是在服务工作程序全局上出现。
不幸的是,您无法采取任何措施来修复真正的全局变量,但是您仍然可以修复self
:
declare var self: ServiceWorkerGlobalScope;
export {};
Run Code Online (Sandbox Code Playgroud)
现在,您需要确保通过可以访问服务人员专用的每个全局变量self
。
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);
});
Run Code Online (Sandbox Code Playgroud)
对于其他类型的工作程序(例如工作集和共享工作程序),存在相同的问题和解决方法。
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"moduleResolution": "node",
"rootDir": ".",
"outDir": "../dist",
"composite": true,
"declarationMap": true,
"sourceMap": true
}
}
Run Code Online (Sandbox Code Playgroud)
就是这样!
归档时间: |
|
查看次数: |
2208 次 |
最近记录: |