使用workers构建TypeScript项目

使用workers构建TypeScript项目,typescript,service-worker,web-worker,Typescript,Service Worker,Web Worker,我应该如何构造一个包含主线程(DOM)脚本和工作线程的项目?例如: 梅因酒店 工人技术 过去每当我尝试这一点时,我都会觉得我一直在通过以下两种方式与TypeScript进行斗争: 使用一个同时具有worker和DOM类型的tsconfig.json。但这当然不是准确的类型 使用多个tsconfig.json。但是,项目边界使得它们之间很难引用类型 此外,如何在worker中声明全局值?以前我使用了declare var self:DedicatedWorkerGlobalScope,但是有没

我应该如何构造一个包含主线程(DOM)脚本和工作线程的项目?例如:

梅因酒店 工人技术 过去每当我尝试这一点时,我都会觉得我一直在通过以下两种方式与TypeScript进行斗争:

  • 使用一个同时具有worker和DOM类型的
    tsconfig.json
    。但这当然不是准确的类型
  • 使用多个
    tsconfig.json
    。但是,项目边界使得它们之间很难引用类型
此外,如何在worker中声明全局值?以前我使用了
declare var self:DedicatedWorkerGlobalScope
,但是有没有一种方法可以实际设置全局(而不仅仅是设置
self
)?

非常感谢为我指明正确方向的人

项目结构为:

  • dist
  • src
    • generic tsconfig.json
    • main
      • (打字脚本文件)
      • tsconfig.json
    • 专职工人
      • (打字脚本文件)
      • tsconfig.json
    • 服务人员
      • (打字脚本文件)
      • tsconfig.json
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
    专用工作者
    服务工作者
    )将在
    outDir
    中显示为子目录,否则它们将尝试共享同一目录并相互覆盖
  • composite
    -这是TypeScript在项目之间保留引用所必需的
不要在此文件中包含
引用
。由于一些未记录的原因,它们将被忽略(这就是我被卡住的地方)

src/main/tsconfig.json
这是“主线程”项目的配置,如中所示,JavaScript将访问文档

{
  "extends": "../generic-tsconfig.json",
  "compilerOptions": {
    "lib": ["esnext", "dom"],
  },
  "references": [
    {"path": "../dedicated-worker"},
    {"path": "../service-worker"}
  ]
}
  • 扩展
    -这指向上面的通用配置
  • 编译器选项.lib
    -此项目使用的lib。在本例中,JS和DOM
  • 引用
    -由于这是主项目(我们构建的项目),它必须引用所有其他子项目,以确保它们也被构建
src/dedicated worker/tsconfig.json
这是专用工作程序的配置(使用
new worker()
创建的类型)

除非从其他子项目(例如类型)导入内容,否则不需要在此处引用其他子项目

使用专用工作类型 TypeScript不区分不同的工作上下文,尽管它们具有不同的全局变量。因此,事情变得有点混乱:

postMessage('foo');
这是可行的,因为TypeScript的“webworker”类型为所有专用的工作全局创建全局。然而:

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”类型为所有专用工作全局创建全局。但这不是一个专门的工作者,因此某些类型是不正确的:

postMessage('yo');
TypeScript不会抱怨上述问题,但它会在运行时失败,因为
postMessage
不在服务工作者全局上

不幸的是,您无法修复真正的全局设置,但您仍然可以修复
self

declare var self: ServiceWorkerGlobalScope;
export {};
现在,您需要确保通过
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);
});
对于其他工作人员类型(如工作集和共享工作人员),也存在相同的问题和解决方法

建筑
tsc——构建src/main

就这样

感谢您的详细解释,@JaffaTheCake!将此设置为书签。很好的答案+1。仅供参考,我已经为TS和Web Worker创建了一个最小设置示例,这里是我的解决方案:我使用cast to IdeficatedWorkerGlobalScope帮助TS自己获取类型。我希望它会有用。@GibboK您链接的项目并不能解决worker和dom类型之间的冲突问题,因为它完全忽略了dom类型,我认为您的示例可能太小,在实际情况中没有帮助。
postMessage('yo');
declare var self: ServiceWorkerGlobalScope;
export {};
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);
});