Angular-cli: Feat: Run angular in web worker mode

Created on 23 Sep 2016  Β·  65Comments  Β·  Source: angular/angular-cli

In current setup there is no possibility to bootstrap angular in web worker mode.
Please add this killer functionality.

devkibuild-angular triage #1 feature

Most helpful comment

I've been waiting for that too :sweat_smile:

image

It'd be nice to see the priority bumping at least from 3 to 2 ;)

All 65 comments

Currently also looking for a good way to accomplish it. Any1 got a workaround for now?

No support at the moment, but we are looking at it.

Any news here?
Thanks!

I'm also curious if there have been any updates to this.

Also looking for this.

... need this feature!!!

For those who can't wait, I've found a good post on stackoverflow.

I've heard of Angular running in a webworker in the early days of angular.
But when you try it out on a real demo : https://kaikcreator.github.io/angular-cli-web-worker/ ...
It's something :tada: !

Now I'm just wondering whether I'm gonna wait for built in solution with the cli or ng eject :smile:

The stackoverflow approach seems reasonable. Would a PR with this be welcome here?

Gotta try to find out @bmayen ! Seriously I think that yes it'd be welcome and even tho it might not be perfect the first time after few iterations it might go to master ... :smiley:

Don't forget to reference this issue if you try something so we can follow what's going on :+1: !

@maxime1992 Thanks for posting that, I'm not sure why workers (--mobile) were cut from angular-cli.

This is something that we've been exploring. There's currently limited experimental support that you can try by doing:

npm install --save @angular/service-worker
ng set apps.0.serviceWorker=true
ng build --prod

Now --prod builds will generate and load a service worker.

/cc @alxhub

@filipesilva, your comment refers to a service worker, but the issue pertains to web workers. Typo or am I missing something here?

@filipesilva dude there is fundamental difference between webworker and serviceworker.

Sorry guys, this was a major durf on my part. Completely misread the issue.

Service workers would still be nice to have. They don't yet have full modern browser support though, so not as urgent IMO. Web workers on the other hand... :)

@bmayen Service workers are available, very nice tutorial here: https://docs.google.com/document/d/19S5ozevWighny788nI99worpcIMDnwWVmaJDGf_RoDY/edit#

@mwent-cray, this document is all about Service Workers, not Web Workers. They are different things with different objectives.

@willgm I know it is about WEB workers, I was pointing to @bmayen 's post.

The tutorial posted by Enrique here:https://medium.com/@enriqueoriol/angular-with-web-workers-step-by-step-dc11d5872135 using the ng eject approach works for a basic app, I tried to get it to work on my Angular 4 application but I had to get
rid of 'hammerjs' to remove a window undefined error and now I am getting a PlatformLocation provider error...it seem that the routing module breaks it!

Has anyone had any luck getting webworkers with ng eject working ?

Unfortunately not, but haven't done too much additional research into it. Our webworker apps simply do not use Angular CLI now :( Not that we wouldn't love to migrate them over though! @filipesilva, is there any chance of bumping this priority up from "nice to have"? I'd argue that it's higher than that because it's major Angular functionality which isn't supported.

Bump.

@filipesilva For larger applications with heavy computations this is quite important. Otherwise the cli tool is more or less a no go. Agree with @bmayen that this should be bumped. Given the number of "thumbs up" across this post would it be worth reconsidering?

FWIW, sorting issues by reaction shows this as the top 3 for both +1s and hearts. Definitely a strong community desire behind this!

Hey all, I brought this up with the team today, and currently this is something we're interested in adding, but not something we have the time right now to both incorporate and properly validate that would work.

It would probably require a new entry point for the worker bootstrap and some codegen changes. I'm sorry to say that for now the recommended approach is to eject.

@maxime1992 posted about a very detailed guide: https://stackoverflow.com/questions/43276044/angular-cli-generated-app-with-web-workers/43276045

Have you tried it? Does it work in all cases? What are the caveats? This sort of information would be very valuable for the initial design of it. Having a clear path that starts at ejecting helps define what needs to change inside the CLI for non-ejected projects.

