¿Cómo disminuir el tamaño del paquete de productos?

135

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 lodashmódulos Angular 2 HTTP para obtener algunos datos (usando RxJS Observables, mapy subscribe). Muestro estos elementos usando un simple *ngFor.

Pero, a pesar del hecho de que mi aplicación es realmente simple, obtengo un gran paquete de paquetes (en mi opinión) y mapas. Sin embargo, no hablo de las versiones de gzip, sino del tamaño antes de gzipping. Esta pregunta es solo una consulta de recomendaciones generales.

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]

fragmento {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 de nuevo: ¿ un tamaño de paquete de proveedor similar para prod?

ng build --prod --aot

Hash: 517e4425ff872bbe3e5b Tiempo: 22856 ms fragmento {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 kB {3} [inicial] [prestados]

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]

fragmento {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (vendedor) 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] [prestados]

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?
  • ¿Se usa correctamente la sacudida de los árboles angular-cli?
  • ¿Cómo mejorar este tamaño de paquete?
  • ¿Se requieren los archivos .map?
  • ¿Las características 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(usar Webpack en segundo plano) no sea la mejor opción? ¿Podemos hacerlo mejor?

Busqué muchas discusiones sobre Stack Overflow, pero no encontré ninguna pregunta genérica.

BlackHoleGalaxy
fuente
Para obtener más información sobre la optimización de la aplicación angular 2, consulte esto: github.com/mgechev/angular-performance-checklist#introduction
Timathon
1
Pero no creo que debamos preocuparnos tanto, angular-cli evolucionará y las cosas se harán mejor y mejor. Si necesita alguna característica que angular-cli no tiene, solo envíe un problema en su repositorio: github.com/angular/angular-cli
Timathon
Si bien creo que @Timathon tiene razón en algunos aspectos, si alguien está tratando de implementar Angular2 en producción, debería preocuparse por los tamaños de los paquetes, ya que esto afecta directamente el rendimiento de la aplicación. La lista de verificación de rendimiento angular es un gran recurso para ver qué se puede mejorar. El equipo angular está trabajando para reducir el tamaño de los paquetes. ¡Emocionado de ver a dónde va!
Jack Clancy

Respuestas:

72

Actualización febrero 2020

Como esta respuesta recibió mucha tracción, pensé que sería mejor actualizarla con nuevas optimizaciones angulares:

  1. Como dijo otro respondedor, ng build --prod --build-optimizeres una buena opción para las personas que usan menos que Angular v5. Para las versiones más recientes, esto se hace de forma predeterminada conng build --prod
  2. 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
  3. El motor de renderizado Ivy viene por defecto en Angular 9, ofrece mejores tamaños de paquete
  4. Asegúrese de que sus departamentos de terceros sean sacudibles de árbol. Si aún no está utilizando Rxjs v6, debería estarlo.
  5. 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
  6. Comprueba si tus archivos están comprimidos

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 ng build --prod --aot, 10 veces más grande que el supuesto 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). Con Angular 9, AOT está por defecto en el entorno de producción y desarrollo.

2) Uso de la representación del lado del servidor de Angular Universal AKA (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) Los trabajadores del 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 presentes actualmente 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

Jack Clancy
fuente
Mi proyecto mínimo es de 384kB, visita github.com/JCornat/min-angular . Estoy seguro de que hay una manera fácil de optimizarlo, ¡pero está cerca de 250kB!
Jacques Cornat
2
@JacquesCornat se ve bien! Pero su aplicación solo tiene un único componente. La pregunta es cómo administrar tamaños de paquetes o aplicaciones más grandes. A menudo, AOT no reduce el tamaño de los paquetes lo suficiente, y las personas se ven obligadas a buscar otra forma de optimizar. Recomiendo a todos que echen un vistazo al analizador de paquetes webpack. Una manera muy útil / fácil de ver qué está causando la hinchazón
Jack Clancy
Desafortunadamente, las utilidades como sw-precachenegarse a tratar con paquetes de proveedores de más de 2 MB.
1
@JackClancy "La pregunta es cómo administrar tamaños de paquetes o aplicaciones más grandes". No, su pregunta es "¿cómo mejorar este tamaño de paquete?" y él está hablando de su aplicación mínima con 3 componentes. De todos modos, hablando de grandes paquetes, usando la configuración AngularClass / angular-starter, igual que en mi repositorio, el tamaño de mi paquete para grandes aplicaciones pasó de 8 MB (4 MB sin archivos de mapa) a 580 kB.
Jacques Cornat
1
Gracias me salvaste. --prod redujo el tamaño de la aplicación de 6Mb a 1.2Mb. Todavía no es perfecto, pero lo acepta, ya que es solo para uso de escritorio.
Vyacheslav Tsivina
21

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. Los decoradores son utilizados por el compilador, y no son necesarios en tiempo de ejecución y pueden eliminarse. 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 en adelante, ng build --prodse ocupará automáticamente del proceso anterior :)

Shubhendu Vaid
fuente
1
En cuanto a angular 6 en este momento, el proveedor todavía tiene 4 MB para instalar solo angular / material y firebase
FindOutIslamNow
Ese es un problema con angular / material, incluso me he enfrentado a ese error. La sacudida de los árboles no realizada correctamente es probablemente la causa raíz. Con el nuevo motor de render IVY, probablemente se resolvería.
Shubhendu Vaid,
13

