Secouement de l'arbre JavaScript, comme un pro

Il s'agit de la traduction d'un article sur l'optimisation et la réduction de la taille d'un ensemble d'applications. C'est bien parce que les meilleures pratiques sont décrites ici, des conseils que vous devez suivre pour faire fonctionner Trishhing et jeter le code inutilisé de l'assembly. Cela sera utile à beaucoup, car maintenant tout le monde utilise des systèmes d'assemblage dans lesquels il y a trishahing hors de la boîte. Mais pour que cela fonctionne correctement, vous devez respecter les principes décrits ci-dessous.

image

Trichashing devient la technique principale lorsque vous devez réduire la taille du bundle et améliorer les performances des applications sur JS.

Comment fonctionne le trichashing:

  1. Vous déclarez les importations et les exportations dans chaque module.
  2. Le collecteur (Webpack, Rollup ou autre) analyse l'arborescence des dépendances lors de l'assemblage.
  3. Le code inutilisé est exclu du pack final.

image
Le fichier utilitaire exporte deux fonctions,

image
mais seul initializeName est utilisé, formatName peut être supprimé.

Malheureusement, pour le bon fonctionnement du trishaking, une configuration du collecteur ne suffit pas. Pour obtenir un meilleur résultat, il est nécessaire de prendre en compte de nombreux détails, ainsi que de s'assurer que les modules n'ont pas été ignorés lors de l'optimisation.

Où commencer?


Il existe un grand nombre de directives pour la mise en place de trishaking. Il est préférable de commencer à plonger dans le sujet avec la documentation officielle de Webpack .

Il convient de mentionner qu'il y a quelques années, j'ai créé un passe-partout avec un assemblage et un trichashing déjà configurés. Donc, si vous avez besoin d'un point de départ pour un projet, mon référentiel peut être un bon exemple de krakenjs / grumbler .

Cet article explique comment travailler avec Webpack, Babel et Terser. Cependant, la plupart des principes présentés fonctionneront, que vous utilisiez Webpack, Rollup ou autre chose.

Utiliser la syntaxe ES6 pour les importations et les exportations


L'utilisation des importations et des exportations ES6 est la première et la plus importante étape du travail de trichashing.

La plupart des autres implémentations du modèle «module», y compris commonjs et require.js, ne sont pas déterministes pendant le processus de génération. Cette fonctionnalité ne permet pas aux collectionneurs tels que Webpack de déterminer exactement ce qui est importé, ce qui est exporté et, par conséquent, quel code peut être supprimé en toute sécurité.

image
Options possibles lors de l'utilisation de commonjs.

Lorsque vous utilisez des modules ES6, les options d'importation et d'exportation sont plus limitées:

  • Vous ne pouvez importer et exporter qu'au niveau du module, et non à l'intérieur de la fonction;
  • le nom du module ne peut être qu'une chaîne statique, pas une variable;
  • tout ce que vous importez doit être exporté quelque part.

image
Les modules ES6 ont une sémantique et des règles d'utilisation plus simples.

Des règles simplifiées permettent aux assembleurs de comprendre exactement ce qui a été importé et exporté et, par conséquent, de déterminer quel code n'est pas utilisé du tout.

Ne pas autoriser Babel à transporter des importations et des exportations


Le premier problème que vous pouvez rencontrer lors de l'utilisation de Babel pour traduire du code est la conversion par défaut des modules ES6 en commonjs. Cela empêche le collecteur d'optimiser le code et d'en lancer trop.

Heureusement, dans la configuration Babel, il existe un moyen simple de désactiver la transpilation des modules .

Après cela, le collectionneur pourra assumer la transpilation des importations et des exportations.

Rendez vos exportations atomiques


Webpack laisse généralement les exportations intactes dans les cas suivants:

  • ;
  • ;
  • .

Ces exportations seront soit entièrement incluses dans le bundle, soit complètement supprimées. Donc, à la fin, vous pouvez vous retrouver avec un bundle contenant du code qui ne sera jamais utilisé.

image
Les deux fonctions seront incluses dans le bundle, même si une seule est utilisée.

image
Et ici, la classe sera entièrement ajoutée à l'assemblage.

Essayez de garder vos exportations aussi petites et simples que possible.

image
Seule la fonction qui sera utilisée entrera dans le bundle final.

La mise en œuvre de ces conseils permet au collecteur de jeter plus de code car maintenant, pendant le processus d'assemblage, vous pouvez suivre quelle fonction a été importée et utilisée, et laquelle ne l'a pas été.

Cette astuce permet également d'écrire du code dans un style plus fonctionnel et réutilisable, et d'éviter d'utiliser des classes là où cela n'est pas justifié.

