简体   繁体   English

在 Angular 上注册自己的 Service Worker 和它自己的 worker

[英]Register own Service Worker on Angular alongside its own worker

I have an web application that needs to work offline.我有一个需要脱机工作的 Web 应用程序。 I want to create my service worker to handle the API caching/sync logic, and let the angular's service worker cache the application assets.我想创建我的 service worker 来处理 API 缓存/同步逻辑,并让 angular 的 service worker 缓存应用程序资产。

I got the Angular worker to register and work perfectly.我让 Angular 工人注册并完美地工作。 But I could not get to register my worker.但是我无法注册我的工人。

I tried three methods:我尝试了三种方法:

//1. Does not seem to do anything. No worker built, no worker starter.
ServiceWorkerModule.register('./offline.worker', {enabled: environment.production});

//2. The worker does not get built, registering fails since the script does not exist.
navigator.serviceWorker.register('./offline.worker');

//3. The worker gets built, it even gets started, but is not registered as ServiceWorker.
new Worker('./offline.worker', {type: 'module'});

So, option 1 works fine using the docs on the angular service worker when we point to the ngsw js file.因此,当我们指向 ngsw js 文件时,选项 1 可以很好地使用 angular service worker 上的文档。 Maybe it is simply not made to work for our workers?也许它根本不是为我们的工人工作的?

Option 2 is the documented/standard way to register service workers, maybe I should simply get my worker to be built?选项 2 是注册服务人员的记录/标准方式,也许我应该简单地构建我的工作人员? I do not know where to start to do that... The complete error I get is我不知道从哪里开始……我得到的完整错误是

Uncaught (in promise) TypeError: Failed to register a ServiceWorker for scope (' http://localhost:8080/ ') with script (' http://localhost:8080/offline.worker '): A bad HTTP response code (404) was received when fetching the script. Uncaught (in promise) TypeError: Failed to register a ServiceWorker for scope (' http://localhost:8080/ ') with script (' http://localhost:8080/offline.worker '): A bad HTTP response code ( 404) 在获取脚本时收到。

Option 3 gets everything done as I would have expected.选项 3 按我的预期完成了所有工作。 My worker is compiled the ./offline.worker is even changed to the bundle created!我的工作人员已编译./offline.worker甚至更改为创建的包! That's really how I would have expected to get things going.这真的是我期望事情进展的方式。 Unfortunately the worker created like so is only a web worker, not a ServiceWorker.不幸的是,像这样创建的 worker 只是一个 web worker,而不是 ServiceWorker。 This means it does not get to handle FetchEvents...这意味着它无法处理 FetchEvents...

For sake of completeness, here is my tsconfig.worker.json为了完整起见,这是我的 tsconfig.worker.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/worker",
    "lib": [
      "es2018",
      "webworker"
    ],
    "types": []
  },
  "include": [
    "src/**/*.worker.ts"
  ],
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}

And the commands used to launch angular in production mode since service workers do not worker in develop:以及用于在生产模式下启动 angular 的命令,因为 Service Worker 不在开发中工作:

ng build --prod
http-server dist/app

We've added custom logic along-side the Angular Service Worker by using a simple intermediary script to load both the generated ngsw script and our own custom script.我们通过使用一个简单的中间脚本加载生成的 ngsw 脚本和我们自己的自定义脚本,在 Angular Service Worker 旁边添加了自定义逻辑。 This plays well with the Angular build process.这与 Angular 构建过程配合得很好。

app.module.ts app.module.ts

@NgModule({
  //...
  imports: [
    ServiceWorkerModule.register('sw-master.js', {
      enabled: environment.production
    }),
    //...
  ],
  //...
});

angular.json angular.json

...
"assets": [
  ...
  "src/manifest.json",
  "src/sw-custom.js",
  "src/sw-master.js"
],...

sw-master.js sw-master.js

importScripts('./ngsw-worker.js'); // generated by Angular build process
importScripts('./sw-custom.js');

sw-custom.js sw-custom.js

Just an example... we were making it so users could click on push notifications and be directed to a particular app view.只是一个例子......我们正在制作它,以便用户可以点击推送通知并被定向到特定的应用程序视图。

(function () {
  'use strict';
  self.addEventListener('notificationclick', (event) => {
    event.notification.close();
    if (clients.openWindow && event.notification.data.url) {
      event.waitUntil(clients.openWindow(event.notification.data.url));
    }
  });
}());

Only one service worker per scope is allowed to be registered , so you can not register more than one service worker.每个范围只允许注册一个 Service Worker ,因此您不能注册多个 Service Worker。

You can handle both API caching/sync and application assets caching in a single service worker file.您可以在单个 Service Worker 文件中处理 API 缓存/同步和应用程序资产缓存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM