Dans cet atelier de programmation, vous allez améliorer les performances de l'application suivante en supprimant toutes les dépendances inutilisées et inutiles.

Mesurer
Il est toujours judicieux de commencer par mesurer les performances d'un site Web avant d'ajouter des optimisations.
- Pour prévisualiser le site, appuyez sur View App (Afficher l'application), puis sur Fullscreen (Plein écran)
.
Cliquez sur votre chaton préféré. La base de données en temps réel de Firebase est utilisée dans cette application. C'est pourquoi le score est mis à jour en temps réel et synchronisé avec toutes les autres personnes qui utilisent l'application. 🐈
- Appuyez sur Ctrl+Maj+J (ou Cmd+Option+J sur Mac) pour ouvrir les outils de développement.
- Cliquez sur l'onglet Réseau.
- Cochez la case Désactiver le cache.
- Actualisez l'application.

Près de 1 Mo de JavaScript est envoyé pour charger cette application simple !
Examinez les avertissements du projet dans les outils de développement.
- Cliquez sur l'onglet Console.
- Assurez-vous que
Warningsest activé dans le menu déroulant des niveaux à côté de l'entréeFilter.

- Examinez l'avertissement affiché.

Firebase, l'une des bibliothèques utilisées dans cette application, est un bon samaritain qui avertit les développeurs de ne pas importer l'intégralité de son package, mais uniquement les composants utilisés. En d'autres termes, cette application contient des bibliothèques inutilisées qui peuvent être supprimées pour accélérer le chargement.
Il existe également des cas où une bibliothèque particulière est utilisée, mais où une alternative plus simple peut être disponible. Le concept de suppression des bibliothèques inutiles est abordé plus loin dans ce tutoriel.
Analyse du bundle…
L'application comporte deux dépendances principales :
- Firebase : plate-forme qui fournit un certain nombre de services utiles pour les applications iOS, Android ou Web. Ici, sa base de données en temps réel est utilisée pour stocker et synchroniser les informations de chaque chaton en temps réel.
- Moment.js : bibliothèque d'utilitaires qui facilite la gestion des dates en JavaScript. La date de naissance de chaque chaton est stockée dans la base de données Firebase, et
momentest utilisé pour calculer son âge en semaines.
Comment deux dépendances peuvent-elles contribuer à une taille de bundle de près de 1 Mo ? L'une des raisons est que toute dépendance peut à son tour avoir ses propres dépendances. Il y en a donc bien plus que deux si l'on prend en compte chaque profondeur/branche de l'"arbre" de dépendances. Une application peut facilement devenir volumineuse assez rapidement si de nombreuses dépendances sont incluses.
Analysez le bundler pour mieux comprendre ce qui se passe. Il existe un certain nombre d'outils différents créés par la communauté qui peuvent vous aider, tels que webpack-bundle-analyzer.
Le package de cet outil est déjà inclus dans l'application en tant que devDependency.
"devDependencies": {
//...
"webpack-bundle-analyzer": "^2.13.1"
},
Cela signifie qu'il peut être utilisé directement dans le fichier de configuration webpack.
Importez-le au tout début de webpack.config.js :
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
Ajoutez-le maintenant en tant que plug-in à la toute fin du fichier dans le tableau plugins :
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
Lorsque l'application se recharge, vous devriez voir une visualisation de l'ensemble du bundle au lieu de l'application elle-même.

Ce n'est pas aussi mignon que de voir des chatons 🐱, mais c'est incroyablement utile. Pointez sur l'un des packages pour afficher sa taille de trois manières différentes :
| Taille des statistiques | Taille avant toute minimisation ou compression. |
|---|---|
| Taille analysée | Taille du package réel dans le bundle après sa compilation. La version 4 de webpack (utilisée dans cette application) minimise automatiquement les fichiers compilés, ce qui explique pourquoi la taille est inférieure à celle des statistiques. |
| Taille compressée au format Gzip | Taille du package après compression avec l'encodage gzip. Ce sujet est abordé dans un guide distinct. |
L'outil webpack-bundle-analyzer permet d'identifier plus facilement les packages inutilisés ou inutiles qui représentent un pourcentage important du bundle.
Supprimer les packages inutilisés
La visualisation montre que le package firebase ne se limite pas
à une base de données. Il inclut des packages supplémentaires tels que :
firestoreauthstoragemessagingfunctions
Il s'agit de services Firebase très utiles (consultez la documentation pour en savoir plus), mais aucun d'entre eux n'est utilisé dans l'application. Il n'y a donc aucune raison de les importer tous.
Annulez les modifications apportées à webpack.config.js pour afficher à nouveau l'application :
- Supprimez
BundleAnalyzerPluginde la liste des plug-ins :
plugins: [
//...
new BundleAnalyzerPlugin()
];
- Supprimez maintenant l'importation inutilisée en haut du fichier :
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
L'application devrait maintenant se charger normalement. Modifiez src/index.js pour mettre à jour les importations Firebase.
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
Désormais, lorsque l'application se recharge, l'avertissement des outils de développement ne s'affiche pas. L'ouverture du panneau Réseau des outils de développement montre également une réduction intéressante de la taille du bundle :

La taille du bundle a été réduite de plus de moitié. Firebase fournit de nombreux services différents et permet aux développeurs de n'inclure que ceux dont ils ont réellement besoin. Dans cette application, seul firebase/database a été utilisé pour stocker et synchroniser toutes les données. L'importation firebase/app, qui configure la surface de l'API pour chacun des différents services, est toujours requise.
De nombreuses autres bibliothèques populaires, telles que lodash, permettent également aux développeurs d'importer de manière sélective différentes parties de leurs packages. Sans trop d'efforts, mettre à jour les importations de bibliothèques dans une application pour n'inclure que ce qui est utilisé peut entraîner des améliorations significatives des performances.
Bien que la taille du bundle ait été considérablement réduite, il reste encore du travail. 😈
Suppression des packages inutiles…
Contrairement à Firebase, l'importation de parties de la bibliothèque moment n'est pas aussi simple, mais peut-être peut-elle être entièrement supprimée ?
La date de naissance de chaque chaton est stockée au format Unix (millisecondes) dans la base de données Firebase.

Il s'agit d'un code temporel d'une date et d'une heure spécifiques, représenté par le nombre de millisecondes écoulées depuis le 1er janvier 1970 à 00:00 UTC. Si la date et l'heure actuelles peuvent être calculées dans le même format, il est probablement possible de créer une petite fonction pour trouver l'âge de chaque chaton en semaines.
Comme toujours, essayez de ne pas copier-coller lorsque vous suivez les instructions. Commencez par supprimer moment des importations dans src/index.js.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
Un écouteur d'événements Firebase gère les modifications de valeurs dans notre base de données :
favoritesRef.on("value", (snapshot) => { ... })
Au-dessus, ajoutez une petite fonction pour calculer le nombre de semaines à partir d'une date donnée :
const ageInWeeks = birthDate => {
const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
const diff = Math.abs((new Date).getTime() - birthDate);
return Math.floor(diff / WEEK_IN_MILLISECONDS);
}
Dans cette fonction, la différence en millisecondes entre la date et l'heure actuelles (new Date).getTime() et la date de naissance (l'argument birthDate, déjà en millisecondes) est calculée et divisée par le nombre de millisecondes dans une seule semaine.
Enfin, toutes les instances de moment peuvent être supprimées dans l'écouteur d'événements en utilisant plutôt cette fonction :
favoritesRef.on("value", (snapshot) => {
const { kitties, favorites, names, birthDates } = snapshot.val();
favoritesScores = favorites;
kittiesList.innerHTML = kitties.map((kittiePic, index) => {
const birthday = moment(birthDates[index]);
return `
<li>
<img src=${kittiePic} onclick="favKittie(${index})">
<div class="extra">
<div class="details">
<p class="name">${names[index]}</p>
<p class="age">${moment().diff(birthday, 'weeks')} weeks old</p>
<p class="age">${ageInWeeks(birthDates[index])} weeks old</p>
</div>
<p class="score">${favorites[index]} ❤</p>
</div>
</li>
`})
});
Maintenant, actualisez l'application et examinez à nouveau le panneau Réseau.