Si vous êtes intéressé par la programmation fonctionnelle, consultez cet article .

Évitez les effets secondaires au niveau du module


Lors de l'écriture de modules, de nombreuses personnes manquent un facteur important, mais très insidieux - l'influence des effets secondaires.

image
Webpack ne comprend pas ce que fait window.memoize et ne peut donc pas lancer cette fonction.

Notez que l'exemple ci window.memoize- dessus sera appelé au moment de l'importation du module.

Comme Webpack le voit:

  • ok, une fonction pure add est créée et exportée ici - je peux peut-être la supprimer si elle ne sera pas utilisée plus tard;
  • ensuite window.memoize est appelé, auquel add est passé;
  • Je ne sais pas ce qu'elle fait window.memoize, mais je sais qu'elle appellera probablement add et créera un effet secondaire.
  • donc pour des raisons de sécurité, je laisse la fonction d'ajout dans le bundle, même si personne d'autre ne l'utilise .

En réalité, nous sommes sûrs que c'est window.memoizeune fonction pure qui ne crée aucun effet secondaire et appelle add si quelqu'un l'utilise memoizedAdd.

Mais Webpack ne le sait pas et, pour des raisons de paix, ajoute la fonction d'ajout au bundle final.

Pour être honnête: les dernières versions de Webpack et Terser sont exceptionnellement douées pour détecter les effets secondaires.

image
Nous donnons à Webpack plus d'informations et obtenons un ensemble optimisé.

Maintenant, le collecteur a suffisamment d'informations pour l'analyse:

  • appelé ici memoizeau niveau du module, cela peut être lourd de problèmes;
  • mais la fonction memoizeest venue de l'importation ES6, vous devez regarder la fonction dans util.js;
  • en effet, la mémorisation ressemble à une fonction pure, il n'y a pas d'effets secondaires;
  • si personne n'utilise la fonction add, nous pouvons l'exclure en toute sécurité du bundle final.

Lorsque Webpack ne reçoit pas suffisamment d'informations pour prendre une décision, il emprunte le chemin sécurisé et quitte la fonction.

Utiliser des outils pour identifier les problèmes potentiels de trishaking


J'ai trouvé deux outils pour identifier les problèmes.

Le premier outil est la concaténation de modules , un plugin pour Webpack, qui vous permet d'obtenir une augmentation significative des performances. Il a une option de débogage. Il convient de noter que les facteurs empêchant la concaténation et le trichashing sont les mêmes: par exemple, les effets secondaires au niveau du module. Prenez les avertissements du plugin au sérieux, car tout problème augmente potentiellement la taille du bundle.

Le second est le plugin pour le linter https://www.npmjs.com/package/eslint-plugin-tree-shaking . Je ne l'ai pas encore intégré dans mon passe-partout, car il ne supportait pas l'écoulement lorsque je l'ai expérimenté. Cependant, il a assez bien identifié les problèmes de trichashing.

Soyez prudent avec les bibliothèques


Essayez d'utiliser des bibliothèques optimisées pour trichashing. Par exemple, si vous importez un grand ensemble de code minimisé jquery.min.js, il est possible que ce module ne soit pas optimisé. Il est préférable de rechercher un module à partir duquel les fonctions atomiques peuvent être importées, et pour l'assemblage et la minification, utilisez Webpack ou Rollup.

Parfois, vous pouvez importer une bibliothèque entière. Par exemple, lorsque vous utilisez la version de production de React, vous n'avez rien à jeter - tout ce qui s'y trouve est déjà optimisé.

Si vous utilisez une bibliothèque qui exporte des fonctions individuelles, par exemple lodash, essayez d'importer uniquement les fonctions nécessaires et assurez-vous que les autres sont exclues du bundle final.

Utiliser des drapeaux de construction


Le plugin DefinePlugin pour Webpack a une fonctionnalité merveilleuse, mais pas la plus célèbre - la possibilité d'influencer le code qui sera exclu pendant le processus de construction.

image

Si nous le passons __PRODUCTION__: trueau plugin, non seulement l'appel de fonction validateOptions, mais aussi sa définition seront exclus du bundle final .
Cela simplifie la création de différents bundles pour le développement et la production, et permet également de garantir que le code destiné au débogage n'entre pas en production.

Commencer l'assemblage


Il est très difficile à l’œil de déterminer comment Webpack optimisera un module particulier.

Exécutez donc la build, vérifiez le bundle final et voyez ce qui se passe. Jetez un œil au code JavaScript et assurez-vous qu'il ne reste rien qui aurait dû être jeté par trichashing.

Autre chose?


Si vous connaissez d'autres conseils utiles, veuillez en parler dans les commentaires.

All Articles