web-dev-qa-db-fra.com

Angular2 CLI bundle bundle énorme: comment améliorer la taille de prod?

J'ai une application simple, initialisée par angular-cli.

Il affiche des pages relatives à 3 itinéraires. J'ai 3 composants. Sur l’une de ces pages, j’utilise les modules lodash et Angular2 Http pour obtenir des données (avec Rxjs Observables, map et subscribe). Je montre ces éléments en utilisant un simple ngFor.

Mais, malgré le fait que mon application est vraiment simple, je reçois un paquet énorme et des cartes (à mon avis). Je ne parle pas des versions de gzip mais taille avant gzipping. Cette question est juste une des recommandations générales demander.

Quelques résultats de tests:

ng construire

Hachage: 8efac7d6208adb8641c1 Durée: 10129ms morceau {0} main.bundle.js, main.bundle.map (main) 18,7 Ko {3} [initial] [rendu]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [initial] [rendu]

chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 ko {4} [initiale] [rendue]

chunk {3} vendor.bundle.js, vendor.bundle.map (vendor) 3,96 Mo [initial] [rendu]

chunk {4} inline.bundle.js, inline.bundle.map (inline) 0 octet [entrée] [rendu]

Attendez: Paquet de fournisseur de 10 Mo pour une application aussi simple?

ng build --prod

