5
votes

I am using Angular v8. I have a file called model.ts that looks like the following.

import {map} from 'rxjs/operators';

export class Person {
 constructor() { }
}

I then have a WebWorker file called test.worker.ts that looks like the following.

/// <reference lib="webworker" />
import {Person} from './bo/model';

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

When I type in ng compile I get the following ERROR.

ERROR in ./src/app/test.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/test.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
Error: node_modules/rxjs/internal/types.d.ts(45,13): error TS2339: Property 'observable' does not exist on type 'SymbolConstructor'.

    at AngularCompilerPlugin._update (/Users/jwayne/my-app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:767:31)
    at processTicksAndRejections (internal/process/task_queues.js:89:5)
    at async AngularCompilerPlugin._make (/Users/jwayne/my-app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:658:13)

If I comment out import {map} from 'rxjs/operators', then I can compile. Are there limitations on importing libraries that import other libraries?

Interestingly, if I do this import import {HttpClient} from '@angular/common/http'; then I get a different error as follows.

ERROR in ./src/app/test.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/test.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
Error: node_modules/@angular/core/core.d.ts(1470,29): error TS2304: Cannot find name 'Element'.
node_modules/@angular/core/core.d.ts(1471,29): error TS2304: Cannot find name 'Element'.
node_modules/@angular/core/core.d.ts(1538,26): error TS2304: Cannot find name 'Node'.
node_modules/@angular/core/core.d.ts(1539,29): error TS2304: Cannot find name 'Node'.
node_modules/@angular/core/core.d.ts(7082,33): error TS2304: Cannot find name 'Node'.
node_modules/@angular/core/core.d.ts(8711,81): error TS2304: Cannot find name 'HTMLElement'.
node_modules/@angular/core/core.d.ts(8822,15): error TS2304: Cannot find name 'HTMLElement'.
node_modules/@angular/core/core.d.ts(9753,62): error TS2304: Cannot find name 'Element'.
node_modules/@angular/core/core.d.ts(9755,62): error TS2304: Cannot find name 'Node'.
node_modules/@angular/core/core.d.ts(9778,59): error TS2304: Cannot find name 'Element'.
node_modules/@angular/core/core.d.ts(9820,82): error TS2304: Cannot find name 'HTMLElement'.
node_modules/@angular/core/core.d.ts(10214,83): error TS2304: Cannot find name 'HTMLElement'.
node_modules/@angular/core/core.d.ts(12863,20): error TS2304: Cannot find name 'Document'.
node_modules/@angular/core/core.d.ts(12866,13): error TS2304: Cannot find name 'HTMLElement'.
node_modules/@angular/core/core.d.ts(12874,20): error TS2304: Cannot find name 'Document'.
node_modules/@angular/core/core.d.ts(12877,13): error TS2304: Cannot find name 'Document'.
node_modules/@angular/core/core.d.ts(12885,20): error TS2304: Cannot find name 'Document'.
node_modules/@angular/core/core.d.ts(12888,13): error TS2304: Cannot find name 'Window'.

    at AngularCompilerPlugin._update (/Users/jwayne/my-app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:767:31)
    at processTicksAndRejections (internal/process/task_queues.js:89:5)
    at async AngularCompilerPlugin._make (/Users/jwayne/my-app/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:658:13)

Even more interesting, if import import {Observable, of} from 'rxjs'; then I get absolutely no errors! What's going on here?

Note that I am using ng-cli v8.0.2.

1
FWIW, a work around I have right now is to refactor all code that depends on those external libraries (Angular libraries included) into their own file. I realize that the web worker is running in its own thread so it shares no memory with the Angular application; though you may import classes, state is lost and you have to serialize them to the web worker and recreate/instantiate the objects again.Jane Wayne
I wonder if you could share your work around as a gist or something.Pirun Seng

1 Answers

2
votes

I'm not sure what the issue is with the rxjs/operators import, but I know what the issue is with the HttpClient import.

The problem is that Web Workers cannot access the DOM (https://stackoverflow.com/a/58414760/10452581). You can't use @angular/common since it accesses the DOM. I'm dealing with a similar issue (I'm trying to use pipes in my worker, which import from @angular/common). It's quite frustrating since the methods and classes of @angular/common I'm using have nothing to do with the DOM. The only potential solution I've found so far is to do what work you need to do with the libraries that manipulate the DOM outside of the worker (if possible).

TL;DR: You can't access the DOM in the web worker or even use libraries that access it, so do it outside of the worker if possible.

edit: as a better explanation, it is not just that web workers cannot access the DOM, they cannot have access to the DOM for thread safety. (https://stackoverflow.com/a/56715738/10452581) and (https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#about_thread_safety).