Lodash puede contribuir con 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, flattenpuede contribuir hasta 1.2Ksu paquete, después de la minimización. Así que he estado construyendo una colección de funciones lodash simplificadas. Mi implementación de flattencontribuye alrededor 50 bytes. Puede verificarlo aquí para ver si funciona para usted: https://github.com/simontonsoftware/micro-dash

Eric Simonton
fuente
1
2 / Probé los consejos "loadash-es" del comentario anterior. Reduce el tamaño de mi paquete de 0.08mb.
Stefdelec
¡Eso no es mucho! ¿Todavía tienes algo más que importar lodash a la antigua usanza? No recibirá ayuda a menos que todo se importe de la nueva manera.
Eric Simonton el
Creo que lo he reemplazado todo. El tamaño no habría cambiado de otra manera. Di otro consejo a continuación (cosa de gzip) que realmente nos ayudó.
Stefdelec
Interesante. ¿En qué parte de su paquete está / estaba contribuyendo lodash? (Por ejemplo, usando source-map-explorer)
Eric Simonton
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 no incluir .maparchivos, porque se usa sólo 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, yo personalmente uso Webpack (y angular-cli también se basa en él ), porque realmente puedes configure everythingoptimizarlo o depurarlo.
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 hacen el trabajo realmente bien.

El uso de 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 configuración 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 .

Jacques Cornat
fuente
¿Qué configuración específica de inicio angular es la que ayuda a reducir el tamaño del paquete? ¿Es el webpack.config?
MartinJH
2
Sí, es la configuración del paquete web que reduce el tamaño del paquete.
Jacques Cornat
Gracias por la aclaración :)
MartinJH
8

La siguiente solución asume que está sirviendo su dist / carpeta usando nodejs. Utilice el siguiente 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, digamos reducir 300 kb (aprox.) Desde, luego siga el proceso a continuación;

Cree una carpeta llamada vendordentro de la srccarpeta y dentro de la carpeta del 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 tsconfig.jsonarchivo en su aplicación angular-cli. Luego en el 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

Renil Babu
fuente
5

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",

fragmento {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [inicial] [procesado] fragmento {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.

kwalski
fuente
1

Si ha ejecutado ng build --prod, no debería tener vendorarchivos en absoluto.

Si ejecuto solo ng build, obtengo estos archivos:

ingrese la descripción de la imagen aquí

El tamaño total de la carpeta es de ~ 14 MB. Waat! :RE

Pero si ejecuto ng build --prod, obtengo estos archivos:

ingrese la descripción de la imagen aquí

El tamaño total de la carpeta es 584K.

Uno y el mismo código. He habilitado a Ivy en ambos casos. Angular es 8.2.13.

Entonces, ¿supongo que no agregaste --proda tu comando de compilación?

pesho hristov
fuente
1

Si está utilizando Angular 8+ y desea reducir el tamaño del paquete, puede usar Ivy. Ivy viene como el motor de vista predeterminado en Angular 9 Simplemente vaya a src / tsconfig.app.json y agregue el parámetro angularCompilerOptions, por ejemplo:

{
  "extends": ...,
  "compilerOptions":...,
  "exclude": ...,

/* add this one */ 
  "angularCompilerOptions": {
    "enableIvy": true
  }
}
Rachel
fuente
1

Esto redujo el tamaño en mi caso:

ng build --prod --build-optimizer --optimization.

Para Angular 5+ ng-build --prod hace esto por defecto. 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.

Mahesh Sharma
fuente
1

Funciona 100% ng build --prod --aot --build-optimizer --vendor-chunk = true

AJAY AVHAD
fuente
0

Tengo una aplicación de arranque angular 5 + spring (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://stackoverflow.com/a/28216983/9491345

sah1
fuente
0

Verifique que tenga una configuración llamada "producción" para ng build --prod, ya que es la abreviatura de ng build --configuration = production Sin 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 ha ejecutado, lo que da como resultado un paquete de 7mb en lugar de 250kb.

antídoto
fuente
0

Tomado de los documentos angulares v9 ( https://angular.io/guide/workspace-config#alternate-build-configurations ):

De manera predeterminada, se define una configuración de producción y el comando ng build tiene la opción --prod que se compila utilizando esta configuración. La configuración de producción establece valores predeterminados que optimizan la aplicación de varias maneras, como agrupar archivos , minimizar el espacio en blanco en exceso , eliminar comentarios y código muerto , y reescribir el código para usar nombres cortos y crípticos ( "minificación" ).

Además, puede comprimir todos sus implementables con @ angular-builders / custom-webpack: generador de navegador donde su webpack.config.js personalizado se ve así:

module.exports = {
  entry: {
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash].js'
  },
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    })
  ]
};

Luego, deberá configurar su servidor web para que sirva contenido comprimido, por ejemplo, con nginx debe agregarlo a su nginx.conf:

server {
    gzip on;
    gzip_types      text/plain application/xml;
    gzip_proxied    no-cache no-store private expired auth;
    gzip_min_length 1000;
    ...
}

En mi caso, la carpeta dist se redujo de 25 a 5 mb después de usar el --prod en ng build y luego se redujo a 1.5mb después de la compresión.

Bat0u89
fuente