Thanks @filipesilva. Unfortunately I don't have any detailed feedback to provide on the eject-based approach. Our project which needed WW was based on the AngularClass starter and we rolled our own solution there; based on that link but not using the CLI.

We had started work on a PR to integrate the above approach in the CLI, but according to https://github.com/angular/angular-cli/issues/5885#issuecomment-300446321, this would not have been the preferred approach, so we decided to abandon it and wait for the pending platform-server work to pave the way. But if a PR along these lines would be welcomed now, I could potentially revisit that WIP (depending on availability).

@filipesilva @bmayen

One of the issues with the eject approach is that it is not possible to hash the bundle file names. It also seems that we need multiple config files for multiple environment builds which becomes a bit unwieldily. Admittedly, refactoring the config would solve this.

@MurhafSousli I am right there with you, one of the few reasons I won't be making anything new with angular if I can help it. πŸ˜•

I've been waiting for that too :sweat_smile:

image

It'd be nice to see the priority bumping at least from 3 to 2 ;)

I have this suspicion for a while, that the reason that we seen no progress on this is because the angular team is moving in another direction or waiting for some other technology that would make the current webwork implementation obsolet.

I have no proof of this, but I think the answer to the question about what new technology the different framework looks forward to the most during the "Chrome Dev Summit 2017" is telling. Basically everyone agrees that the DOMChangeList would be great.

Please see the answer from the Angular representative on the panel here:
http://www.youtube.com/watch?v=q5HDhQtpDRU&t=3m30s

And more about the DOMChangeList here:
https://github.com/whatwg/dom/issues/270

How would this make current implementation obsolete? Wouldn't current implementation just batch calls to the UI thread via DOMChangeList? There would be changes required to DomRenderer, sure, but I don't see this completely deprecating the current Webworkers implementation. More of an optimization, no?

In terms of how this affects CLI, I don't see it either. The issue with missing CLI support is less to do with the specific Angular implementation AFAIK.

Sorry I were a bit unclear in my comment. I don't mean it is obsolet, that were only my suspicion. What I tried to say is things are happening in this space an I think one of the reasons we are not seeing any progress on this is because things are still a bit up in the air. But this is of course just speculations.

I want to share my experience with you.

I made a enterprise application with Angular V4 and when I render a couple hundred records on screen it's incredible more slower than in AngularJs.
I'm sure I haven't done all the performance work to get it working smooth.
But in the development stage of the app it works at light speed, I see this slow app now that the volume of records growth and had the chance to experience the (now) normal UI block all the time. In the other hand my old AngularJs app has the same info and maintains its usual speed, not so fast, but no the slowest.

I really don't know if this change could improve the UI speed, but I know that in my case, when a huge payload of information is handled by Angular, all those filters, maps, and other transform operations feels right to be done in a separate thread.

It's just an opinion, I would really like to see this come through.

Thanks for the great work!!!

@IgorMinar @mhevery I heard from @hansl you had looked into this topic, could you give an answer here please?

Can you get a rough estimate for the cli integration and we can discuss it
then during the next planning session.

On Tue, Nov 14, 2017, 11:32 AM Filipe Silva notifications@github.com
wrote:

@IgorMinar https://github.com/igorminar @mhevery
https://github.com/mhevery I heard from @hansl
https://github.com/hansl you had looked into using Webworkers in
Angular, could you give an answer here please?

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/2305#issuecomment-344215407,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AANM6JF4RXYoXWo97j2sar8nCtyKuvVtks5s2WxYgaJpZM4KEyA1
.

@IgorMinar and @filipesilva can you please also discuss how Material 5 could be integrated when running Angular app in Web worker mode?

Ref: https://github.com/angular/material2/issues/1406#issuecomment-251141980

Current plan is to support it once the WebWorker support in Angular core improves. In particular, Material needs custom renderers (to deal with marshalling between UI and worker threads).

