Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Run angular in web worker mode #2305

Closed
k3nsei opened this issue Sep 23, 2016 · 65 comments
Closed

Feat: Run angular in web worker mode #2305

k3nsei opened this issue Sep 23, 2016 · 65 comments
Labels
area: devkit/build-angular feature Issue that requests a new feature
Milestone

Comments

@k3nsei
Copy link

k3nsei commented Sep 23, 2016

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

@filipesilva filipesilva added type: enhancement P5 The team acknowledges the request but does not plan to address it, it remains open for discussion labels Oct 3, 2016
@datrinh
Copy link

datrinh commented Oct 9, 2016

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

@filipesilva
Copy link
Contributor

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

@armaserg
Copy link

Any news here?
Thanks!

@alexjlockwood
Copy link

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

@jhertz123
Copy link

Also looking for this.

@IPRIT
Copy link

IPRIT commented Apr 9, 2017

... need this feature!!!

@maxime1992
Copy link
Contributor

maxime1992 commented Apr 15, 2017

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 🎉 !

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

@bmayen
Copy link

bmayen commented Apr 19, 2017

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

@maxime1992
Copy link
Contributor

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 ... 😃

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

@jakeNiemiec
Copy link

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

@k3nsei k3nsei changed the title Feat: Run angular2 in web worker mode Feat: Run angular in web worker mode Apr 21, 2017
@filipesilva filipesilva self-assigned this May 4, 2017
@filipesilva filipesilva added feature Issue that requests a new feature and removed type: enhancement labels May 4, 2017
@filipesilva
Copy link
Contributor

filipesilva commented May 4, 2017

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

@bmayen
Copy link

bmayen commented May 4, 2017

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

@k3nsei
Copy link
Author

k3nsei commented May 4, 2017

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

@filipesilva
Copy link
Contributor

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

@bmayen
Copy link

bmayen commented May 4, 2017

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... :)

@mwent-cray
Copy link

mwent-cray commented Jun 7, 2017

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

@willgm
Copy link

willgm commented Jun 7, 2017

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

@mwent-cray
Copy link

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

@fedeee
Copy link

fedeee commented Jul 6, 2017

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 ?

@bmayen
Copy link

bmayen commented Jul 6, 2017

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.

@ShadowManu
Copy link

Bump.

@maxime1992
Copy link
Contributor

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

@mhosman
Copy link

mhosman commented Nov 12, 2018

No news about this??? 😴😴😴😴

@ngbot ngbot bot added this to the Backlog milestone Jan 24, 2019
@cedvdb
Copy link

cedvdb commented Jan 27, 2019

Having the choice to do it would be really nice

@filipesilva
Copy link
Contributor

@maxime1992 there's ongoing work to add that plugin in #12575.

@mhosman
Copy link

mhosman commented Jan 28, 2019

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

@michaeljota
Copy link

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

@mhosman
Copy link

mhosman commented Jan 28, 2019

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

@Serginho
Copy link

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

@khaledosman
Copy link

khaledosman commented Feb 20, 2019

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.

@glemiere
Copy link

@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.

@glemiere
Copy link

glemiere commented Feb 27, 2019

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.

@LeonBarroso
Copy link

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

@cedvdb
Copy link

cedvdb commented Mar 19, 2019

@glemiere good work.

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

@bmayen
Copy link

bmayen commented May 24, 2019

platform-webworker deprecated
angular/angular#30642

@glemiere
Copy link

glemiere commented Jun 10, 2019

Indeed @bmayen it's not officially deprecated in v8 angular/angular@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💪

@filipesilva
Copy link
Contributor

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.

@dherges
Copy link

dherges commented Mar 6, 2020

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

@alan-agius4 alan-agius4 added triage #1 needs: discussion On the agenda for team meeting to determine next steps labels May 27, 2020
@dgp1130
Copy link
Collaborator

dgp1130 commented Jun 24, 2020

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.

@dgp1130 dgp1130 closed this as completed Jun 24, 2020
@pshields
Copy link

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?

@maxime1992
Copy link
Contributor

@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) 🎉

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

@dgp1130 dgp1130 removed the needs: discussion On the agenda for team meeting to determine next steps label Jun 26, 2020
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jul 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: devkit/build-angular feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests