big - Paquete de gran proveedor de CLI Angular2: ¿cómo mejorar el tamaño de la producción?
vendor.bundle.js too big (11)
En primer lugar, los paquetes de proveedores son enormes simplemente porque Angular 2 depende de muchas bibliotecas.
El tamaño mínimo para la
aplicación Angular 2 es de alrededor de 500 KB
(250 KB en algunos casos, vea la publicación inferior).
La sacudida del árbol es utilizada adecuadamente por
angular-cli
.
No incluya archivos
.map
, ya que solo se utilizan para la depuración.
Además, si usa un módulo de reemplazo en caliente, retírelo para aligerar al proveedor.
Para empacar para la producción, personalmente uso
Webpack
(y
angular-cli también depende de él
), porque realmente puedes
configure everything
para la optimización o depuración.
Si desea usar
Webpack
, estoy de acuerdo en que es un poco complicado una primera vista, pero vea los tutoriales en la red, no se sentirá decepcionado.
De lo contrario, use
angular-cli
, que hace el trabajo realmente bien.
Usar la compilación anticipada es obligatorio para optimizar las aplicaciones y reducir la aplicación Angular 2 a 250 KB .
Aquí hay un repositorio que creé ( github.com/JCornat/min-angular ) para probar el tamaño mínimo del paquete angular, y obtengo 384kB . Estoy seguro de que hay una manera fácil de optimizarlo.
Hablando de grandes aplicaciones, usando la AngularClass/angular-starter , igual que en el repositorio anterior, el tamaño de mi paquete para grandes aplicaciones ( más de 150 componentes ) pasó de 8 MB (4 MB sin archivos de mapa) a 580 kB .
Tengo una aplicación simple, inicializada por
angular-cli
.
Muestra algunas páginas relativas a 3 rutas. Tengo 3 componentes En una de esta página, uso los módulos lodash y Angular2 Http para obtener algunos datos (usando Rxjs Observables, mapear y suscribir). Muestro estos elementos usando un simple ngFor.
Pero, a pesar del hecho de que mi aplicación es realmente simple, obtengo un paquete y mapas ENORMES (en mi opinión). Sin embargo, no hablo de las versiones de gzip, sino del tamaño antes de gzipping. Esta pregunta es solo una recomendación general.
Resultados de algunas pruebas:
ng build
Hash: 8efac7d6208adb8641c1 Tiempo: 10129ms trozo {0} main.bundle.js, main.bundle.map (main) 18.7 kB {3} [inicial] [prestados]
trozo {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [inicial] [prestados]
fragmento {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [inicial] [prestados]
trozo {3} vendor.bundle.js, vendor.bundle.map (vendedor) 3.96 MB [inicial] [prestados]
trozo {4} inline.bundle.js, inline.bundle.map (en línea) 0 bytes [entrada] [prestados]
Espere: ¿ Paquete de paquete de proveedor de 10Mb para una aplicación tan simple?
ng build --prod
Hash: 09a5f095e33b2980e7cc Tiempo: 23455ms fragmento {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (main) 18.3 kB {3} [inicial] [prescrito]
trozo {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (estilos) 154 kB {]} [presentado] [inicial]
trozo {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.bundle.map (scripts) 128 kB {4} [inicial] [procesado]
trozo {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (vendedor) 3.96 MB [inicial] [procesado]
trozo {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (en línea) 0 bytes [entrada] [prestados]
Espere nuevamente: ¿ un tamaño de paquete de proveedor similar para prod?
ng build --prod --aot
Hash: 517e4425ff872bbe3e5b Tiempo: 22856ms trozo {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 kB {3} [inicial] [procesado]
trozo {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (estilos) 154 kB {4} [inicial] [prestados]
trozo {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a7564.bundle.map (scripts) 128 kB {4} [inicial] [procesado]
trozo {3} proveedor.41a6c1f57136df286f14.bundle.js, proveedor.41a6c1f57136df286f14.bundle.map (proveedor) 2.75 MB [inicial] [procesado]
trozo {4} en línea.97c0403c57a46c6a7920.bundle.js, en línea.97c0403c57a46c6a7920.bundle.map (en línea) 0 bytes [entrada] [prestados]
ng build --aot
Hash: 040cc91df4df5ffc3c3f Tiempo: 11011ms trozo {0} main.bundle.js, main.bundle.map (main) 130 kB {3} [inicial] [procesado]
trozo {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [inicial] [prestados]
fragmento {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 kB {4} [inicial] [prestados]
trozo {3} vendor.bundle.js, vendor.bundle.map (vendedor) 2.75 MB [inicial] [procesado]
trozo {4} inline.bundle.js, inline.bundle.map (en línea) 0 bytes [entrada] [prestados]
Entonces, algunas preguntas para implementar mi aplicación en prod:
- ¿Por qué los paquetes de proveedores son tan grandes?
- ¿Es la sacudida del árbol utilizada correctamente por angular-cli?
- ¿Cómo mejorar este tamaño de paquete?
- ¿Se requieren los archivos .map?
- ¿Las funciones de prueba están incluidas en paquetes? No los necesito en productos.
- Pregunta genérica: ¿cuáles son las herramientas recomendadas para empacar para productos? ¿Quizás angular-cli (usando webpack en segundo plano) no es el más adecuado? ¿Puedo hacer más?
Busqué muchas discusiones sobre Stack Overflow pero no encuentro ninguna pregunta genérica.
Esto redujo el tamaño en mi caso:
ng build --prod --build-optimizer --optimization
El tamaño después de ejecutar este comando se redujo de 1.7MB a 1.2MB, pero no lo suficiente para mi propósito de producción.
Trabajo en la plataforma de mensajería de Facebook y las aplicaciones de mensajería deben tener menos de 1 MB para ejecutarse en la plataforma de mensajería. He estado tratando de encontrar una solución para una sacudida efectiva de los árboles, pero todavía no tuve suerte.
La siguiente solución asume que está sirviendo su dist / carpeta usando nodejs. Utilice los siguientes app.js en el nivel raíz
const express = require(''express''),http = require(''http''),path = require(''path''),compression = require(''compression'');
const app = express();
app.use(express.static(path.join(__dirname, ''dist'')));
app.use(compression()) //compressing dist folder
app.get(''*'', (req, res) => {
res.sendFile(path.join(__dirname, ''dist/index.html''));
})
const port = process.env.PORT || ''4201'';
app.set(''port'', port);
const server = http.createServer(app);
server.listen(port, () => console.log(''Running at port '' + port))
Asegúrese de instalar dependencias;
npm install compression --save
npm install express --save;
Ahora construye la aplicación
ng build --prod --build-optimizer
Si desea comprimir aún más la compilación, por ejemplo, reduzca 300 kb (aprox.) Desde, luego siga el proceso a continuación;
Cree una carpeta llamada
vendor
dentro de la carpeta
src
y dentro de la carpeta proveedor cree un archivo
rxjs.ts
y pegue el siguiente código en él;
export {Subject} from ''rxjs/Subject'';
export {Observable} from ''rxjs/Observable'';
export {Subscription} from ''rxjs/Subscription'';
Y luego agregue lo siguiente en el archivo
tsconfig.json
en su aplicación angular-cli.
Luego, en
compilerOptions
, agregue el siguiente json;
"paths": {
"rxjs": [
"./vendor/rxjs.ts"
]
}
Esto hará que su tamaño de construcción sea demasiado pequeño. En mi proyecto reduje el tamaño de 11mb a 1mb. Espero eso ayude
Lodash puede aportar una porción de código de error a su paquete dependiendo de cómo importe desde él. Por ejemplo:
// includes the entire package (very large)
import * as _ from ''lodash'';
// depending on your buildchain, may still include the entire package
import { flatten } from ''lodash'';
// imports only the code needed for `flatten`
import flatten from ''lodash-es/flatten''
Personalmente, todavía quería huellas más pequeñas de mis funciones de utilidad.
Por ejemplo,
flatten
puede contribuir hasta
1.2K
a su paquete, después de la minimización.
Así que he estado creando una colección de funciones lodash simplificadas.
Mi implementación de
flatten
aporta alrededor de
50 bytes
.
Puede verificarlo aquí para ver si funciona para usted:
https://github.com/simontonsoftware/micro-dash
Otra forma de reducir el paquete es servir GZIP en lugar de JS. Pasamos de 2.6mb a 543ko.
Si está usando Angular 8+ y desea reducir el tamaño del paquete, puede usar Ivy. Simplemente vaya a src / tsconfig.app.json y agregue el parámetro angularCompilerOptions, por ejemplo:
{
"extends": ...,
"compilerOptions":...,
"exclude": ...,
/* add this one */
"angularCompilerOptions": {
"enableIvy": true
}
}
Tengo una aplicación de arranque de resorte angular 5 + (application.properties 1.3+) con ayuda de compresión (enlace adjunto a continuación) pude reducir el tamaño del tamaño main.bundle.ts de 2.7 MB a 530 KB.
También de forma predeterminada, --aot y --build-optimizer están habilitados con el modo --prod, no necesita especificarlos por separado.
https://.com/a/28216983/9491345
Una cosa que deseo compartir es cómo las bibliotecas importadas aumentan el tamaño del dist. Importé el paquete angular2-moment, mientras que pude hacer todo el formato de fecha y hora que necesitaba usando el DatePipe estándar exportado desde @ angular / common.
Con Angular2-Moment
"angular2-moment": "^1.6.0",
trozo {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [inicial] [procesado] trozo {1} main.e7496551a26816427b68.bundle.js (principal) 2.2 MB {3} [inicial] [procesado] trozo {2} estilos.056656ed596d26ba0192.bundle.css (estilos) 69 bytes {4} [inicial] [procesado] trozo {3} vendedor.62c2cfe0ca794a5006d1.bundle.js (vendedor) 3.84 MB [inicial] [procesado] trozo {4 } inline.0b9c3de53405d705e757.bundle.js (en línea) 0 bytes [entrada] [prestados]
Después de eliminar Angular2-moment y usar DatePipe en su lugar
fragmento {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [inicial] [procesado] fragmento {1} main.f2b62721788695a4655c.bundle.js (main) 2.2 MB {3} [inicial] [renderizado] fragmento {2} estilos.056656ed596d26ba0192.bundle.css (estilos) 69 bytes {4} [inicial] [procesado] fragmento {3} proveedor.e1de06303258c58c9d01.bundle.js (proveedor) 3.35 MB [inicial] [procesado] fragmento {4 } inline.3ae24861b3637391ba70.bundle.js (en línea) 0 bytes [entrada] [prestados]
¡Tenga en cuenta que el paquete de proveedores ha reducido medio megabyte!
El punto es que vale la pena verificar qué pueden hacer los paquetes estándar angulares incluso si ya está familiarizado con una lib externa.
Use la última versión angular de cli y use el comando ng build --prod --build-optimizer Definitivamente reducirá el tamaño de compilación para prod env.
Esto es lo que hace el optimizador de compilación bajo el capó:
El optimizador de compilación tiene dos trabajos principales. Primero, podemos marcar partes de su aplicación como puras, esto mejora el movimiento del árbol proporcionado por las herramientas existentes, eliminando partes adicionales de su aplicación que no son necesarias.
La segunda cosa que hace el optimizador de compilación es eliminar los decoradores angulares del código de tiempo de ejecución de su aplicación. El compilador utiliza decoradores, que no son necesarios en tiempo de ejecución y se pueden quitar. Cada uno de estos trabajos disminuye el tamaño de sus paquetes de JavaScript y aumenta la velocidad de arranque de su aplicación para sus usuarios.
Nota : Una actualización para Angular 5, ng build --prod se encarga automáticamente del proceso anterior :)
Actualización octubre 2018
Dado que esta respuesta recibió mucha tracción, pensé que sería mejor actualizarla con nuevas optimizaciones angulares:
-
Como dijo otro respondedor,
ng build --prod --build-optimizer
es una buena opción para las personas que usan menos que Angular v5. Para las versiones más recientes, esto se hace de manera predeterminada conng build --prod
- Otra opción es usar el módulo de fragmentación / carga diferida para dividir mejor su aplicación en fragmentos más pequeños
- El motor de renderizado Ivy, aunque todavía no está en producción, pronto ofrecerá mejores tamaños de paquete
- Asegúrese de que sus departamentos de terceros sean sacudibles de árbol. Si aún no está utilizando Rxjs v6, debería estarlo.
- Si todo lo demás falla, use una herramienta como webpack-bundle-analyzer para ver qué está causando la hinchazón en sus módulos
Algunas afirmaciones de que el uso de la compilación AOT puede reducir el tamaño del paquete del proveedor a 250kb.
Sin embargo, en el ejemplo de BlackHoleGalaxy, él usa la compilación AOT y todavía tiene un tamaño de paquete de proveedor de 2.75MB con
ng build --prod --aot
, 10 veces más grande que los supuestos 250kb.
Esto no está fuera de la norma para aplicaciones angular2, incluso si está utilizando v4.0.
2,75 MB sigue siendo demasiado grande para cualquiera que realmente se preocupe por el rendimiento, especialmente en un dispositivo móvil.
Hay algunas cosas que puede hacer para ayudar al rendimiento de su aplicación:
1) AOT & Tree Shaking (angular-cli hace esto fuera de la caja)
2) Uso de representación angular del servidor universal AKA angular (no en cli)
3) Trabajadores web (nuevamente, no en cli, pero es una característica muy solicitada)
ver:
https://github.com/angular/angular-cli/issues/2305
4) Trabajadores de servicio
ver:
https://github.com/angular/angular-cli/issues/4006
Es posible que no necesite todo esto en una sola aplicación, pero estas son algunas de las opciones que están actualmente presentes para optimizar el rendimiento angular. Creo / espero que Google sea consciente de las deficiencias de fábrica en términos de rendimiento y planea mejorar esto en el futuro.
Aquí hay una referencia que habla más en profundidad sobre algunos de los conceptos que mencioné anteriormente:
https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294
Verifique que tenga una configuración llamada "producción" para ng build --prod, ya que es la abreviatura de ng build --configuration = production. Ninguna respuesta resolvió mi problema, porque el problema estaba justo en frente de la pantalla. Creo que esto podría ser bastante común ... He internacionalizado la aplicación con i18n cambiando el nombre de todas las configuraciones a, por ejemplo, production-en. Luego construí con ng build --prod suponiendo que se usa la optimización predeterminada y debería ser casi óptima, pero de hecho solo ng build se ejecutó, lo que resultó en un paquete de 7mb en lugar de 250kb.