使用 WebPack 在 Web Worker 中运行 Angular 2 应用程序 [英] Run Angular 2 app in web worker using WebPack

查看:32
本文介绍了使用 WebPack 在 Web Worker 中运行 Angular 2 应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

有没有人做过这个或者有关于如何用 WebPack 做到这一点的想法?

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

import './polyfills.ts';从@angular/core"导入 { enableProdMode };从'./environments/environment'导入{环境};如果(环境.生产){enableProdMode();}从@angular/platform-webworker"导入 {bootstrapWorkerUi};bootstrapWorkerUi('/app/loader.js');

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

import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic';从 './app/' 导入 { AppModule };platformWorkerAppDynamic().bootstrapModule(AppModule);

我的app.module.ts以这种方式声明@NgModule:

import { NgModule } from '@angular/core';从@angular/platform-webworker"导入 {WorkerAppModule};从 './app.component' 导入 { AppComponent };@NgModule({声明: [应用组件],进口:[工人应用程序模块],提供者:[],引导程序:[AppComponent]})导出类 AppModule { }

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

这个问题似乎与 webpack 和 webworker 端缺少 @angular 库的导入有关,正如 Tamas Gegedus 和 MathMate 所建议的,所以下一步是修改 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');模块.出口 = {入口: {'app': ['./src/polyfills.ts', './src/vendor.ts', './src/main.ts'],'网络工作者':['./src/workerLoader.ts']},解决: {扩展名:['', '.ts', '.js']},输出: {路径:helpers.root('dist'),publicPath: 'http://localhost:8080/',文件名:'[名称].js'},开发工具:廉价模块评估源地图",模块: {装载机: [{测试:/\.ts$/,加载器:['awesome-typescript-loader?tsconfig=./src/tsconfig.json', 'angular2-template-loader']},{测试:/\.html$/,加载器:'html'},{测试:/\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,loader: 'file?name=assets/[name].[hash].[ext]'},{测试:/\.css$/,排除:helpers.root('src', 'app'),loader: ExtractTextPlugin.extract('style', 'css?sourceMap')},{测试:/\.css$/,包括: helpers.root('src', 'app'),装载机:'原始'}]},插件: [新的 HtmlWebpackPlugin({模板:'src/index.html',excludeChunks: ['webworker']}),new ExtractTextPlugin('[name].css')]};

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

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

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

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

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

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

WorkerLoader.ts 文件如下所示:

import './polyfills.ts';导入'@angular/core';导入'@angular/common';从@angular/platform-webworker-dynamic"导入{platformWorkerAppDynamic};从 './app/' 导入 { AppModule };platformWorkerAppDynamic().bootstrapModule(AppModule);

我知道 web worker 已经生成,如下图所示,但是如下图所示,我得到错误 VM33:106 Uncaught ReferenceError: window is not defined,并且除了来自 index.html 的 Loading 消息外,没有显示任何内容.

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

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

任何帮助将不胜感激;)

解决方案

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

<块引用>

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

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

我通过以下方式解决了:

1 - 做一个独立的 webpack 构建

$: webpack --watch #this 在 myProject/dist 创建bundes

2 - 与另一个开发服务器工具一起运行,例如 simplehttpserver

$: npm install simplehttpserver -g$: simplehttpserver -p 8080 dist/#as 我的 webpack 包默认包含在 index.html 中,使用该端口

瞧,错误消失了,它可以正常工作!

应用于 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');模块.出口 = {入口: {'app': ['./src/polyfills.ts', './src/vendor.ts', './src/main.ts'],'网络工作者':['./src/workerLoader.ts']},解决: {扩展名:['', '.ts', '.js']},输出: {路径:helpers.root('dist'),publicPath: 'http://localhost:8080/',文件名:'[名称].js'},开发工具:廉价模块评估源地图",模块: {装载机: [{测试:/\.ts$/,加载器:['awesome-typescript-loader?tsconfig=./src/tsconfig.json', 'angular2-template-loader']},{测试:/\.html$/,加载器:'html'},{测试:/\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,loader: 'file?name=assets/[name].[hash].[ext]'},{测试:/\.css$/,排除:helpers.root('src', 'app'),loader: ExtractTextPlugin.extract('style', 'css?sourceMap')},{测试:/\.css$/,包括: helpers.root('src', 'app'),装载机:'原始'}]},插件: [新的 HtmlWebpackPlugin({模板:'src/index.html',excludeChunks: ['webworker']}),new ExtractTextPlugin('[name].css')]};

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

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

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

