How to use SharedWorker in Angular?

Viewed 1294

I already have Workers in my Angular app. But I'm trying to create a Shared Worker, and it fails, saying "Failed to fetch a worker script." in the console.

const worker = new SharedWorker('../../../workers/my.shared.worker', { name: 'mySharedWorker', type: 'module' });

If I replace SharedWorker with Worker - it works perfectly.

Of course, I made everything as needed. Created an additional .tsconfig file:

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

And added webWorkerTsConfig to angular.json config:

projects.myProject.architect.build.options.webWorkerTsConfig: "tsconfig.worker.json"

I found this article by Nikita Barsukov but it works only if your Worker is stored as a single file in the assets folder. But my SharedWorker contains dozen of .ts files, that should be bundled just like an ordinary Worker.

1 Answers

Seems Angular-CLI now (as for v10.0.7) supports Workers only. But not SharedWorkers.

Angular-CLI uses worker-plugin under the hood. And actually, it can load SharedWorkers, but it should be enabled in WebpackConfig.

So there are two options.

  1. Use @angular-builders/custom-webpack and add sharedWorker parameter to WorkerPlugin in custom webpack config. But I was unable to make it work.

  2. Use custom-webpack loader (this options works for me):

import workerUrl from 'worker-plugin/loader?name=mySharedWorker!../../../workers/my.shared.worker.ts';
// ....
const worker = new SharedWorker(workerUrl, { name: 'mySharedWorker', type: 'module' });

Where name=mySharedWorker is the name of future bundle file. If you omit it, it will use something like 0.worker.js, but it can cause a collision with ordinary Worker bundling because it'll use the same name. So always specify the name of your bundle in loader params.

Related