Angular CLI使用Web Workers生成应用程序

时间:2017-04-07 10:39:52

标签: angular web-worker

阅读Angular文档,您可以找到几个references to bootstrap your whole Angular app inside a Web Worker,因此您的UI不会被大量的JS使用阻止。

然而,目前还没有关于如何做到这一点的官方信息,以及Angular Doc中的唯一信息。这是一个实验性功能。

如何使用此方法来利用Angular中的Web工作者?

2 个答案:

答案 0 :(得分:70)

对于Angular 7,请参阅下面的答案。

我花了很多时间来弄明白该怎么做,所以我希望this can help someone

的前提条件

我假设你有一个使用Angular CLI 1.0或更高版本生成的Angular项目(版本2或4)。

使用CLI生成项目并不是必须遵循此步骤,但我将提供与webpack文件相关的说明,它们基于CLI webpack配置。

的步骤

1。解压缩webpack文件

从Angular CLI v1.0开始,就有“弹出”功能,它允许你提取webpack配置文件并按照你的意愿操作它。

  • 运行ng eject以便Angular CLI生成 webpack.config.js 文件。

  • 运行npm install以满足CLI生成的新依赖关系

2。安装webworker引导程序依赖项

运行npm install --save @angular/platform-webworker @angular/platform-webworker-dynamic

3。 UI线程引导程序的更改

3.1 app.module.ts中的更改

BrowserModule替换为app.module.ts文件中的WorkerAppModule。您还需要更新import语句才能使用@angular/platform-webworker库。



//src/app/app.module.ts

import { WorkerAppModule } from '@angular/platform-webworker';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
//...other imports...

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    WorkerAppModule,
    //...other modules...
  ],
  providers: [/*...providers...*/],
  bootstrap: [AppComponent]
})
export class AppModule { }




3.2 src / main.ts中的更改

将引导程序替换为:bootstrapWorkerUI(同时更新导入)。

您需要传递一个URL,其中包含定义Web worker的文件。使用名为webworker.bundle.js的文件,不用担心,我们很快就会创建此文件。



//main.ts

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();
}

bootstrapWorkerUi('webworker.bundle.js');




3.3创建workerLoader.ts文件

  • 创建新文件src / workerLoader.ts
  • 由于您的Web Worker将是包含所有必需内容的单个文件,因此您需要包含polyfills.ts@angular/core@angular/common个包。在接下来的步骤中,您将更新Webpack以便转换并构建包含结果的包。
  • 导入platformWorkerAppDynamic
  • 导入AppModule(从 main.ts 中删除导入)并使用此platformWorkerAppDynamic平台进行引导。



// workerLoader.ts

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);




4。更新webpack以构建您的webworker

webpack自动生成的配置文件很长,但您只需要将注意力集中在以下方面:

  • webworker文件添加workerLoader.ts 入口点。如果查看输出,您会看到它将bundle.js前缀附加到所有块。这就是为什么在引导步骤中我们使用了webworker.bundle.js

  • 转到 HtmlWebpackPlugin 并排除webworker入口点,因此生成的Web Worker文件不会包含在index.html文件中。

  • 转到 CommonChunksPlugin ,对于inline公共块,请明确设置条目块以防止包含webworker

  • 转到 AotPlugin 并明确设置entryModule



// webpack.config.js

//...some stuff...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CommonsChunkPlugin } = require('webpack').optimize;
const { AotPlugin } = require('@ngtools/webpack');
//...some stuff...

