Настройка веб-работника в Angular 7.0.1

Я пытаюсь выполнить настройку веб-работника в моем существующем проекте Angular 7.0.1 (проект среднего масштаба). Я сделал настройку после перехода по следующим ссылкам:

Вот мои изменения в каждом файле:

. /src/main.ts

import 'zone.js';
import { enableProdMode } from '@angular/core';
import { bootstrapWorkerUi } from '@angular/platform-webworker';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

console.log("main.ts file loaded!");
bootstrapWorkerUi('webworker.js');

. /src/workerLoader.ts

import 'polyfills.ts';
import '@angular/core';
import '@angular/common';

console.log("workerLoader.ts file loaded!");

import { platformWorkerAppDynamic } from '@angular/platform-webworker-dynamic';
import { AppModule } from './app/app.module';

platformWorkerAppDynamic().bootstrapModule(AppModule);

. /angular.json

"projects": {
  "[project name]": {
    "architect": {
      "build": {
        "builder": "@angular-builders/custom-webpack:browser",
        "options": {
          "customWebpackConfig": {
            "path": "./extra-webpack.config.js"
          }
          ...
          ...
        }
      }
    }
  }
}

. /extra-webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    "entry": {
        "webworker": [
            "./src/workerLoader.ts"
        ]
    },
    "plugins": [
        new HtmlWebpackPlugin({
            "excludeChunks": [
                "webworker"
            ],
        })
    ],
    "output": {
        "globalObject": 'this'
    }
}

. /tsconfig.json

{
    ...
    ...
    "angularCompilerOptions": {
        "entryModule": "./app/app.module#AppModule"
    }
}

Вот демо. Вы можете проверить мои исследовательские заметки.

Возможно, я иду в совершенно неверном направлении, потому что мне просто нужно включить и запустить библиотеку Angular Service Worker в проекте Angular (что должно быть очень просто).

Мое основное намерение попытаться включить веб-работника - позволить веб-приложению работать в многопоточном режиме, чтобы анимации, флажки, настраиваемые выпадающие и прокручиваемые эффекты на экране работали плавно.

Ответ 1

Вы можете следить за этой статьей еще с 2016 года, которая по-прежнему применима в настоящее время. В общем, вам следует сделать следующее:

Допустим, у нас есть сервисный брокерский завод:

import {Component} from '@angular/core';
const FACTORIAL_CHANNEL = "FACTORIAL";
import {NgModule} from '@angular/core';
import {WorkerAppModule} from '@angular/platform-webworker';
import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic';
import {ServiceMessageBrokerFactory, PRIMITIVE} from '@angular/platform-webworker';

@Component({
  selector: 'app',
  template:'<div>Web worker loaded</div>'
})
class Worker {
  time: string;
  constructor(private _serviceBrokerFactory: ServiceMessageBrokerFactory){
    var broker = _serviceBrokerFactory.createMessageBroker(FACTORIAL_CHANNEL, false);
    broker.registerMethod("factorial", [PRIMITIVE], this.calculate, PRIMITIVE);
  }

  private calculate(val: string) {
    if(val) {
      let result = factorial(parseInt(val));
      return Promise.resolve(result);
    }
    return Promise.resolve('');
  }
}

@NgModule({imports: [WorkerAppModule], bootstrap: [Worker], declarations: [Worker]})
class WorkerModule {
}

platformWorkerAppDynamic().bootstrapModule(WorkerModule);

function factorial(num) {
  if (num === 0) {
    return 1;
  }
  else {
    return (num * factorial(num - 1));
  }
}

Здесь всякий раз, когда мы получаем сообщение по правильному каналу, будет вызываться метод вычисления, в этом и заключается важность фабрики сервисных брокеров.


Затем мы создаем файл loader.ts для загрузки созданного нами компонента:

declare var System: any;
importScripts(
  "node_modules/systemjs/dist/system.js",
  "node_modules/zone.js/dist/zone.min.js",
  "node_modules/reflect-metadata/Reflect.js",
  "config.js");
System.import("./web-worker-app.js");

Затем создайте точку входа для веб-работника:

import {PlatformRef} from '@angular/core';
import {UiArguments, FnArg, PRIMITIVE, ClientMessageBrokerFactory} from '@angular/platform-webworker';
import {bootstrapWorkerUi} from "@angular/platform-webworker";

const FACTORIAL_CHANNEL = "FACTORIAL";

bootstrapWorkerUi("factorial/loader.js")
  .then((ref: any) => {
    let brokerFactory: ClientMessageBrokerFactory = ref.injector.get(ClientMessageBrokerFactory);
    var broker = brokerFactory.createMessageBroker(FACTORIAL_CHANNEL, false);

    document.getElementById("calculate_factorial").addEventListener("click", (e) => {
      var val = (document.getElementById("factorial")).value;
      var args = new UiArguments("factorial");
      args.method = "factorial";
      var fnArg = new FnArg(val, PRIMITIVE);
      fnArg.value = val;
      fnArg.type = PRIMITIVE;
      args.args = [fnArg];
      broker.runOnService(args, PRIMITIVE)
        .then((res: string) => {
          document.getElementById("result").innerHTML = '${res}';
        });
    });
});

main.ts здесь служит main.ts загрузки веб-работника и каналом связи между хост-приложением и веб-работником.


Это простой фрагмент, который поможет вам поработать с веб-работниками, более подробную информацию можно найти в статье, которую я опубликовал.