Run Angular 2 app in web worker using WebPack

前端 未结 2 1005
野性不改
野性不改 2020-12-16 17:16

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

相关标签:
2条回答
  • 2020-12-16 17:22

    As Tamas Hegedus has already mentioned in comment, most likely your webpack bundle is still referring es6 file for loader.js.

    You need to create separate bundle with entry point for loader script.

    If you share your webpack config then it would be easier to tell where the things might be going wrong.

    Also your loader script needs to have required polyfills. You can add

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

    0 讨论(0)
  • 2020-12-16 17:34

    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.

    0 讨论(0)
提交回复
热议问题