However, it's not yet clear whether using web workers at all would actually be an improvement for the types on lower-level ui components that material offers; pretty much all of the logic in the components deals with changing the rendered DOM in some way. Given that, it may end up being faster for material to continue running on the UI thread even when web-worker support is out of experimental.

It takes no long until you face a situation in your app where it could be great to have the Web worker mode feature. I've been using Angular + Material for about a year and right now one of my projects needs a dashboard. Lots of json data could potentially arrive from the backend to be plotted on the screen (depends on how complex each end user will setup his particular dashboards - there's no limit on the number of charts he can choose to see in each of his dashboards) and I'm really worried about how this feature will behave without web workers. It doesn't depends just on Angular, but also on chartjs - apparently both of them need hacks to run in web worker mode.

Ideally I'd show a panel to the user and after that I'd go to the server to get each chart data - and the charts, one by one, would become visible in the panel. But if I do that, it's likely each chart won't be updated in the screen smoothly. So I changed my mind and I think I'll get all of the data from the server before showing the user anything. And I hope it works.

I think I'll have some trouble with ux sooner or later.

I've created a web-worker.service to offload high CPU tasks similar to the example/demo posted above and I am now a huge fan as well. This would be a great addition to the cli!

Anyone have any update to date webpack configs with Angular 5 for this? My web workers stopped working after migrating from 4 to 5.

I am looking for adding Web worker with Angular CLI but didn't found nay solution yet. Waiting for this !!!

If you want to use Web Workers in Angular, just use the Web Worker. See angular2-web-worker$web-worker.ts for an implementation. Is plain simple JS at the end.

This is about run the entire Angular application inside a Web Worker.

@dipaktelangre check out @fedeee comment about Angular with Web Workers Step by step

I waiting for this for a long time, this can improve any apps performance significantly. Although we have managed to handle it manually that would be nice if the Angular team can support it out of the box in Angular/cli.

BTW, would be nice if Angular team can share their discussions here, maybe someone (for instance myself) can help to send a PR and help to get this done quicker.

ng eject no longer works; is there any hope of accomplishing this with angular-cli-builders?

Any news on that? I have a table of a lot of heavy OnPush components, everything works fine, except for when they are initiated at first β€” would love to show loader spinning while they do, but for it to not freeze the UI they need to initialize in a worker.

Could that be helpful to a smooth integration with the CLI?
https://github.com/GoogleChromeLabs/worker-plugin

No news about this??? 😴😴😴😴

Having the choice to do it would be really nice

@maxime1992 there's ongoing work to add that plugin in https://github.com/angular/angular-cli/pull/12575.

One of the problems is when you load modules and material2 animations get stuck.

Material2 works with DOM manipulation, so it won't run in a web worker.

Yes, but maybe the loading of the modules could be done in a web worker.

Any news on that? people are existed with that feature.

with the ng eject command removed, there's no way to load the workderLoader file.. considering that @angular/platform-webworker and @angular/platform-webworker-dynamic are part of angular there's literally no way to use them as a developer at the moment with the new cli version. I'd expect them to work with the cli by default.. Perhaps an ng add @angular/platform-webworker command could do.

Are there any updates/workarounds and how to do this considering that ejecting is not possible anymore? this was one of the most exciting features about angular that was show cased in ng-conf when angular2 was first released.

@khaledosman I've been trying to implement this for a little while. I got some results but it's still a work in progress. Here is what I've been doing so far:

npm install --save-dev @angular-builders/custom-webpack

src/main.ts

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

src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser'
import { WorkerAppModule } from '@angular/platform-webworker'

const AppBootstrap =
    environment.production
    ? WorkerAppModule
    : BrowserModule.withServerTransition({ appId: 'myApp' })

imports: [
    ...
    AppBootstrap
]

angular.json

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

                }
             },

