185 votes

Comment réduire la taille du bundle de prod?

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

Elle affiche quelques pages relatives à 3 routes. J'ai 3 composants. Sur l'une de ces pages j'utilise lodash et les modules Angular 2 HTTP pour obtenir des données (en utilisant les Observables RxJS, map et subscribe). J'affiche ces éléments en utilisant un simple *ngFor.

Cependant, malgré le fait que mon application soit vraiment simple, j'obtiens un package et des maps très volumineux (à mon avis). Je ne parle pas des versions compressées en gzip mais de la taille avant compression. Cette question est juste une demande de recommandations générales.

Résultats de quelques tests:

ng build

Hash: 8efac7d6208adb8641c1 Temps: 10129ms chunk {0} main.bundle.js, main.bundle.map (main) 18,7 ko {3} [initiale] [rendue]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 ko {4} [initiale] [rendue]

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 [initiale] [rendue]

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

Attendez: 10 Mo de bundle vendor pour une application aussi simple?

ng build --prod

Hash: 09a5f095e33b2980e7cc Temps: 23455ms chunk {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (main) 18,3 ko {3} [initiale] [rendue]

chunk {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (styles) 154 ko {4} [initiale] [rendue]

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

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

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

Attendez encore: une taille de bundle vendor similaire pour prod?

ng build --prod --aot

Hash: 517e4425ff872bbe3e5b Temps: 22856ms chunk {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 ko {3} [initiale] [rendue]

chunk {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 ko {4} [initiale] [rendue]

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

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

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

ng build --aot

Hash: 040cc91df4df5ffc3c3f Temps: 11011ms chunk {0} main.bundle.js, main.bundle.map (main) 130 ko {3} [initiale] [rendue]

chunk {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 ko {4} [initiale] [rendue]

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

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

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

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

  • Pourquoi les bundles vendor sont-ils si énormes?
  • Est-ce que l'élagage d'arbre est correctement utilisé par angular-cli?
  • Comment améliorer cette taille de bundle?
  • Les fichiers .map sont-ils nécessaires?
  • Les fonctionnalités de test sont-elles incluses dans les bundles? Je n'en ai pas besoin en prod.
  • Question générale: quels outils sont recommandés pour empaqueter en prod? Peut-être que angular-cli (utilisant Webpack en arrière-plan) n'est pas la meilleure option? Peut-on faire mieux?

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

0 votes

Pour en savoir plus sur l'optimisation de l'application angular 2, consultez ceci : github.com/mgechev/angular-performance-checklist#introductio‌​n

1 votes

Mais je ne pense pas que nous devrions nous en faire autant, angular-cli évoluera et les choses seront de mieux en mieux faites. Si vous avez besoin d'une fonctionnalité que angular-cli n'a pas, il suffit de soumettre un problème dans leur dépôt: github.com/angular/angular-cli

0 votes

Alors que je pense que @Timathon a raison à certains égards, si quelqu'un essaie de déployer Angular2 en production, il devrait se préoccuper des tailles des bundles car cela affecte directement les performances de l'application. La liste de contrôle des performances d'Angular est une excellente ressource pour voir ce qui peut être amélioré. L'équipe Angular travaille à réduire les tailles des bundles. Excité de voir où cela va !

102voto

Jack Clancy Points 636

Mise à jour février 2020

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

  1. Comme l'a dit un autre répondant, ng build --prod --build-optimizer est une bonne option pour les personnes utilisant une version inférieure à Angular v5. Pour les nouvelles versions, cela se fait par défaut avec ng build --prod
  2. Une autre option consiste à utiliser le fractionnement des modules/le chargement différé pour mieux diviser votre application en plus petits morceaux
  3. Le moteur de rendu Ivy est activé par défaut dans Angular 9, il offre de meilleures tailles de bundles
  4. Assurez-vous que vos dépendances tierces peuvent être éliminées lors de la construction (tree shakeable). Si vous n'utilisez pas encore Rxjs v6, vous devriez le faire.
  5. Si tout le reste échoue, utilisez un outil tel que webpack-bundle-analyzer pour voir ce qui provoque un excès de poids dans vos modules
  6. Vérifiez si vos fichiers sont compressés avec gzip

Certains affirment que l'utilisation de la compilation AOT peut réduire la taille du bundle du fournisseur à 250ko. Cependant, dans l'exemple de BlackHoleGalaxy, il utilise la compilation AOT et se retrouve toujours avec une taille de bundle du fournisseur de 2,75 Mo avec ng build --prod --aot, 10 fois plus grand que les supposés 250ko. Ce n'est pas anormal pour les applications Angular2, même si vous utilisez la v4.0. 2,75 Mo reste trop grand pour quiconque se soucie vraiment des performances, surtout sur un appareil mobile.

Il y a quelques choses que vous pouvez faire pour améliorer les performances de votre application :

1) AOT & Élimination des dépendances inutilisées (angular-cli fait cela par défaut). Avec Angular 9, l'AOT est activé par défaut en environnement de prod et de dev.

2) Utilisation d'Angular Universal également appelé rendu côté serveur (pas dans cli)

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

4) Service Workers
voir : https://github.com/angular/angular-cli/issues/4006

Vous n'avez pas forcément besoin de tout cela dans une seule application, mais ce sont quelques-unes des options actuellement disponibles pour optimiser les performances d'Angular. Je crois/j'espère que Google est conscient des lacunes par défaut en termes de performances et prévoit de les améliorer à l'avenir.

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

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

0 votes

Mon projet minimal est de 384ko, voir github.com/JCornat/min-angular Je suis sûr qu'il y a un moyen facile de l'optimiser, mais il est proche de 250ko !

2 votes

@JacquesCornat semble bon! Mais votre application n'a qu'un seul composant. La question est de savoir comment gérer les tailles de bundle ou les applications plus grandes. Souvent, AOT ne réduit pas suffisamment les tailles de bundle, et les gens sont obligés de chercher d'autres moyens d'optimiser. Je recommande vivement à tout le monde de consulter webpack-bundle-analyzer. Un moyen très utile/facile de voir ce qui cause le gonflement

0 votes

Malheureusement, des utilitaires tels que sw-precache refusent de traiter des paquets de fournisseurs de plus de 2 Mo.

24voto

Shubhendu Vaid Points 442

Utilisez la dernière version d'angular cli et utilisez la commande ng build --prod --build-optimizer Cela réduira certainement la taille de construction pour l'environnement de production.

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

L'optimiseur de construction a deux principales tâches. Tout d'abord, nous sommes en mesure de marquer des parties de votre application comme pures, cela améliore l'élagage fourni par les outils existants, supprimant des parties supplémentaires de votre application qui ne sont pas nécessaires.

La deuxième chose que fait l'optimiseur de construction est de supprimer les décorateurs Angular du code d'exécution de votre application. Les décorateurs sont utilisés par le compilateur, et ne sont pas nécessaires à l'exécution et peuvent donc être supprimés. Chacune de ces tâches diminue la taille de vos bundles JavaScript, et augmente la vitesse de démarrage de votre application pour vos utilisateurs.

Remarque : Une mise à jour pour Angular 5 et supérieur, la ng build --prod s'occupe automatiquement du processus ci-dessus :)

1 votes

En ce qui concerne Angular 6 en ce moment, le fournisseur pèse toujours 4 Mo pour simplement installer angular/material et firebase

0 votes

C'est un problème avec angular/material, même moi j'ai rencontré cette erreur. Le "tree shaking" n'a probablement pas été effectué correctement, c'est probablement la cause principale. Avec le nouveau moteur de rendu IVY, il serait probablement résolu.

19voto

Eric Simonton Points 580

Lodash peut contribuer à une grosse partie de code à votre bundle en fonction de la manière dont vous l'importe. Par exemple :

// inclut l'ensemble du package (très volumineux)
import * as _ from 'lodash';

// selon votre chaîne de construction, peut toujours inclure l'ensemble du package
import { flatten } from 'lodash';

// importe uniquement le code nécessaire pour `flatten`
import flatten from 'lodash-es/flatten'

Personnellement, je voulais toujours des empreintes plus petites de mes fonctions utilitaires. Par exemple, flatten peut contribuer jusqu'à 1,2K à votre bundle, après minimisation. J'ai donc constitué une collection de fonctions lodash simplifiées. Mon implémentation de flatten contribue d'environ 50 octets. Vous pouvez consulter cela ici pour voir si cela vous convient : https://github.com/simontonsoftware/micro-dash

1 votes

2/ J'ai essayé les astuces "loadash-es" du commentaire ci-dessus. Cela a réduit la taille de mon bundle de 0,08 Mo.

0 votes

Ce n'est pas grand-chose! Avez-vous encore autre chose important lodash à l'ancienne? Vous n'obtiendrez aucune aide à moins que tout ne soit importé de la nouvelle manière.

0 votes

Je pense que j'ai tout remplacé. La taille n'aurait pas changé autrement. J'ai donné un autre conseil ci-dessous (chose gzip) qui nous a vraiment aidés.

13voto

Jacques Cornat Points 1017

Tout d'abord, les paquets de fournisseurs sont énormes simplement parce qu'Angular 2 repose sur de nombreuses bibliothèques. La taille minimale pour une application Angular 2 est d'environ 500 Ko (250 Ko dans certains cas, voir le post ci-dessous).
Tree shaking est correctement utilisé par angular-cli.
Ne pas inclure les fichiers .map, car ils sont utilisés uniquement pour le débogage. De plus, si vous utilisez le module de remplacement à chaud, supprimez-le pour alléger le fournisseur.

Pour l'emballage en production, j'utilise personnellement Webpack (et angular-cli l'utilise aussi), car vous pouvez vraiment configurer tout pour l'optimisation ou le débogage.
Si vous voulez utiliser Webpack, je suis d'accord que c'est un peu difficile à première vue, mais consultez des tutoriels sur le net, vous ne serez pas déçu.
Sinon, utilisez angular-cli, qui fait vraiment bien le travail.

L'utilisation de la compilation en avance est obligatoire pour optimiser les applications et réduire la taille de l'application Angular 2 à 250 Ko.

Voici un dépôt que j'ai créé (github.com/JCornat/min-angular) pour tester la taille minimale du bundle Angular, et j'obtiens 384 Ko. Je suis sûr qu'il y a un moyen simple de l'optimiser.

En parlant d'applications volumineuses, en utilisant la configuration AngularClass/angular-starter, la même que dans le dépôt ci-dessus, la taille de mon bundle pour les grandes applications (150+ composants) est passée de 8 Mo (4 Mo sans fichiers map) à 580 Ko.

0 votes

Quelle configuration spécifique d'angular-starter aide à réduire la taille du bundle? Est-ce le webpack.config?

2 votes

Oui, c'est la configuration webpack qui réduit la taille du bundle.

9voto

Renil Babu Points 470

La solution suivante suppose que vous servez votre dossier dist/ en utilisant nodejs. Veuillez utiliser le fichier app.js suivant au niveau de la 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 les dépendances;

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

Maintenant construisez l'application

ng build --prod --build-optimizer

Si vous souhaitez compresser davantage la construction, disons réduire de 300ko (environ) , suivez le processus ci-dessous;

Créez un dossier appelé vendor à l'intérieur du dossier src et à l'intérieur du dossier vendor créez un fichier rxjs.ts et collez le code suivant dedans;

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

Ensuite, ajoutez le contenu suivant dans le fichier tsconfig.json de votre application angular-cli. Ensuite, dans les compilerOptions, ajoutez le json suivant;

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

Cela réduira considérablement la taille de votre construction. Dans mon projet, j'ai réduit la taille de 11mo à 1mo. J'espère que cela vous aidera

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X