Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web worker setup in Angular 7.0.1

I am trying to do web-worker setup in my existing Angular 7.0.1 project (medium scale project). I did the setup after going through the following links:

  • Web workers setup for Angular 4 app
  • Webpack config change for Angular 6+ app - library and related article

Here are my changes in each file:

./src/main.ts

import 'zone.js';
import { enableProdMode } from '@angular/core';
import { bootstrapWorkerUi } from '@angular/platform-webworker';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

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

console.log("main.ts file loaded!");
bootstrapWorkerUi('webworker.js');

./src/workerLoader.ts

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

console.log("workerLoader.ts file loaded!");

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

./angular.json

"projects": {
  "[project name]": {
    "architect": {
      "build": {
        "builder": "@angular-builders/custom-webpack:browser",
        "options": {
          "customWebpackConfig": {
            "path": "./extra-webpack.config.js"
          }
          ...
          ...
        }
      }
    }
  }
}

./extra-webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    "entry": {
        "webworker": [
            "./src/workerLoader.ts"
        ]
    },
    "plugins": [
        new HtmlWebpackPlugin({
            "excludeChunks": [
                "webworker"
            ],
        })
    ],
    "output": {
        "globalObject": 'this'
    }
}

./tsconfig.json

{
    ...
    ...
    "angularCompilerOptions": {
        "entryModule": "./app/app.module#AppModule"
    }
}

Here is the demo. You might want to check my research notes.

I might be going in completely wrong direction because I just need to include and run a angular service worker library in Angular project (which should be super easy).

My main intention of trying to include webworker is to let the web app run on multi-thread so that the animations, checkbox, custom dropdown and scroll effects on the screen performs smoothly.

like image 604
Mr_Green Avatar asked Nov 01 '18 11:11

Mr_Green


1 Answers

Here is a copy of my answer here

Good news guys, I got this to work with Angular 7! 🎉🎉🎉

Requirement: npm install --save-dev @angular-builders/custom-webpack html-webpack-plugin Make sure that you have production:true in your env file if you just want to copy/past code from below.

Step 1: Edit your angular.json file the following way:

"architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
                "path": "./webpack.client.config.js",
                "replaceDuplicatePlugins": true
             },
            ...
          }

You are only editing the build part because you don't really need the whole worker thing in dev server.

Step 2: Create webpack.client.config.js file at the root of your project. If you're not using SSR, you can remove exclude: ['./server.ts'],

const path = require('path');
const webpack = require('webpack');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { AngularCompilerPlugin } = require('@ngtools/webpack');

module.exports = {
  entry: {
    webworker: [
      "./src/workerLoader.ts"
    ],
    main: [
      "./src/main.ts"
    ],
    polyfills: [
      "./src/polyfills.ts"
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      excludeChunks: [
        "webworker"
      ],
      chunksSortMode: "none"
    }),
    new AngularCompilerPlugin({
      mainPath: "./src/main.ts",
      entryModule: './src/app/app.module#AppModule',
      tsConfigPath: "src/tsconfig.app.json",
      exclude: ['./server.ts'],
      sourceMap: true,
      platform: 0
    }),
  ],
  optimization: {
    splitChunks: {
      name: "inline"
    }
  }
}

Step 3: Edit you AppModule:

import { BrowserModule } from '@angular/platform-browser'
import { WorkerAppModule } from '@angular/platform-webworker'
const AppBootstrap =
            environment.production
            ? WorkerAppModule
            : BrowserModule.withServerTransition({ appId: 'myApp' })
    imports: [
        ...
        AppBootstrap,
        ...
    ]

Step 4: Edit you main.ts file.

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { bootstrapWorkerUi } from '@angular/platform-webworker';

import {AppModule} from './app/app.module';
import {environment} from './environments/environment';

if (environment.production) {
  enableProdMode();
  bootstrapWorkerUi('webworker.bundle.js');
}

else {
  document.addEventListener('DOMContentLoaded', () => {
    platformBrowserDynamic().bootstrapModule(AppModule);
  });
}

Step 5: It will compile just fine, but you may have a runtime issue due to DOM manipulation in your app. At this point you just have to remove any DOM manipulation and replace it by something else. I'm still working at figuring this part out and will edit my answer later to give direction about this issue.

If you're not doing savage DOM manipulation, then you're good to go with a free main-thread and auditing your app using lighthouse should not show Minimize main-thread work anymore, as most of your app except UI loads in a second thread.

like image 107
Dev Avatar answered Nov 09 '22 02:11

Dev