La taille de notre bundle a encore été réduite de plus de moitié !
Conclusion
Grâce à cet atelier de programmation, vous devriez avoir une bonne compréhension de la façon d'analyser un bundle particulier et de l'utilité de supprimer les packages inutilisés ou inutiles. Avant de commencer à optimiser une application avec cette technique, sachez que cela peut être beaucoup plus complexe dans les applications plus volumineuses.
En ce qui concerne la suppression des bibliothèques inutilisées, essayez de déterminer quelles parties d'un bundle sont utilisées et lesquelles ne le sont pas. Si un package semble mystérieux et ne semble pas être utilisé, prenez du recul et vérifiez quelles dépendances de premier niveau pourraient en avoir besoin. Essayez de trouver un moyen de les dissocier les uns des autres.
La suppression des bibliothèques inutiles peut être un peu plus compliquée. Il est important de travailler en étroite collaboration avec votre équipe et de voir s'il est possible de simplifier certaines parties du codebase. Supprimer moment dans cette application peut sembler être la bonne chose à faire à chaque fois, mais que se passe-t-il si des fuseaux horaires et des paramètres régionaux différents doivent être gérés ? Et si les manipulations de dates étaient plus complexes ? La manipulation et l'analyse des dates et des heures peuvent s'avérer très complexes. Les bibliothèques telles que moment et date-fns simplifient considérablement ces opérations.
Tout est une question de compromis, et il est important de déterminer si la complexité et les efforts nécessaires pour déployer une solution personnalisée en valent la peine, plutôt que de s'appuyer sur une bibliothèque tierce.