当包含 index.html 时,ma​​in.ts(包含在 app.js 中)被调用并像这样引导 webworker:

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

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

WorkerLoader.ts 文件如下所示:

import './polyfills.ts';导入'@angular/core';导入'@angular/common';从@angular/platform-webworker-dynamic"导入{platformWorkerAppDynamic};从 './app/' 导入 { AppModule };platformWorkerAppDynamic().bootstrapModule(AppModule);

AppModule 看起来像这样:

import { NgModule } from '@angular/core';从@angular/platform-webworker"导入 {WorkerAppModule};从 './app.component' 导入 { AppComponent };@NgModule({声明: [应用组件],进口:[工人应用程序模块],提供者:[],引导程序:[AppComponent]})导出类 AppModule { }

代码示例

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

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

I'm trying to move the whole execution of an Angular 2 app to a web worker, but I've find out that all examples available right now are using System.js, and I'm trying to do so with a WebPack based project (built with angular-cli).

Has anyone done this or have an idea on how to do this with WebPack?

Below is my main.ts bootstrap file:

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

My loader.js looks like this:

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

And my app.module.tsis declaring @NgModulethis way:

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 { }

However, when I run it, I get the error Uncaught SyntaxError: Unexpected token import in loader.js:1.

The issue seems related with webpack and some lack of imports of @angular libs in the webworker side, as suggested by Tamas Gegedus and MathMate, so the next step is to modify the webpack config file in order to provide all the required libs to the webworker. I'll work on that.

----------- UPDATE -----------

Since angular-cli do not provide access to webpack.config.js file, I've included mine, making little changes in code so it can work. I created the second entry point at webpack config file and I'm getting the error VM33:106 Uncaught ReferenceError: window is not defined.

Webpack config file looks like this:

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')
  ]
};

where polyfills.ts and vendor.ts include polyfills and angular libs respectively.

I've created 2 entry points, that generate 2 outputs (app.js and webworker.js).

With the HtmlWebpackPlugin, the first one is included in the index.html file, but not the second one.

When index.html is included, main.ts (contained in app.js) is called and tries to bootstrap the webworker using the second output of webpack (webworker.js):

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

webworker.js has been generated by webpack using workerLoader.ts entry, that is like previous loader.js, but including some imports.

WorkerLoader.ts file looks like this:

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

I know that the web worker is been generated, as shown in the following image, but as shown in the image, I get the error VM33:106 Uncaught ReferenceError: window is not defined, and nothing is displayed except the Loading message from index.html.

On the other side, I think that the webpack config is OK because if running the app with webpack in NO webworker mode, it works fine.

Right now I think that this issue is related with webworker bootstrap, but I'm quite stucked here.

Any help would be appreciated ;)

解决方案

I finally solved the issue :)

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 this answer in that case.

After running the code with my custom webpack config, I realized that the error VM33:106 Uncaught ReferenceError: window is not defined was caused by webpack-dev-server.

I solved it by:

1 - doing a standalone webpack build

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

and

2 - running with another devserver tool like simplehttpserver

$: npm install simplehttpserver -g
$: simplehttpserver -p 8080 dist/ #as my webpack bundle is included in index.html using that port by default

And voilà, the error is gone and it simply works!

 

Changes applied to angular-cli project: Webpack config

Let me summarize the webpack changes regarding the original Angular-CLI project.

As angular-cli do not provide access to webpack.config.js file and customizing webpack is key to use webworkers, I've included mine, making little changes in code.

Webpack config file looks like this:

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')
  ]
};

where polyfills.ts and vendor.ts include polyfills and angular libs respectively.

I've created 2 entry points, that generate 2 outputs (app.js and webworker.js).

With the HtmlWebpackPlugin, the first one is included in the index.html file, but not the second one.

When index.html is included, main.ts (contained in app.js) is called and bootstraps the webworker like this:

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

webworker.js is the code webpack generated using workerLoader.ts entry.

WorkerLoader.ts file looks like this:

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

And AppModule looks like this:

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 { }

Code example

To make easier to understand the differences, I've created a project showing how to convert a regular angular 2 project in a web workers based one. Check this repo: https://github.com/kaikcreator/webWorkerFactorialExample

You'll see in master branch the "single thread" code, and in webWorkers branch, the changes to run code using web workers.

这篇关于使用 WebPack 在 Web Worker 中运行 Angular 2 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