webpack.client.config.js

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"
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      excludeChunks: [
        "webworker"
      ],
      chunksSortMode: "none"
    }),
    new AngularCompilerPlugin({
      mainPath: path.join(__dirname, "src/main.ts"),
      tsConfigPath: path.join(__dirname, "src/tsconfig.app.json"),
      entryModule: path.join(__dirname, "src/app/app.module#AppModule"),
      exclude: ['./server.ts']
    })
  ],
  optimization: {
    splitChunks: {
      name: "inline"
    }
  }
}

src/workerLoader.ts

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

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

platformWorkerAppDynamic().bootstrapModule(AppModule);

Running bg build produces the following error: ERROR in : TypeError: Cannot read property 'getTypeChecker' of undefined

If I remove the AngularCompilerPlugin in the custom webpack file, it does compile successfully but the client can't find app-root.

If anybody here figures something out, let me know. I'll keep digging.

Hey guys! I got this to work with Angular7!

Here is copy of my StackOverflow answer:

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 the code 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.

@glemiere it gives me webworker.bundle.js not found
where I can find webworker.bundle.js ?
Thanks

@glemiere good work.

Is angular official support for this ever gonna be a thing ?

platform-webworker deprecated
https://github.com/angular/angular/pull/30642

Indeed @bmayen it's not officially deprecated in v8 https://github.com/angular/angular/commit/361f181

That is a huge disappointment. We were all very excited about this.
To let everybody know, it is still possible to run parts of your code inside a webworker to make multi-threading possible. I just wish Angular had at least offered the possibility to run services or anything web crawlers don't care much about in separate threads.

I will be digging into making a library to make this behavior possible and developer friendly, any help is welcome. Thanks everybody for the hard workπŸ’ͺ

Running Angular itself in a Web Worker (via @angular/platform-webworker) is indeed deprecated. But it is now easier to run parts of your app in a Web Worker using https://angular.io/guide/web-worker.

I came across web workers recently and early thoughts went into the direction of @angular/platform-browser:

  • abstract the DOM APIs away,
  • thus, code would run in a worker...

I just flipped the idea the other way around:

  • DONT ABSTRACT the DOM APIs away,
  • Extract the _supposed to run in a worker_-code,
  • Wrap it in a _if no worker_-fallback.

You would end up with a style of code like this:

// All worker-compatible code goes to @my/worker
import { WorkerFacade, workerCompatibleCode } from '@my/worker';

// WorkerFacade would implement the "if no worker" fallback and messaging from UI to worker
const myWorker: WorkerFacade = /* ... */

const runnableInWorker = myWorker
  // You would need to map messages to function calls in the worker (not shown here)
  .postToWorker({ run: 'workerCompatibleCode', data: { foo: 'bar' } })
  // workerCompatibleCode() would be run in the UI were web worker isn't available
  .orElse(() => workerCompatibleCode());

runnableInWorker.subscribe(result=> {
 console.log("result was returned either from a web worker or from UI process");
});

Running Angular inside a web worker has been deprecated for a while now, as it just isn't typically beneficial for performance: https://angular.io/guide/deprecations#webworker-apps. As a result, the CLI doesn't support this use case anymore.

Applications can still add web workers to run their own CPU-intensive tasks, just not running Angular itself. See https://angular.io/guide/web-worker for more on that.

I'd really like to use angular's dependency injection system in my web workers. I have a bunch of heavily modularized Angular services that rely heavily on the Angular DI system. I'd like to use some of those services in a web worker (even if it meant instantiating a secondary service tree that lived on the web worker side.) Does anyone have any suggestions on how to replicate that kind of approach in a web worker? Ideally reusing the actual service code, if possible?

@pshields I assume using Angular DI system directly into a webworker would be hard but I remember that Minko extracted the DI part into a separate project which is browser agnostic (can work on Node) :tada:

https://github.com/mgechev/injection-js Maybe this will help you

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brtnshrdr picture brtnshrdr  Β·  3Comments

IngvarKofoed picture IngvarKofoed  Β·  3Comments

NCC1701M picture NCC1701M  Β·  3Comments

jmurphzyo picture jmurphzyo  Β·  3Comments

ericel picture ericel  Β·  3Comments