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


我正在尝试将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');

9745
2017-10-19 11:27


起源

这意味着你没有在你的html中引用webpack编译的bundle,而是原始的es6文件。 - Tamas Hegedus
当设置为单个线程(具有典型的引导程序并且已经使用WebPack)时,应用程序工作正常,在引入我在代码中反映的更改时出现问题,以便在webworker中运行它。 - Enrique Oriol
我设法构建了一个项目并重现了你的问题:到目前为止,我理解有一个对-shim的引用,它为窗口对象增加了一些内容,从而打破了运行时。 - user2363245
但是,我仍然遇到一些css-loader的问题 - 继续调查 - user2363245
通过不使用webpack-dev-server,我能够摆脱“窗口未定义”,但现在我仍然坚持“没有PlatformLocation的提供者”,即使@ angular / common CommonModule存在。 - user2363245


答案:


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

注意: 如果你有 产生 该项目使用 Angular CLI 1.0 或者更高,您现在可以使用自己的webpack配置文件,这简化了整个过程。 检查 在这种情况下这个答案

使用我的自定义webpack配置运行代码后,我意识到了这一点 错误 VM33:106未捕获的ReferenceError:窗口未定义 是由...引起的 的WebPack-DEV-服务器

我通过以下方式解决了

1 - 做一个独立的webpack构建

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

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

而且,错误消失了 它只是工作!

应用于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 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');

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

而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的工作者中转换常规角度2项目。检查这个回购: https://github.com/kaikcreator/webWorkerFactorialExample

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


9
2017-11-24 17:21



我尝试了你的解决方案,但仍然在工作者中出现“未定义窗口”错误。问题似乎是在创建的webworker.js包中,webpack引用了窗口对象,它将自己绑定到UI线程。你能帮我这个吗? - NewtonCode
您使用webpack dev服务器来运行应用程序吗? - Enrique Oriol
不,我就像你一样使用simplehttpserver - NewtonCode
离开webpack-dev-server时我解决了这个问题。也许你包括en webworker.js不应该存在的东西。我已经使用URL将响应更新为使用带有webpack的angular 2 webworkers的示例repo。也许你可以找到你的答案。 - Enrique Oriol
@chliebel我已经创建了一个新的SO,其中包含使用CLI 1.0+的答案,因此您可以利用从中创建的webpack配置文件 ng eject。在这里查看: stackoverflow.com/questions/43276044/... - Enrique Oriol


正如Tamas Hegedus在评论中已经提到的,很可能你的webpack包仍然在引用loader.js的es6文件。

您需要使用加载程序脚本的入口点创建单独的bundle。

如果你共享你的webpack配置,那么就更容易分辨出事情可能出错的地方。

您的加载器脚本也需要具有所需的polyfill。你可以加

import'core-js / es7 / reflect'; import'zone.js / dist / zone';


1
2017-10-23 11:11



好吧,我已经认为这个问题是朝这个方向发展的,但是你的评论让我们更清楚了。问题是angular-cli在内部使用webpack,但没有任何webpack.config.js文件。我将弄清楚如何将它与配置文件一起使用以及如何定义新的入口点以便留下解决方案。 - Enrique Oriol
我尝试使用加载器脚本的第二个入口点,但现在我正面临Web worker中的错误“VM33:106未捕获的ReferenceError:窗口未定义”。我已更新问题以分享所有细节。 - Enrique Oriol