运行 Angular Web Worker 中的 2 个应用程序使用 WebPack

Run Angular 2 app in web worker using WebPack

我正在尝试将 Angular 2 应用程序的整个执行过程移交给网络工作者,但我发现现在所有可用的示例都在使用 System.js,并且我我正在尝试使用基于 WebPack 的项目(使用 angular-cli 构建)。

有没有人这样做过或知道如何使用 WebPack 做到这一点?

下面是我的main.tsbootstrap文件:

import './polyfills.ts';


import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';


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

import {bootstrapWorkerUi} from '@angular/platform-webworker';
bootstrapWorkerUi('/app/loader.js');

我的 loader.js 看起来像这样:

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

我的 app.module.ts 是这样声明的 @NgModule

import { NgModule } from '@angular/core';
import {WorkerAppModule} from '@angular/platform-webworker';


import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    WorkerAppModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
 export class AppModule { }

但是,当我 运行 它时,我收到错误 Uncaught SyntaxError: Unexpected token import in loader.js:1.

这个问题似乎与 webpack 有关,并且正如 Tamas Gegedus 和 MathMate 所建议的那样,在 webworker 端缺少@angular 库的导入,因此下一步是按顺序修改 webpack 配置文件向网络工作者提供所有必需的库。我会努力的。

------------ 更新 ----------

由于 angular-cli 不提供对 webpack.config.js 文件的访问权限,我已经包含了我的文件,对代码进行了一些小改动,以便它可以工作。我在 webpack 配置文件中创建了第二个入口点,但出现错误 VM33:106 Uncaught ReferenceError: window is not defined.

Webpack 配置文件如下所示:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var helpers = require('./config/helpers');


module.exports = {
  entry: {
    'app': ['./src/polyfills.ts', './src/vendor.ts', './src/main.ts'],
    'webworker': ['./src/workerLoader.ts']
  },

  resolve: {
    extensions: ['', '.ts', '.js']
  },

  output: {
    path: helpers.root('dist'),
    publicPath: 'http://localhost:8080/',
    filename: '[name].js'
  },

  devtool: 'cheap-module-eval-source-map',

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loaders: ['awesome-typescript-loader?tsconfig=./src/tsconfig.json', 'angular2-template-loader']
      },
      {
        test: /\.html$/,
        loader: 'html'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.css$/,
        exclude: helpers.root('src', 'app'),
        loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
      },
      {
        test: /\.css$/,
        include: helpers.root('src', 'app'),
        loader: 'raw'
      }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      excludeChunks: ['webworker']
    }),

    new ExtractTextPlugin('[name].css')
  ]
};

其中 polyfills.ts 和 vendor.ts 分别包含 polyfill 和 angular 库。

我创建了 2 个入口点,生成 2 个输出(app.js 和 webworker.js)。

使用 HtmlWebpackPlugin,第一个包含在 index.html 文件中,但第二个不包含。

当包含 index.html 时,调用 main.ts(包含在 app.js 中)并且 尝试 bootstrap webworker 使用 webpack 的第二个输出 (webworker.js):

import {bootstrapWorkerUi} from '@angular/platform-webworker';
bootstrapWorkerUi('../webworker.js');

webworker.js 由 webpack 使用 workerLoader.ts 条目生成,类似于之前的 loader.js,但包括一些导入。

WorkerLoader.ts 文件如下所示:

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

我知道已经生成了web worker,如下图,但是如图所示,我得到错误VM33:106 Uncaught ReferenceError: window is未定义 ,除了来自 index.html 的正在加载消息外,不显示任何内容。

另一方面,我认为 webpack 配置没问题,因为如果 运行在 NO webworker 模式下使用 webpack 应用程序,它工作正常。

现在我认为这个问题与 webworker bootstrap 有关,但我很卡在这里。

如有任何帮助,我们将不胜感激 ;)

正如 Tamas Hegedus 在评论中提到的那样,很可能您的 webpack 包仍在为 loader.js 引用 es6 文件。

您需要为加载程序脚本创建带有入口点的单独包。

如果您分享您的 webpack 配置,那么就可以更容易地判断哪里出了问题。

此外,您的加载程序脚本需要具有所需的 polyfill。您可以添加

进口'core-js/es7/reflect'; 导入 'zone.js/dist/zone';

我终于解决了这个问题:)

NOTE: if you have generated the project using Angular CLI 1.0 or higher, you can now use their own webpack config file, and that simplifies the whole process. Check .

运行使用我的自定义 webpack 配置修改代码后,我意识到 错误 VM33:106 Uncaught ReferenceError: window is not defined 是由 webpack-dev-server.

引起的

我通过以下方式解决了它:

1 - 进行独立的 webpack 构建

$: webpack --watch #this creates the bundes at myProject/dist

2 - 运行 另一个类似 simplehttpserver

的开发服务器工具
$: npm install simplehttpserver -g
$: simplehttpserver -p 8080 dist/ #as my webpack bundle is included in index.html using that port by default

瞧瞧,错误消失了,一切正常!

更改应用于 angular-cli 项目:Webpack 配置

让我总结一下关于原始 Angular-CLI 项目的 webpack 更改。

由于 angular-cli 不提供对 webpack.config.js 文件的访问权限,并且自定义 webpack 是使用 webworkers 的关键,我已经包含了我的代码,对代码进行了一些改动。

Webpack 配置文件如下所示:

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var helpers = require('./config/helpers');


module.exports = {
  entry: {
    'app': ['./src/polyfills.ts', './src/vendor.ts', './src/main.ts'],
    'webworker': ['./src/workerLoader.ts']
  },

  resolve: {
    extensions: ['', '.ts', '.js']
  },

  output: {
    path: helpers.root('dist'),
    publicPath: 'http://localhost:8080/',
    filename: '[name].js'
  },

  devtool: 'cheap-module-eval-source-map',

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loaders: ['awesome-typescript-loader?tsconfig=./src/tsconfig.json', 'angular2-template-loader']
      },
      {
        test: /\.html$/,
        loader: 'html'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.css$/,
        exclude: helpers.root('src', 'app'),
        loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
      },
      {
        test: /\.css$/,
        include: helpers.root('src', 'app'),
        loader: 'raw'
      }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      excludeChunks: ['webworker']
    }),

    new ExtractTextPlugin('[name].css')
  ]
};

其中 polyfills.ts 和 vendor.ts 分别包含 polyfill 和 angular 库。

我创建了 2 个入口点,生成 2 个输出(app.js 和 webworker.js)。

使用 HtmlWebpackPlugin,第一个包含在 index.html 文件中,但第二个不包含。

当包含 index.html 时,会调用 main.ts(包含在 app.js 中)并且 像这样引导 webworker这个:

import {bootstrapWorkerUi} from '@angular/platform-webworker';
bootstrapWorkerUi('../webworker.js');

webworker.js是webpack使用workerLoader.ts入口生成的代码。

WorkerLoader.ts 文件如下所示:

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

AppModule 看起来像这样:

import { NgModule } from '@angular/core';
import {WorkerAppModule} from '@angular/platform-webworker';


import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    WorkerAppModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
 export class AppModule { }

代码示例

为了更容易理解差异,我创建了一个项目来展示如何在基于 Web Worker 的项目中转换常规 angular 2 项目。检查此回购协议:https://github.com/kaikcreator/webWorkerFactorialExample

您将在 master 分支中看到“单线程”代码,并在 webWorkers 分支 中看到使用网络工作者对 运行 代码的更改。