Luca Mele
Luca Mele

Performance

Réduire vos dépendances Node pour des applications maintenables

Réduire vos dépendances Node pour des applications maintenables
Retour aux articles
·7 min de lecture

Lancez `ls node_modules | wc -l` dans votre projet. Si le nombre vous met mal à l'aise, vous n'êtes pas seul. Le projet JavaScript moyen embarque des centaines de dépendances transitives, et chacune est un risque : vulnérabilités de sécurité, breaking changes, maintenance abandonnée ou simplement du bloat.

Après des années à diriger des équipes frontend dans des entreprises comme AXA, Migros, Vontobel et UBS, j'ai développé une opinion tranchée : chaque dépendance doit mériter sa place. Si vous pouvez l'écrire en 20 lignes, vous devriez probablement le faire.

Le coût caché de npm install

Les dépendances ne sont pas gratuites. Chacune s'accompagne de coûts qui n'apparaissent pas dans votre analyseur de taille de bundle :

Surface d'attaque de sécurité — chaque paquet est du code que vous n'avez pas écrit et que vous ne pouvez pas entièrement auditer. L'incident event-stream, le détournement de ua-parser-js, le sabotage de colors.js — ce ne sont pas des cas limites, c'est la conséquence naturelle de faire confiance à des milliers d'inconnus avec votre chaîne d'approvisionnement.

Charge de maintenance — les paquets se mettent à jour, et ces mises à jour peuvent casser des choses. Plus vous avez de paquets, plus vous passez de temps sur les mises à jour de dépendances au lieu de développer des fonctionnalités. J'ai vu des équipes passer des sprints entiers à traiter les alertes Dependabot.

Surcharge cognitive — les nouveaux développeurs qui rejoignent votre projet doivent comprendre non seulement votre code mais aussi chaque abstraction introduite par vos dépendances. Cette bibliothèque utilitaire 'pratique' avec 200 fonctions signifie 200 choses que quelqu'un pourrait utiliser au lieu de l'approche standard.

Impact sur le temps de build — chez Migros, nous avions un monorepo PNPM avec Turbo pour Bikeworld et Micasa. Lorsque nous avons audité notre arbre de dépendances et supprimé les paquets inutiles, notre pipeline CI est devenue nettement plus rapide. C'est du temps de développeur économisé sur chaque PR.

Avant d'installer, posez-vous trois questions

J'impose une checklist simple dans mes équipes avant d'ajouter toute dépendance :

1. Pouvons-nous l'écrire nous-mêmes en moins de 50 lignes ? Si oui, écrivez-le. Un petit utilitaire que vous possédez est meilleur qu'un paquet que vous ne contrôlez pas. Vous le comprenez parfaitement, il a zéro dépendance transitive et fait exactement ce dont vous avez besoin.

2. Ce paquet est-il activement maintenu ? Vérifiez la date du dernier commit, les issues ouvertes et le bus factor. Un paquet avec un seul mainteneur qui a fait son dernier commit il y a 8 mois est une bombe à retardement.

3. Quel est le nombre de dépendances transitives ? Installez-le isolément et vérifiez ce qu'il embarque. J'ai vu des paquets 'simples' embarquer plus de 40 dépendances transitives. Ce sont 40 paquets qui peuvent casser, être détournés ou devenir abandonnés.

# Check what a package actually pulls in
mkdir /tmp/dep-check && cd /tmp/dep-check
npm init -y && npm install <package-name>
ls node_modules | wc -l
# If this number surprises you, reconsider

Des paquets courants dont vous n'avez pas besoin

Voici des exemples réels de projets dont j'ai hérité et que j'ai nettoyés :

lodash — Le JavaScript moderne dispose de Array.flat(), Array.flatMap(), Object.entries(), Object.fromEntries(), structuredClone() et de l'opérateur de chaînage optionnel. Importez la fonction lodash spécifique si vous en avez vraiment besoin (lodash/debounce), jamais la bibliothèque entière.

moment.js — Utilisez l'API native Intl.DateTimeFormat, ou tout au plus date-fns avec tree-shaking. Moment ajoute 300 Ko à votre bundle et est officiellement en mode maintenance.

axios — L'API Fetch est disponible partout désormais, y compris dans Node.js 18+. Vous n'avez plus besoin d'un wrapper autour de XMLHttpRequest.

uuid — Si vous avez juste besoin d'identifiants uniques, crypto.randomUUID() est intégré dans chaque runtime moderne.

classnames / clsx — Si vous utilisez Tailwind, vous avez probablement déjà un utilitaire cn() ou pouvez en écrire un en 3 lignes avec des template literals.

// Instead of: import { v4 as uuid } from 'uuid'
const id = crypto.randomUUID();

// Instead of: import axios from 'axios'
const res = await fetch('/api/data');
const data = await res.json();

// Instead of: import _ from 'lodash'
const unique = [...new Set(items)];
const grouped = Object.groupBy(items, (i) => i.type);

Quand les dépendances en valent la peine

Je ne dis pas d'éviter tous les paquets. Certains problèmes nécessitent véritablement des solutions externes :

Cryptographie — ne développez jamais la vôtre. Utilisez des bibliothèques établies et auditées.

Parsing complexe — analyse de dates avec gestion des fuseaux horaires, parsing CSV/XML, rendu markdown. Ce sont des domaines où les cas limites vous dévoreront.

Intégrations de frameworks — si vous utilisez Next.js, React ou Vue, les paquets de leur écosystème existent pour de bonnes raisons. next/image optimise les images mieux que tout ce que vous écririez vous-même.

Chez Vontobel, nous avons gardé notre nombre de dépendances réduit tout en construisant une plateforme financière complexe avec des prix WebSocket en temps réel. Les dépendances clés — React, Next.js et quelques bibliothèques spécialisées de formatage financier — ont toutes mérité leur place. Tout le reste, nous l'avons écrit nous-mêmes ou avons utilisé les API de la plateforme.

Une approche plus saine

Ma règle d'or : traitez les dépendances comme des recrutements. Chacune devrait passer par un processus de revue. Résout-elle un problème véritablement difficile (cryptographie, génération de PDF, traitement d'images) ? Gardez-la. Vous fait-elle gagner 15 minutes pour écrire une fonction utilitaire ? Écrivez la fonction.

Lancez un audit de dépendances chaque trimestre. Supprimez les paquets inutilisés. Remplacez les paquets lourds par des alternatives plus légères ou des API natives. Faites-en une habitude d'équipe, pas un nettoyage ponctuel.

Le résultat est un projet plus rapide à installer, plus rapide à builder, plus facile à auditer et — surtout — plus facile à maintenir à long terme pour votre équipe. Votre futur vous vous remerciera quand vous ne serez pas en train de déboguer un problème en production causé par une dépendance transitive cinq niveaux plus bas dont vous ne connaissiez même pas l'existence.