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
Nous vous recommandons de commencer par mesurer les performances d'un site Web avant d'ajouter des optimisations.
- Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran .
Allez-y, cliquez sur votre chaton préféré ! Realtime Database de Firebase est utilisé 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 DevTools.
- Cliquez sur l'onglet Réseau.
- Cochez la case Disable cache (Désactiver le cache).
- Actualisez l'application.
Presque 1 Mo de code JavaScript est envoyé pour charger cette application simple.
Examinez les avertissements du projet dans DevTools.
- Cliquez sur l'onglet Console.
- Assurez-vous que
Warnings
est activé dans le menu déroulant des niveaux à côté de l'entréeFilter
.
- Examinez l'avertissement affiché.
Firebase, qui est l'une des bibliothèques utilisées dans cette application, est un bon samaritain. En effet, il affiche un avertissement indiquant aux développeurs de ne pas importer l'intégralité de son package, mais uniquement les composants utilisés. En d'autres termes, il existe des bibliothèques inutilisées qui peuvent être supprimées dans cette application pour accélérer son chargement.
Il existe également des cas où une bibliothèque particulière est utilisée, mais où il peut exister une alternative plus simple. Le concept de suppression des bibliothèques inutiles est abordé plus loin dans ce tutoriel.
Analyser le groupe
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. Sa base de données en temps réel est utilisée pour stocker et synchroniser les informations concernant 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
moment
permet de calculer son âge en semaines.
Comment deux dépendances seulement peuvent-elles contribuer à une taille de bundle de près d'1 Mo ? L'une des raisons est que toute dépendance peut à son tour avoir ses propres dépendances. Il y en a donc beaucoup plus que deux si chaque profondeur/branche de l'"arbre" de dépendance est prise en compte. Une application peut facilement devenir volumineuse relativement rapidement si de nombreuses dépendances sont incluses.
Analysez le bundler pour mieux comprendre ce qui se passe. Plusieurs outils créés par la communauté peuvent vous aider à le faire, comme 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 est actualisée, vous devriez voir une visualisation de l'intégralité du bundle au lieu de l'application elle-même.
Pas aussi mignons que de voir des chatons ⁂, mais incroyablement utiles quand même. Pointez sur l'un des packages pour voir sa taille représentée de trois manières différentes:
Taille de la statistique | 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) réduit automatiquement la taille des fichiers compilés. C'est pourquoi elle est inférieure à la taille des statistiques. |
Taille compressée | Taille du package après compression avec l'encodage gzip. Ce sujet est traité dans un guide distinct. |
Avec l'outil webpack-bundle-analyzer, il est plus facile d'identifier les packages inutilisés ou inutiles qui représentent une grande partie du bundle.
Supprimer les packages inutilisés
La visualisation montre que le package firebase
comprend beaucoup plus qu'une simple base de données. Il comprend des packages supplémentaires tels que:
firestore
auth
storage
messaging
functions
Ce sont tous des services incroyables fournis par Firebase (voir 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 tous les importer.
Annulez les modifications dans webpack.config.js
pour afficher à nouveau l'application:
- Supprimez
BundleAnalyzerPlugin
de 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;
À présent, l'application devrait 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';
Lorsque l'application se recharge, l'avertissement DevTools ne s'affiche plus. L'ouverture du panneau Network (Réseau) des outils de développement permet également d'obtenir une bonne réduction de la taille du bundle:
Plus de la moitié de la taille du bundle a été supprimée. 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 sélectivement différentes parties de leurs packages. Sans trop d'efforts, la mise à jour des 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é nettement réduite, il reste encore beaucoup à faire. 😈
Supprimer les packages inutiles
Contrairement à Firebase, l'importation de parties de la bibliothèque moment
ne peut pas être effectuée aussi facilement, mais peut-être peut-elle être supprimée complètement ?
L'anniversaire de chaque chaton mignon est stocké 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 particulières, 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 au même format, une petite fonction permettant de trouver l'âge de chaque chaton en semaines peut probablement être créée.
Comme toujours, essayez de ne pas effectuer de copier-coller en suivant la procédure. 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 valeur dans notre base de données:
favoritesRef.on("value", (snapshot) => { ... })
Au-dessus de cela, 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 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> `}) });
Rechargez l'application et examinez à nouveau le panneau Network (Réseau).
La taille de notre bundle a été réduite de plus de la 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 pourquoi il peut être si utile de supprimer les packages inutilisés ou inutiles. Avant de commencer à optimiser une application avec cette technique, il est important de savoir que cela peut être beaucoup plus complexe dans les applications plus volumineuses.
En ce qui concerne la suppression des bibliothèques inutilisées, essayez d'identifier les parties d'un bundle qui sont utilisées et celles qui ne le sont pas. Si un paquet semble mystérieux et qu'il ne semble pas être utilisé nulle part, prenez du recul et vérifiez quelles dépendances de niveau supérieur pourraient en avoir besoin. Essayez de trouver un moyen de les dissocier.
La suppression des bibliothèques inutiles peut s'avérer un peu plus compliquée. Il est important de travailler en étroite collaboration avec votre équipe pour voir s'il est possible de simplifier certaines parties du codebase. Il peut sembler que supprimer moment
dans cette application soit la bonne chose à faire à chaque fois, mais que se passerait-il s'il y avait des fuseaux horaires et des paramètres régionaux différents à gérer ? Ou que se passerait-il s'il y avait
des manipulations de date plus compliquées ? La manipulation et l'analyse des dates et heures peuvent s'avérer très délicates. Les bibliothèques telles que moment
et date-fns
simplifient considérablement ce processus.
Tout est un compromis, et il est important d'évaluer si la complexité et l'effort nécessaires pour déployer une solution personnalisée sont justifiés au lieu de s'appuyer sur une bibliothèque tierce.