Hachage: 09a5f095e33b2980e7cc Temps: bloc 23455ms {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (principal) 18,3 kB {3} [initial] [rendu]

chunk {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (styles) 154 kB {4} [initial] [rendu]

chunk {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.bundle.map (scripts) 128 ko {4} [initial] [rendu]

chunk {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (fournisseur) 3,96 Mo [initiale] [rendu]

chunk {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (inline) 0 octet [entrée] [rendu]

Attendez encore: une telle taille de lot fournisseur similaire pour prod?

ng build --prod --aot

Hash: 517e4425ff872bbe3e5b Time: bloc 22856ms {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 kB {3} [initial] [rendu]

chunk {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 kB {4} [initial] [rendu]

chunk {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a7564.bundle.map (scripts) 128 ko {4} [initial] [rendu]

chunk {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (vendor) 2,75 Mo [initiale] [rendu]

chunk {4} inline.97c0403c57a46c6a7920.bundle.js, inline.97c0403c57a46c6a7920.bundle.map (inline) 0 octet [entrée] [rendu]

ng build --aot

Hachage: 040cc91df4df5ffc3c3f Heure: bloc 11011ms {0} main.bundle.js, main.bundle.map (main) 130 Ko {3} [initial] [rendu]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 kB {4} [initial] [rendu]

chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 ko {4} [initiale] [rendue]

chunk {3} vendor.bundle.js, vendor.bundle.map (fournisseur) 2,75 Mo [initial] [rendu]

chunk {4} inline.bundle.js, inline.bundle.map (inline) 0 octet [entrée] [rendu]

Donc, quelques questions pour le déploiement de mon application sur prod:

  • Pourquoi les offres des fournisseurs sont-elles si énormes?
  • La secousse des arbres est-elle bien utilisée par angular-cli? 
  • comment améliorer cette taille de paquet?
  • Les fichiers .map sont-ils nécessaires?
  • Les fonctionnalités de test sont-elles incluses dans les bundles? Je n'ai pas besoin d'eux en prod.
  • Question générique: quels sont les outils recommandés pour emballer pour prod? Peut-être que angular-cli (avec Webpack en arrière-plan) n’est pas le mieux adapté? Peut-on faire plus?

J'ai cherché beaucoup de discussions sur Stack Overflow mais je n'ai trouvé aucune question générique.

95
BlackHoleGalaxy

Mise à jour d'octobre 2018

Cette réponse ayant suscité beaucoup d'intérêt, j'ai pensé qu'il serait préférable de la mettre à jour avec de nouvelles optimisations angulaires: 

  1. Comme l'a dit un autre intervenant, ng build --prod --build-optimizer est une bonne option pour les personnes utilisant une version inférieure à Angular v5. Pour les versions plus récentes, ceci est fait par défaut avec ng build --prod
  2. Une autre option consiste à utiliser le découpage de module/le chargement différé pour scinder mieux votre application en fragments plus petits. 
  3. Le moteur de rendu Ivy, bien que pas encore en production, offrira bientôt de meilleures tailles de paquet
  4. Assurez-vous que vos ressources tierces peuvent être transformées en arbre. Si vous n'utilisez pas encore Rxjs v6, vous devriez le faire. 
  5. Si tout échoue, utilisez un outil tel que webpack-bundle-analyszer pour voir la cause du gonflement de vos modules.

Certaines déclarations prétendent que l'utilisation de la compilation AOT peut réduire la taille de l'ensemble des fournisseurs à 250 Ko. Cependant, dans l’exemple de BlackHoleGalaxy, il utilise la compilation AOT et conserve une taille de lot de 2,75 Mo avec ng build --prod --aot, 10 fois plus grande que le supposé 250 ko. Ce n'est pas hors de la norme pour les applications angular2, même si vous utilisez v4.0. 2,75 Mo est encore trop volumineux pour quiconque se soucie vraiment de la performance, en particulier sur un appareil mobile. 

Vous pouvez effectuer certaines opérations pour améliorer les performances de votre application: 

1) AOT & Tree Shaking (angular-cli fait ceci en sortie de boîte) 

2) Utilisation de Angular Universal A.K.A. rendu côté serveur (pas en cli) 

3) Web Workers (encore une fois, pas en cli, mais une fonctionnalité très demandée)
voir: https://github.com/angular/angular-cli/issues/2305

4) Travailleurs de service
voir: https://github.com/angular/angular-cli/issues/4006

Vous n’avez peut-être pas besoin de tous ces éléments dans une seule application, mais ce sont quelques-unes des options actuellement disponibles pour optimiser les performances angulaires. Je pense/espère que Google est conscient des insuffisances originales en termes de performances et envisage de les améliorer à l'avenir. 

Voici une référence qui décrit plus en détail certains des concepts que j'ai mentionnés ci-dessus: 

https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-your-angular2-app-922ce5c1b294

36
Jack Clancy

Utilisez la dernière version de cli angulaire et utilisez la commande ng build --prod --build-optimizer Elle va certainement réduire la taille de la construction pour env env.

Voici ce que l'optimiseur de construction fait sous le capot:

L'optimiseur de construction a deux tâches principales. Premièrement, nous sommes en mesure de marquer des parties de votre application comme étant pures, cela améliore l’arborescence fournie par les outils existants, en supprimant des parties supplémentaires de votre application qui ne sont plus nécessaires.

La deuxième chose que l'optimiseur de génération fait consiste à supprimer les décorateurs angulaires du code d'exécution de votre application. Les décorateurs sont utilisés par le compilateur et ne sont pas nécessaires au moment de l’exécution et peuvent être supprimés. Chacune de ces tâches réduit la taille de vos ensembles JavaScript et augmente la vitesse de démarrage de votre application pour vos utilisateurs.

Note: Une mise à jour pour Angular 5, le ng build --prod se charge automatiquement du processus ci-dessus :)

18
Shubhendu Vaid

Lodash peut apporter une grande quantité de code à votre paquet en fonction de la manière dont vous l'importez. Par exemple:

// 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'

Personnellement, je voulais toujours de plus petites empreintes de pas de mes fonctions utilitaires. Par exemple. flatten peut contribuer jusqu'à 1.2K à votre paquet, après réduction. J'ai donc constitué une collection de fonctions lodash simplifiées. Mon implémentation de flatten contribue autour de 50 bytes. Vous pouvez vérifier ici pour voir si cela fonctionne pour vous: https://github.com/simontonsoftware/micro-dash

8
Eric Simonton

La solution suivante suppose que vous servez votre dossier dist/à l’aide de nodejs. Veuillez utiliser le fichier app.js suivant au niveau racine

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

Assurez-vous d'installer des dépendances.

npm install compression --save
npm install express --save;

Maintenant, construis l'application

ng build --prod --build-optimizer

Si vous voulez compresser davantage la construction, réduisez de 300 kb (environ) de, puis suivez le processus ci-dessous;

Créez un dossier appelévendordans le dossiersrcet dans le dossier du fournisseur. Créez un fichierrxjs.tset collez-y le code ci-dessous.

export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';

Et ajoutez ensuite ce qui suit dans le fichiertsconfig.jsonde votre application angular-cli. Puis dans la compilerOptions, ajoutez le json suivant;

"paths": {
      "rxjs": [
        "./vendor/rxjs.ts"
      ]
    }

Cela rendra votre taille de construction trop petite. Dans mon projet, j'ai réduit la taille de 11 Mo à 1 Mo . J'espère que cela aide

6
Renil Babu

Une chose que je souhaite partager est la façon dont les bibliothèques importées augmentent la taille de la distribution. J'avais un paquet angular2-moment importé, alors que je pouvais faire tout le formatage date-heure dont j'avais besoin en utilisant le DatePipe standard exporté à partir de @ angular/common.

Avec Angular2-Moment "angular2-moment": "^1.6.0",

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 Ko {4} [initial] [rendu] chunk {1} main.e7496551a26816427b68.bundle.js (principal) 2,2 Mo {3} [initial] [render] chunk {2} styles.056656ed596d26ba0192.bundle.css (styles) 69 octets {4} chunk {3} vendor.62c2cfe0ca794a5006d1.bundle.js (fournisseur) 3,84 Mo [initiale] [render] chunk {4} inline.0b9c3de53405d705e757.bundle.js (inline) 0 octet [entrée] [rendu]

Après avoir retiré Angular2-moment et utilisé DatePipe à la place

chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 Ko {4} [initial] [rendu] chunk {1} main.f2b62721788695a4655c.bundle.js (principal) 2,2 Mo {3} [initial] [render] chunk {2} styles.056656ed596d26ba0192.bundle.css (styles) 69 octets {4} chunk {3} vendor.e1de06303258c58c9d01.bundle.js (fournisseur) 3,35 Mo [initiale] [render] chunk {4} inline.3ae24861b3637391ba70.bundle.js (inline) 0 octet [entrée] [rendu]

Notez que le paquet du fournisseur a réduit un demi-mégaoctet!

Le fait est que cela vaut la peine de vérifier ce que les paquets standard angulaires peuvent faire même si vous êtes déjà familiarisé avec une bibliothèque externe.

4
kwalski

Une autre façon de réduire les offres groupées consiste à servir GZIP au lieu de JS. Nous sommes passés de 2.6mb à 543ko. 

https://httpd.Apache.org/docs/2.4/mod/mod_deflate.html

2
Stefdelec

Cela a réduit la taille dans mon cas:

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

Taille après exécution de cette commande réduite de 1,7 Mo à 1,2 Mo, mais pas assez pour mon objectif de production.

Je travaille sur la plate-forme de messagerie Facebook et les applications de messagerie ont besoin de moins de 1 Mo pour fonctionner sur la plate-forme de messagerie. Vous avez essayé de trouver une solution pour secouer efficacement les arbres mais toujours pas de chance.

1
Mahesh Sharma

Si vous utilisez Angular 8+ et que vous souhaitez réduire la taille du paquet, vous pouvez utiliser Ivy. Allez simplement sur src/tsconfig.app.json et ajoutez le paramètre angularCompilerOptions, par exemple:

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

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

Vérifiez que vous avez une configuration nommée "production" pour ng build --prod, car c’est un raccourci pour ng build --configuration = production Pas de réponse a résolu mon problème, car le problème se trouvait juste devant le écran. Je pense que cela pourrait être assez courant ... J'ai internationalisé l'application avec i18n en renommant toutes les configurations, par exemple. production-fr. Ensuite, j'ai construit avec ng build --prod en supposant que l'optimisation par défaut est utilisée et qu'elle devrait être proche de l'optimum, mais en fait, ng build a été exécutée, ce qui a abouti à un bundle de 7 Mo au lieu de 250 Ko.

0
antidote

J'ai une application de démarrage à ressort 5 + angulaire (application.properties 1.3+) avec l'aide de la compression (lien ci-dessous) qui a été en mesure de réduire la taille de la taille de main.bundle.ts de 2,7 Mo à 530 Ko.

De plus, par défaut --aot et --build-optimizer sont activés avec le mode --prod, vous n'avez pas besoin de les spécifier séparément.

https://stackoverflow.com/a/28216983/9491345

0
sah1