proyecto - iniciar angular
Aplicación CLI angular generada con Web Workers (2)
Al leer la documentación angular, puede encontrar varias referencias para iniciar su aplicación Angular completa dentro de un Web Worker , para que su UI no se bloquee por el uso intensivo de JS.
Sin embargo, en este momento no hay información oficial sobre cómo hacer eso, y la única información en Angular Doc. es que esta es una característica experimental.
¿Cómo puedo usar este enfoque para aprovechar a los trabajadores web en Angular?
Buenas noticias chicos, ¡tengo esto para trabajar con Angular 7! 🎉🎉🎉
Requisito
:
npm install --save-dev @angular-builders/custom-webpack html-webpack-plugin
Asegúrese de tener
production:true
en su archivo env si solo desea copiar / pegar el código desde abajo.
Paso 1 : Edite su archivo angular.json de la siguiente manera:
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.client.config.js",
"replaceDuplicatePlugins": true
},
...
}
Solo está editando la parte de
build
porque realmente no necesita todo el elemento trabajador en el servidor de desarrollo.
Paso 2
: Cree el archivo
webpack.client.config.js
en la raíz de su proyecto.
Si no está utilizando SSR, puede eliminar la
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"
}
}
}
Paso 3 : Edita tu AppModule:
import { BrowserModule } from ''@angular/platform-browser''
import { WorkerAppModule } from ''@angular/platform-webworker''
const AppBootstrap =
environment.production
? WorkerAppModule
: BrowserModule.withServerTransition({ appId: ''myApp'' })
imports: [
...
AppBootstrap,
...
]
Paso 4 : edita tu archivo 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);
});
}
Paso 5 : se compilará bien, pero es posible que tenga un problema de tiempo de ejecución debido a la manipulación del DOM en su aplicación. En este punto, solo tiene que eliminar cualquier manipulación DOM y reemplazarla por otra cosa. Todavía estoy trabajando para resolver esta parte y editaré mi respuesta más tarde para dar instrucciones sobre este problema.
Si no está haciendo una manipulación DOM salvaje, entonces es bueno ir con un hilo principal gratuito y auditar su aplicación usando lighthouse ya no debería mostrar
Minimize main-thread work
, ya que la mayoría de su aplicación, excepto la IU, se carga en un segundo hilo.
Para Angular 7, vea la respuesta a continuación.
Pasé mucho tiempo para descubrir cómo hacerlo, así que espero que esto pueda ayudar a alguien .
Condiciones previas
Supongo que tiene un proyecto Angular (versión 2 o 4) generado con Angular CLI 1.0 o superior.
No es obligatorio generar el proyecto con CLI para seguir estos pasos, pero las instrucciones que daré relacionadas con el archivo del paquete web se basan en la configuración del paquete web CLI.
Pasos
1. Extraer el archivo webpack
Desde Angular CLI v1.0, existe la función de "expulsión", que le permite extraer el archivo de configuración del paquete web y manipularlo como desee.
-
Ejecute
ng eject
para que Angular CLI genere el archivo webpack.config.js . -
Ejecute
npm install
para que se satisfagan las nuevas dependencias generadas por CLI
2. Instalar dependencias de arranque de webworker
Ejecute
npm install --save @angular/platform-webworker @angular/platform-webworker-dynamic
3. Cambios en el arranque de subprocesos de la interfaz de usuario
3.1 Cambios en app.module.ts
Reemplace
BrowserModule
por
WorkerAppModule
en el archivo app.module.ts.
También deberá actualizar la declaración de importación para usar la biblioteca
@angular/platform-webworker
.
//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 { }
3.2 Cambios en src / main.ts
Reemplace el proceso bootstrap con:
bootstrapWorkerUI
(actualice también la importación).
Deberá pasar una URL con el archivo donde está definido el trabajador web.
Use un archivo llamado
webworker.bundle.js
, no se preocupe, crearemos este archivo pronto.
//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'');
3.3 Crear archivo workerLoader.ts
- Cree un nuevo archivo src / workerLoader.ts .
-
Como su Web Worker será un solo archivo que contiene todo lo necesario, debe incluir
@angular/common
paquetespolyfills.ts
,@angular/core
y@angular/common
. En los próximos pasos, actualizará Webpack para transpilar y crear un paquete con el resultado. -
Importar
platformWorkerAppDynamic
-
Importe el
AppModule
(elimine la importación de main.ts ) y arranque utilizando estaplatformWorkerAppDynamic
platformWorkerAppDynamic.
// 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);
4. Actualice webpack para construir su webworker
El archivo de configuración generado automáticamente por webpack es bastante largo, pero solo deberá centrar su atención en lo siguiente:
-
Agregue un punto de entrada de
webworker
para nuestro archivoworkerLoader.ts
. Si observa la salida, verá que adjunta un prefijo bundle.js a todos los fragmentos. Es por eso que durante el paso de arranque hemos utilizadowebworker.bundle.js
-
Vaya a HtmlWebpackPlugin y excluya el punto de entrada de
webworker
, por lo que el archivo Web Worker generado no se incluye en el archivo index.html. -
Vaya a CommonChunksPlugin y, para el fragmento común en
inline
, configure los fragmentos de entrada explícitamente para evitar que sewebworker
alwebworker
. -
Vaya a AotPlugin y configure explícitamente el
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...
};
Estas listo
Si ha seguido correctamente los pasos anteriores, ahora solo necesita compilar el código y probar los resultados.
Ejecute
npm start
Toda la lógica de su aplicación Angular debería estar ejecutándose dentro de un WebWorker, haciendo que la IU sea más fluida.
Notas adicionales
npm start
ejecuta el
servidor webpack-dev
, y tiene algún tipo de problema con los trabajadores web que arrojan un mensaje de error en el registro de la consola.
De todos modos, el trabajador web parece funcionar bien.
Si compila la aplicación usando el comando
webpack
y la sirve desde cualquier servidor http como
simplehttpserver
, el error desaparece;)
Código de muestra y demostración
Puede obtener el código completo (webpack config, app.module.ts, ...) de este repositorio .
También puede ver aquí una demostración en vivo , para ver las diferencias entre usar Web Workers o no