module.exports = {
  //...some stuff...
  "entry": {
    "main": [
      "./src/main.ts"
    ],
    "polyfills": [
      "./src/polyfills.ts"
    ],
    "styles": [
      "./src/styles.css"
    ],
    "webworker": [
      "./src/workerLoader.ts"
    ]
  },
  "output": {
    "path": path.join(process.cwd(), "dist"),
    "filename": "[name].bundle.js",
    "chunkFilename": "[id].chunk.js"
  },
  "module": { /*...a lot of stuff...*/ },
  "plugins": [
    //...some stuff...
    new HtmlWebpackPlugin({
      //...some stuff...
      "excludeChunks": [
        "webworker"
      ],
      //...some more stuff...
    }),
    new BaseHrefWebpackPlugin({}),
    new CommonsChunkPlugin({
      "name": "inline",
      "minChunks": null,
      "chunks": [
        "main",
        "polyfills",
        "styles"
      ]
    }),
    //...some stuff...
    new AotPlugin({
      "mainPath": "main.ts",
      "entryModule": "app/app.module#AppModule",
      //...some stuff...
    })
  ],
  //...some more stuff...
};




你准备好了

如果您已正确遵循前面的步骤,那么现在只需要编译代码并尝试结果。

运行npm start

Angular应用程序的所有逻辑都应该在WebWorker中运行,从而使UI更流畅。

Furter notes

npm start运行 webpack-dev服务器,并且在网络工作者在控制台日志上抛出错误消息时遇到了某种问题。无论如何,网络工作者似乎运行良好。 如果您使用webpack命令编译应用程序并从任何http服务器(如simplehttpserver)提供,则错误消失;)

示例代码和演示

您可以从this repo获取整个代码(webpack config,app.module.ts,...)。

您还可以在此处观看live demo,以查看使用Web Workers之间的差异

答案 1 :(得分:2)

好消息,我让它可以与Angular 7一起使用!

要求npm install --save-dev @angular-builders/custom-webpack html-webpack-plugin 如果您只想从下面复制/粘贴代码,请确保您的环境文件中包含production:true

第1步:按以下方式编辑angular.json文件:

"architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
                "path": "./webpack.client.config.js",
                "replaceDuplicatePlugins": true
             },
            ...
          }

您只在编辑build部分,因为您并不需要开发服务器中的全部工作人员。

第2步:在项目的根目录下创建webpack.client.config.js文件。 如果您不使用SSR,则可以删除exclude: ['./server.ts'],

const path = require('path');
const webpack = require('webpack');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { AngularCompilerPlugin } = require('@ngtools/webpack');

module.exports = {
  entry: {
    webworker: [
      "./src/workerLoader.ts"
    ],
    main: [
      "./src/main.ts"
    ],
    polyfills: [
      "./src/polyfills.ts"
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      excludeChunks: [
        "webworker"
      ],
      chunksSortMode: "none"
    }),
    new AngularCompilerPlugin({
      mainPath: "./src/main.ts",
      entryModule: './src/app/app.module#AppModule',
      tsConfigPath: "src/tsconfig.app.json",
      exclude: ['./server.ts'],
      sourceMap: true,
      platform: 0
    }),
  ],
  optimization: {
    splitChunks: {
      name: "inline"
    }
  }
}

第3步:编辑您的AppModule:

import { BrowserModule } from '@angular/platform-browser'
import { WorkerAppModule } from '@angular/platform-webworker'
const AppBootstrap =
            environment.production
            ? WorkerAppModule
            : BrowserModule.withServerTransition({ appId: 'myApp' })
    imports: [
        ...
        AppBootstrap,
        ...
    ]

步骤4 :编辑main.ts文件。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { bootstrapWorkerUi } from '@angular/platform-webworker';

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

if (environment.production) {
  enableProdMode();
  bootstrapWorkerUi('webworker.bundle.js');
}

else {
  document.addEventListener('DOMContentLoaded', () => {
    platformBrowserDynamic().bootstrapModule(AppModule);
  });
}

第5步:它将很好地编译,但是由于您的应用程序中存在DOM操作,您可能会遇到运行时问题。此时,您只需要删除所有DOM操作,然后将其替换为其他内容即可。我仍在努力弄清这部分内容,稍后将编辑我的答案以提供有关此问题的指导。

如果您不进行繁琐的DOM操作,那么最好使用免费的主线程,并且使用lighthouse审核应用程序不再显示Minimize main-thread work,因为除了UI加载之外,您的大多数应用程序在第二个线程中。