Optimisation des performances pour les applications Node.js
Les performances sont un aspect important lors de la création de pages Web et d'applications. Vous devez comprendre combien de temps vos utilisateurs interagissent avec votre application, à quelle fréquence ils la quittent, ainsi que le temps de réponse. Les 10 premières secondes sont vitales pour déterminer si un utilisateur quittera ou continuera d'interagir avec vos pages Web. Vous devez clairement accélérer la page, apporter de la valeur dans ces 10 secondes et attirer l'attention de l'utilisateur pour qu'il passe plus de temps sur votre page. C'est là que l'optimisation de votre page et l'accélération du temps de réponse deviennent importants pour maintenir une bonne expérience utilisateur. Le Node.js est connu pour produire des applications Web ultra-rapides et évolutives. Le Node.js utilise une architecture événementielle et des tâches non bloquantes (désynchronisés) s'exécutant sur un seul processus léger. Vous avez besoin que votre application soit rapide et entièrement optimisée. On pourrait dire que Node.js est le feu et l'optimisation des performances est l'essence. Imaginez à quel point votre application pourrait être extrêmement rapide.
Réduire le nombre de paquets
Une technique pour accélérer le chargement des pages s'est d'avoir un minimum de paquet à charger. Ce notion est particulièrement vrai du côté client et moins du côté serveur. Ainsi, vous pouvez par exemple installer le paquet depcheck dans la racine du répertoire de votre projet comme ceci avec NPM dans une session en mode administrateur :
npm install -g depcheck |
ou avec NPX à l'aide de la commande suivante :
npx depcheck |
Ensuite, vous n'avez qu'à tapez la commande suivante :
depcheck |
on obtiendra un résultat ressemblant à ceci :
Unused dependencies * @babel/core * @babel/plugin-proposal-object-rest-spread * @babel/register * @material-ui/system * @streamlinehq/streamline-icons-react * @streamlinehq/streamline-regular * confusing-browser-globals * eslint-plugin-import * fs * grunt * ignore-loader * postcss * ramda Missing dependencies * _helpers: .\src\client.js * jss: .\src\requestHandler.js |
En théorie, vous n'avez alors qu'à enlever tous les noms de paquets situés dans «Unused dependencies» et vous verrez réduire la taille de votre code progressivement.
Codage désynchronisée
Le Node.js est conçu avec des architectures de concurrence à un seul processus léger. Le codage désynchronisé est largement utilisé dans Node.js pour garantir un flux opérationnel non bloquant. Les entrées/sorties désynchronisées permettent à d'autres traitements de continuer avant même la fin de la première transmission. Le codage synchronisé peut potentiellement verrouiller votre page Web. Il utilise des opérations de blocage pouvant bloquer votre processus léger principal, ce qui réduira considérablement les performances de votre page Web.
Le codage désynchronisé vous permettra d'utiliser des files d'attente pour surveiller votre flux de travail, vous permettant d'ajouter des tâches supplémentaires et d'ajouter des rappels supplémentaires sans bloquer votre processus léger principal. Même si vous essayez d'utiliser des méthodes asynchrones, dans certains cas, il est possible de trouver votre page Web effectuant des appels bloquants. Ceci est courant lors de l'utilisation de modules tiers. Vous devez garder un oeil sur les bibliothèques externes que vous utilisez et prendre des précautions pour éviter qu'elles ne dominent les appels synchronisées.
Optimisation des requêtes
Imaginez simplement avoir plus d'un million de lignes de données à interroger à partir de votre table de base de données. Le processus généré par cette base de données pour obtenir le point de terminaison de ces données affectera considérablement les performances de votre application. L'utilisation de mauvaises requêtes ralentira votre application, laissant vos utilisateurs insatisfaits. La solution à cela consiste à effectuer une optimisation des requêtes.
- Éviter les «SELECT *» : Ce serait la chose la plus évidente que vous utiliseriez pour sélectionner vos colonnes, non? Cependant, vous ne devez pas oublier à quel point cette requête peut
être lourde. Pour interroger les colonnes d'une table, optez pour une approche plus distincte. Utilisez l'instruction SELECT pour interroger uniquement les
données dont vous avez besoin et éviter des charges de récupération supplémentaires dans votre base de données. Par exemple, supposons que vous ayez une table nommée Clients avec les champs Prenom,
NomFamille, Ville, Province, Telephone et Notes. Pour sélectionner les champs Prenom, NomFamille, Ville et Province les deux requêtes suivantes peuvent être utilisées :
SELECT * FROM Clients
et la requête suivante :
SELECT Prenom, NomFamille, Ville et Province FROM Clients
La première requête extrait tous les champs de cette table même si nous n'en avons pas tous besoin. La deuxième requête extraira les seuls champs obligatoires, la deuxième requête sera donc le moyen le plus efficace d'exécuter l'instruction SELECT. Car, il ne faut pas oublier que moins vous transmettez de données entre votre serveur Web et votre serveur de base de données, moins il prendra de temps à transmettre les données. La même idée doit s'appliquer lors de l'utilisation des instructions INSERT et UPDATE.
- Utiliser la clause WHERE Le but de la requête est d'extraire les enregistrements requis de votre base de données. La clause WHERE permet de filtrer les enregistrements et limite le nombre d'enregistrements à extraire en fonction des conditions. La clause WHERE remplace la clause HAVING sélectionnant les enregistrements avant de filtrer l'ensemble de données. Dans les opérations SQL, les instructions WHERE sont plus rapides car elles réduisent les données traitées par le moteur de base de données.
Mise en cache
Un cache est une mémoire tampon dans laquelle les données fréquemment consultées sont entreposées temporairement pour y accéder plus rapidement. Les données mises en cache sont ensuite récupérées sans avoir à accéder à l'origine. La mise en cache améliorera le temps de réponse de votre application et réduira même certains coûts tels que la bande passante et les volumes de données.
La mise en cache est une excellente pratique pour améliorer les performances de votre application. Si vous avez un faible nombre d'utilisateurs, les performances de votre application peuvent ne pas être grandement affectées. Cependant, des problèmes de performances peuvent survenir lorsque le trafic augmente et que vous devez maintenir l'équilibre de charge. Lorsque cela se produit, la mise en cache régulière de votre application sera une excellente technique pour obtenir de meilleures performances. La mise en cache peut être un peu difficile, vous avez donc besoin d'outils pour mettre en cache efficacement votre application, tels que :
- Le cache Redis est entièrement désynchronisé avec des performances optimales pour gérer les demandes de données mises en cache dans un seul processus léger. Pensez à le vérifier. C'est une API fluide vous aidant à gérer votre cache côté client et côté serveur.
- Le Memcached entrepose les données sur différents noeuds. Il utilise un schéma de hachage fournissant une fonctionnalité de table de hachage. Cela garantit que l'ajout ou la suppression d'un noeud de serveur ne modifie pas de manière significative la cartographie des clefs aux noeuds de serveur.
- Le Node-cache fonctionne presque comme Memcached avec les méthodes set, get et delete. Il a un délai d'expiration supprimant les données du cache lorsque le délai expire.
- Le serveur Nginx aidera à maintenir l'équilibre de la charge. Le Nginx aidera à mettre en cache les fichiers statiques, ce qui déchargera considérablement le travail du serveur d'applications. Il offre une faible utilisation de la mémoire et une concurrence élevée.
Libérez-vous des sessions
Les données de session sont entreposées en mémoire. Au fur et à mesure que le trafic dans votre application augmente, davantage de sessions seront générées, ce qui peut ajouter une surcharge importante à votre serveur. Vous devez trouver le moyen d'entreposer les données de session ou de minimiser la quantité de données entreposées dans une session. Des modules tels que Express.js peuvent vous aider à créer des protocoles de serveur sans état. Les protocoles sans état ne sauvegardent ni n'entreposent aucune information des visites précédentes.
Basculez vers un magasin de session externe tel que Redis, Nginx ou MongoDB. Dans la mesure du possible, la meilleure option serait de n'entreposer aucun état de session sur votre serveur pour de meilleures performances.
Rendu côté client
Le puissant MVC/MVVM a contribué à la croissance des applications d'une seule page. Les cadres d'applications tels que AngularJS, Ember, Meteor et BackboneJS sont des exemples de la puissante technologie MVC actuelle pour le rendu côté client.
Ces cadres d'applications renvoient des données dynamiques au format JSON et les affichent sur une interface utilisateur de page Web rendue côté client. Cela signifie qu'aucune mise en page de balisage ne sera envoyée avec chaque demande. Le JSON brut sera envoyé puis rendu côté client, ce qui rendra la page statique lors du rechargement de la page. Cela permet d'économiser de la bande passante, ce qui se traduit par une vitesse et des performances plus élevées.
Compression Gzip
Le Gzip compresse les requêtes et réponses HTTP. Le Gzip compresse les réponses avant de les envoyer au navigateur Web, le navigateur prend donc moins de temps pour les récupérer. Le Gzip compresse également la requête vers le serveur à distance, ce qui augmente considérablement les performances Web.
Lorsque vous utilisez Express.js, choisissez d'utiliser la compression. Il s'agit d'un intergiciel de compression Node.js prenant en charge deflate, Gzip et sert du contenu statique. La bibliothèque de compression compressera chaque requête passant par l'intergiciel. Exemple de code compressant les données :
- const compression = require("compression");
- const express = require("express");
- const app = express();
- // compresses toutes les responses
- app.use(compression());
- // ajoute toutes les routes
Évitez les fuites de mémoire
Une fuite de mémoire se produit lorsqu'un programme informatique gère de manière incorrecte les allocations de mémoire d'une manière que la mémoire n'étant plus nécessaire n'est pas libérée. Avec des fuites de mémoire, une page chargée réservera de plus en plus de mémoire. Ceux-ci occuperont lentement votre espace disponible à un point où l'utilisation du microprocesseur sera surchargée. De tels scénarios affecteront gravement les performances de votre application.
Vous pouvez choisir de redémarrer votre application et ces problèmes disparaîtront comme par magie, mais ce ne sera pas une solution fiable. Le problème se répétera et la mémoire s'accumulera périodiquement. Les fuites de mémoire peuvent provenir d'un DOM ayant été supprimé d'une page mais certaines variables y font toujours référence. Si vous supprimez des valeurs DOM, assurez-vous de les définir sur null. Lorsqu'elle est nulle, le ramasse-miettes les éliminera et aidera à éviter les fuites de mémoire.
Utilisez les outils de développement Chrome pour analyser si votre page Web présente des fuites de mémoire. Les outils de développement Chrome vous aideront à détecter et à déboguer les fuites de mémoire.
Surveillance en temps réel
La surveillance permet d'avoir un aperçu de votre application de production pour garantir un système stable et fiable. Un aperçu est essentiel pour aider à détecter les problèmes de performances au sein de votre système. Vous devez savoir quand votre système est en panne avant que vos clients ne commencent à se plaindre de votre système défectueux. C'est pourquoi vous avez besoin d'alertes en temps réel pour être immédiatement avertie. Une surveillance appropriée permet également de mieux comprendre les fonctionnalités du comportement de votre application. Vous devez savoir combien de temps prend votre application pour exécuter chaque fonction dans l'environnement de production. De plus, si vous utilisez des microservices, vous devez surveiller les connexions réseau et réduire les délais de communication entre les deux services. Quelques outils tiers couramment utilisés pour surveiller les applications Node.js comprennent LogicMonitor, Monitis, Newrelic et Stackify.
Vous pouvez envisager d'utiliser Google Analytics pour obtenir des informations telles que les visites des utilisateurs, le trafic, les sources de trafic, le taux de rebond, le taux de rétention des utilisateurs, les sessions, la durée des sessions ainsi que les pages vues. Les cadres de surveillance Node.js incluent Hapi, Restify, Derby, Express, Koa et Mocha.
Garder votre code léger et compact
Lors du développement d'applications mobiles et Web, assurez-vous d'appliquer le concept de rendre votre base de code petite et compacte pour le code client et le code serveur. Cela réduira la latence et les temps de chargement. Lorsqu'il s'agit de rendre votre code léger, une application Web d'une seule page est un excellent choix à considérer. Par exemple, supposons que votre application Web comporte une page contenant six fichiers JavaScript. Lorsque cette page est accédée dans le navigateur Web, ce navigateur Web fera six requêtes HTTP pour récupérer tous vos fichiers. Cela créera un scénario de blocage et d'attente. Ceci est un bon exemple de cas où vous pourriez réduire et lier vos multiples fichiers en un seul pour éviter des scénarios comme celui-ci.
Le Node.js a beaucoup de bibliothèques et de modules open source. Au cours de la phase de développement, vous devez vous demander pourquoi vous utilisez ce cadre par rapport à un autre. Vous devez savoir si un cadre d'application vaut la peine d'être utilisé ou s'il existe d'autres moyens plus simples d'écrire votre code.
Le fait est que lorsque vous envisagez d'utiliser un cadre, cela devrait en valoir la peine. Cela ne veut pas dire que le choix des cadres est mauvais. Les cadres sont super. Ils sont évolutifs et présentent des avantages incontestés. Envisagez d'utiliser un cadre d'application uniquement s'il simplifie votre code.