En lisant la documentation Angular, vous pouvez trouver plusieurs références à bootstrap votre ensemble Angular app dans un site Web) Worker , afin que votre interface utilisateur ne soit pas bloquée par une utilisation intensive de JS.
Cependant, en ce moment, il n'y a aucune information officielle sur la façon de le faire, et la seule information dans le Angular Doc. Est qu'il s'agit d'une fonctionnalité expérimentale.
Comment puis-je utiliser cette approche pour tirer parti des travailleurs Web dans Angular?
Pour Angular 7, voir la réponse ci-dessous.
J'ai passé beaucoup de temps à comprendre comment le faire, alors j'espère cela peut aider quelqu'un .
Je suppose que vous avez un projet Angular (version 2 ou 4) généré avec Angular CLI 1.0 ou supérieur).
Il n'est pas obligatoire de générer le projet avec CLI pour suivre ces étapes, mais les instructions que je donnerai concernant le fichier webpack, sont basées sur la configuration du webpack CLI.
Depuis Angular CLI v1.0, il y a la fonction "éjecter", qui vous permet d'extraire le fichier de configuration du webpack et de le manipuler comme vous le souhaitez.
Courir ng eject
so Angular CLI génère le fichier webpack.config.js .
Courir npm install
pour que les nouvelles dépendances générées par CLI soient satisfaites
Courir npm install --save @angular/platform-webworker @angular/platform-webworker-dynamic
Remplacez BrowserModule
par WorkerAppModule
dans le fichier app.module.ts. Vous devrez également mettre à jour la déclaration d'importation afin d'utiliser @angular/platform-webworker
bibliothèque.
//src/app/app.module.ts
import { WorkerAppModule } from '@angular/platform-webworker';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
//...other imports...
@NgModule({
declarations: [
AppComponent
],
imports: [
WorkerAppModule,
//...other modules...
],
providers: [/*...providers...*/],
bootstrap: [AppComponent]
})
export class AppModule { }
Remplacez bootstrap par: bootstrapWorkerUI
(mettez également à jour l'importation).
Vous devrez transmettre une URL avec le fichier dans lequel le travailleur Web est défini. Utilisez un fichier appelé webworker.bundle.js
, ne vous inquiétez pas, nous allons bientôt créer ce fichier.
//main.ts
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();
}
bootstrapWorkerUi('webworker.bundle.js');
polyfills.ts
, @angular/core
, et @angular/common
paquets. Dans les étapes suivantes, vous mettrez à jour Webpack afin de transpiler et de créer un bundle avec le résultat.platformWorkerAppDynamic
AppModule
(supprimez l'importation de main.ts ) et bootstrap it using this platformWorkerAppDynamic
plateforme.// 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);
Le fichier de configuration généré automatiquement par webpack est assez long, mais vous n'aurez qu'à concentrer votre attention sur les éléments suivants:
Ajoutez un webworker
point d'entrée pour notre workerLoader.ts
fichier. Si vous regardez la sortie, vous verrez qu'elle attache un préfixe bundle.js à tous les morceaux. C’est pourquoi lors de l’étape bootstrap nous avons utilisé webworker.bundle.js
Accédez à HtmlWebpackPlugin et excluez le point d'entrée webworker
, afin que le fichier Web Worker généré ne soit pas inclus dans le fichier index.html.
Accédez à CommonChunksPlugin , et pour le bloc commun inline
, définissez explicitement les blocs d'entrée pour empêcher que webworker
soit inclus .
Allez dans AotPlugin et définissez explicitement le entryModule
// webpack.config.js
//...some stuff...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CommonsChunkPlugin } = require('webpack').optimize;
const { AotPlugin } = require('@ngtools/webpack');
//...some stuff...
module.exports = {
//...some stuff...
"entry": {
"main": [
"./src/main.ts"
],
"polyfills": [
"./src/polyfills.ts"
],
"styles": [
"./src/styles.css"
],
"webworker": [
"./src/workerLoader.ts"
]
},
"output": {
"path": path.join(process.cwd(), "dist"),
"filename": "[name].bundle.js",
"chunkFilename": "[id].chunk.js"
},
"module": { /*...a lot of stuff...*/ },
"plugins": [
//...some stuff...
new HtmlWebpackPlugin({
//...some stuff...
"excludeChunks": [
"webworker"
],
//...some more stuff...
}),
new BaseHrefWebpackPlugin({}),
new CommonsChunkPlugin({
"name": "inline",
"minChunks": null,
"chunks": [
"main",
"polyfills",
"styles"
]
}),
//...some stuff...
new AotPlugin({
"mainPath": "main.ts",
"entryModule": "app/app.module#AppModule",
//...some stuff...
})
],
//...some more stuff...
};
Si vous avez correctement suivi les étapes précédentes, il ne vous reste plus qu'à compiler le code et essayer les résultats.
Courir npm start
Toute la logique de votre application Angular doit s'exécuter à l'intérieur d'un WebWorker, ce qui rend l'interface plus fluide.
npm start
exécute le serveur webpack-dev , et il a une sorte de problème avec les travailleurs Web qui lancent un message d'erreur dans le journal de la console. Quoi qu'il en soit, le webworker semble bien fonctionner. Si vous compilez l'application à l'aide de la commande webpack
et la servez de n'importe quel serveur http comme simplehttpserver , l'erreur disparaît;)
Vous pouvez obtenir le code complet (config webpack, app.module.ts, ...) à partir de ce dépôt .
Vous pouvez également regarder ici une démo en direct , pour vérifier les différences entre l'utilisation de Web Workers ou non
Bonne nouvelle les gars, j'ai réussi à travailler avec Angular 7! ????????????
Exigence: npm install --save-dev @angular-builders/custom-webpack html-webpack-plugin
Assurez-vous d'avoir production:true
dans votre fichier env si vous voulez juste copier/coller le code ci-dessous.
Étape 1: Modifiez votre fichier angular.json de la manière suivante:
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.client.config.js",
"replaceDuplicatePlugins": true
},
...
}
Vous modifiez uniquement la partie build
parce que vous n'avez pas vraiment besoin de tout le travail dans le serveur de développement.
Étape 2: Créez webpack.client.config.js
fichier à la racine de votre projet. Si vous n'utilisez pas SSR, vous pouvez supprimer 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"
}
}
}
Étape: Modifiez votre AppModule:
import { BrowserModule } from '@angular/platform-browser'
import { WorkerAppModule } from '@angular/platform-webworker'
const AppBootstrap =
environment.production
? WorkerAppModule
: BrowserModule.withServerTransition({ appId: 'myApp' })
imports: [
...
AppBootstrap,
...
]
Étape 4: Modifiez votre fichier 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);
});
}
Étape 5: Il se compilera très bien, mais vous pouvez avoir un problème d'exécution en raison de la manipulation DOM dans votre application. À ce stade, il vous suffit de supprimer toute manipulation DOM et de la remplacer par autre chose. Je suis toujours en train de trouver cette partie et je modifierai ma réponse plus tard pour donner des instructions sur ce problème.
Si vous ne faites pas de manipulation DOM sauvage, alors vous êtes prêt à utiliser un thread principal gratuit et l'audit de votre application à l'aide de lighthouse ne devrait pas afficher Minimize main-thread work
plus, car la plupart de votre application, à l'exception de l'interface utilisateur, se charge dans un deuxième thread.