【问题标题】:Angular: Using TypeScript for Service Worker (ServiceWorkerModule)Angular:为 Service Worker 使用 TypeScript (ServiceWorkerModule)
【发布时间】:2019-12-05 21:51:46
【问题描述】:

是否可以使用@angular/service-worker 注册一个用 TypeScript 编写的 ServiceWorker?

当前在 app.module.ts 中注册服务工作者如下所示:

ServiceWorkerModule.register('ngsw-worker.js', {
  enabled: environment.production
})

是否可以注册ngsw-worker.ts?

至少对于 Angular 中的网络工作者来说这是可能的:

const worker = new Worker('../my-worker.worker', {
      type: 'module'
    });

my-worker.worker.ts

/// <reference lib="webworker" />

import {someMethod} from './some-method';

addEventListener('message', ({ data }) => {
  const response = `worker response to ${data}`;
  postMessage(response);
  someMethod();
});

感谢任何帮助 - 谢谢

【问题讨论】:

  • 浏览器不知道 TypeScript。 TypeScript 被编译为 JavaScript,这就是浏览器下载和执行的内容:JavaScript 代码,而不是 TypeScript 代码。
  • 是的,但是 Angular 在内部使用 webpack 将这些 TS 文件编译为 JS。为什么不支持服务工作者,因为他们已经支持网络工作者?
  • AFAIR,此代码用于注册 Angular 服务工作者,由 Angular 编写和提供。为什么要重写?
  • 我想在 SW 和主线程上使用方法(TS 文件)。我目前的方法是将它们捆绑在一个单独的构建步骤中,并通过importScripts('sw-bundle.js') 导入它们。我的问题是是否有更好的方法来做到这一点,例如使用 Angular 编译器。它适用于网络工作者(使用上面的代码),我也希望对 SW 使用类似的东西。
  • 但你是对的,看起来 ServiceWorkerContainer.register 只是从 Angular 模块调用

标签: angular typescript service-worker angular-service-worker


【解决方案1】:

作为 Angular/TypeScript/Javascript 的初学者,我已经尝试了几天。 我的意图是使用 TypeScript 作为我的主要语言来使用它作为 es5 转译器,所以我不必担心:

  • 语言版本控制(es5、es2015、...)
  • 捆绑
  • 掉毛
  • 等

我认为我有一个不错但奇怪的解决方案,它使用工作插件,从 Angular8 开始可用。

例子:

workers/service-worker.worker.ts

// Import angular serviceworker
importScripts("ngsw-worker.js");

// custom code
addEventListener("message", (data) => {
    console.log(data);
});

workers/service-worker-config.ts

import { environment } from "../../environments/environment";

export let generatedServiceWorkerUrl: string = null;
(function generateUrl(): void {
    // Override the real Worker with a stub
    // to return the filename, which will be generated/replaced by the worker-plugin.
    // @ts-ignore
    Worker = class WorkerStub {
        constructor(public stringUrl: string, public options?: WorkerOptions) {}
    };

    const worker = new Worker("./service-worker.worker", { type: "module" }) as any;
    generatedServiceWorkerUrl = worker.stringUrl;
})();

export const serviceWorkerConfig = {
    enabled: environment.production,
    serviceWorkerUrl: generatedServiceWorkerUrl
};

app.module.ts

import { serviceWorkerConfig  } from "./workers/service-worker-config";

@NgModule({
    declarations: [AppComponent],
    entryComponents: [],
    imports: [
        [...],
        ServiceWorkerModule.register(serviceWorkerConfig.serviceWorkerUrl, { enabled: serviceWorkerConfig.enabled })
    ],
    providers: [...],
    bootstrap: [AppComponent]
})
export class AppModule {}

【讨论】:

  • 这很好用!它允许自定义代码 和 它允许通过 ng serve 测试您的服务工作 Angular 10 的更新,在生产中,generateUrl 函数将被删除(显然是因为它没有被直接引用) .直接调用就解决了,比如让generateUrl返回URL,然后用serviceWorkerUrl: generatedUrl()保存到配置中。
  • @kdubb 您能否编辑答案,以便我们为 Angular 的未来版本提供兼容的代码
  • @Kelon 我无法让您的解决方案发挥作用。我有以下Error: The AngularCompilerPlugin was not found. The @ngtools/webpack loader requires the plugin.
  • 我不确定这最终应该如何工作。服务工作者已注册并尝试启动,但最终出现无法安装工作者的启动错误。它试图在http://localhost:4200/service-worker.worker 找到工作人员,构建过程没有生成/替换该 URL。
  • url 由 Angular 构建过程生成,它尝试创建所有生成的“新 Worker”调用。这就是我们将使用 WorkerStub 覆盖这个真正的浏览器已知类并用真正的 service-worker 的导入填充它的原因。 Angular 使用散列版本号构建它,例如 '0.777f70d1e77a7777d346.worker.js'
【解决方案2】:

当然可以在打字稿中重写 js 中的任何内容。但是要在浏览器中运行它,你必须将它编译成 JavaScript。因为,浏览器目前还不能解释/理解打字稿。

为此,您可以使用 typescript 命令:tsc。

在您的 package.json 中,创建如下脚本命令:-

"scripts": {
    "compile-to-ts": "tsc my-service-worker.ts"
}

现在运行上面的命令:-

npm run compile-to-ts

它将您的打字稿文件编译成javascript并将生成的文件放在基于tsconfig文件的目录中。

更新:您还可以使用来自 here 的服务工作者的类型定义。您可以利用它来提高 Service Worker 打字稿代码中的类型安全性,并避免任何与打字稿相关的错误(如果有的话)。

【讨论】:

  • 很公平,但如果我的my-service-worker.ts 正在从其他 ts 文件(如上面的 someMEthod)导入内容,则需要 webpack 或 rollup 之类的捆绑程序。这是我想避免让 Angular 编译器处理此问题的步骤
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 2019-02-09
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
  • 2018-10-06
相关资源
最近更新 更多