使用WebPack在Web worker中运行Angular 2应用程序

Enr*_*iol 12 web-worker webpack angular-cli angular

我正在尝试将Angular 2应用程序的整个执行移动到Web工作者,但我发现现在所有可用的示例都使用System.js,而我正在尝试使用基于WebPack的项目(用angular-cli构建).

有没有人这样做过,或者对如何使用WebPack有所了解?

下面是我的main.ts引导程序文件:

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');
Run Code Online (Sandbox Code Playgroud)

loader.js看起来像这样:

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

platformWorkerAppDynamic().bootstrapModule(AppModule);
Run Code Online (Sandbox Code Playgroud)

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 { }
Run Code Online (Sandbox Code Playgroud)

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

根据Tamas Gegedus和MathMate的建议,这个问题似乎与webpack和webworker端缺少@angular libs的导入有关,所以下一步是修改webpack配置文件,以便为webworker提供所有必需的libs .我会继续努力的.

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

由于angular-cli不提供对webpack.config.js文件的访问,因此我已经包含了我的代码,对代码进行了少量更改,因此它可以正常工作.我在webpack配置文件中创建了第二个入口点,我收到错误VM33:106 Uncaught ReferenceError:窗口未定义.

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')
  ]
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

import {bootstrapWorkerUi} from '@angular/platform-webworker';
bootstrapWorkerUi('../webworker.js');
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

我知道已经生成了Web worker,如下图所示,但是如图所示,我收到错误VM33:106 Uncaught ReferenceError:窗口未定义,除了从索引加载消息外没有显示任何内容. HTML. 网络工作者实例

另一方面,我认为webpack配置是正常的,因为如果在没有webworker模式下使用webpack运行应用程序,它可以正常工作.

现在我认为这个问题与webworker bootstrap有关,但我在这里很困惑.

任何帮助,将不胜感激 ;)

Enr*_*iol 9

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

注意:如果您使用Angular CLI 1.0或更高版本生成项目,则现在可以使用自己的webpack配置文件,这样可以简化整个过程.在这种情况下检查这个答案.

在使用我的自定义webpack配置运行代码后,我意识到错误VM33:106 Uncaught ReferenceError:窗口未定义是由webpack-dev-server引起的.

我通过以下方式解决了

1 - 做一个独立的webpack构建

$: webpack --watch #this creates the bundes at myProject/dist
Run Code Online (Sandbox Code Playgroud)

2 - 使用另一个devserver工具运行,如simplehttpserver

$: npm install simplehttpserver -g
$: simplehttpserver -p 8080 dist/ #as my webpack bundle is included in index.html using that port by default
Run Code Online (Sandbox Code Playgroud)

瞧,错误已经消失,它只是起作用!

 

应用于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')
  ]
};
Run Code Online (Sandbox Code Playgroud)

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

我创建了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');
Run Code Online (Sandbox Code Playgroud)

webworker.js是使用workerLoader.ts条目生成的代码webpack.

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);
Run Code Online (Sandbox Code Playgroud)

而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 { }
Run Code Online (Sandbox Code Playgroud)

代码示例

为了更容易理解这些差异,我创建了一个项目,展示了如何在基于Web的工作者中转换常规角度2项目.检查此repo:https://github.com/kaikcreator/webWorkerFactorialExample

您将在master分支中看到"单线程"代码,并在webWorkers分支看到使用Web worker运行代码的更改.