Pourquoi les arbres de dépendances npm gonflent : trois raisons clés
Les arbres de dépendances dans les projets JavaScript grossissent souvent à cause de paquets obsolètes et de fonctionnalités redondantes. Cela entraîne des coûts de téléchargement inutiles, des conflits de versions et des vulnérabilités dans la chaîne d'approvisionnement. Explorons trois scénarios typiques qui expliquent cette situation et comment y remédier.
Prise en charge d'environnements anciens et problèmes spécifiques aux réalms
De nombreux paquets comme is-string ou hasown existent pour assurer la compatibilité avec des environnements d'exécution anciens, tels que ES3 (IE6/7, Node.js précoce). Ils implémentent des méthodes manquantes : Array.prototype.forEach, Array.prototype.reduce, Object.keys, Object.defineProperty.
Motivations supplémentaires :
- Protection de l'espace de noms global : Node importe des primordiales (par exemple,
Map) pour éviter les ruptures dues aux surcharges. Des paquets commemath-intrinsicsréexportentMath.*dans le même but. - Compatibilité entre réalms :
instanceofne fonctionne pas entre un iframe et son parent (constructeursRegExpdifférents). Une alternative estObject.prototype.toString.call(val) === '[object RegExp]', utilisée danschaiouis-stringpournew String(val).
const shebangRegex = /^#!(.*)/;
export default shebangRegex;
Pour la plupart des développeurs de niveau intermédiaire à senior, c'est excessif : Node moderne (pas plus vieux que 10 ans) et les navigateurs ne nécessitent pas de tels bidouillages. Recommandation : vérifiez votre browserslist et supprimez les polyfills inutiles.
Architecture atomique : de la théorie aux problèmes
La philosophie des paquets 'atomiques' consiste à découper le code en blocs minimaux pour la réutilisation. Un exemple est le graphe de dépendances de execa avec des paquets comme shebang-regex (5 lignes de code).
Utilitaires atomiques typiques :
arrify:Array.isArray(val) ? val : [val]slash: normalisation des barres obliques dans les cheminscli-boxes: JSON avec bordures d'éléments d'interfacepath-key:env['PATH'] || env['Path']onetime: appel de fonction uniqueis-wsl:process.platform === 'linux' && /microsoft/.test(os.release())is-windows:process.platform === 'win32
En théorie, cela simplifie la construction d'outils en ligne de commande. En pratique :
- Utilisation unique :
shebang-regexn'est utilisé que parshebang-command(même auteur) ;cli-boxes— uniquement parboxen/ink. - Duplication par hoisting : Dans
nuxt, des doublons commeis-docker,is-stream,is-wsl(2 versions chacune). Dupliquer le code en ligne est gratuit, sans surcharge npm. - Risques pour la chaîne d'approvisionnement : Plus de paquets signifie plus de vulnérabilités. Compromettre un mainteneur (comme l'an dernier) a affecté des centaines de dépendances.
Solution : intégrez les fonctions simples, utilisez le tree-shaking et pnpm avec hoisting strict.
Ponyfills qui ont survécu à leur époque
Les ponyfills sont des polyfills sans mutation des globaux, importés directement. Utiles pour les bibliothèques : @fastly/performance-observer-polyfill permet d'utiliser PerformanceObserver sans altérer l'environnement.
Problème : ils ne sont pas supprimés après l'arrivée du support natif.
Exemples de ponyfills obsolètes (avec téléchargements hebdomadaires) :
globalthis— pourglobalThis(supporté depuis 2019, 49M téléchargements/semaine)indexof— pourArray.prototype.indexOf(depuis 2010, 2,3M/semaine)object.entries— pourObject.entries(depuis 2017, 35M/semaine)
Dans eslint-plugin-react, la moitié du graphe est constituée de polyfills hérités. Pour les bibliothèques : comptez sur les polyfills côté consommateur (core-js). Vérifiez caniuse.com avant d'ajouter.
Points clés à retenir
- Optimisez l'héritage : 90 % des paquets n'ont pas besoin de polyfills ES3/ES5 ; utilisez
typeofau lieu deis-string. - L'atomicité nuit : Intégrez les fonctions de 5 lignes pour réduire les doublons et la surface d'attaque.
- Auditez les ponyfills : Supprimez les paquets pour des fonctionnalités supportées depuis plus de 5 ans dans l'environnement cible.
- Outils : Utilisez
npm ls --depth=0,depcheck,npm-check-updatespour l'analyse. - Initiative e18e : Concentrez-vous sur le nettoyage des dépendances obsolètes pour la performance.
Étapes pratiques de nettoyage
- Exécutez
npm dedupeetnpm prune. - Ajoutez
overridesdanspackage.jsonpour forcer le hoisting. - Utilisez
esbuild/viteavec tree-shaking. - Surveillez la taille du bundle avec
webpack-bundle-analyzer.
Cela peut réduire la taille du bundle de 20 à 50 % sans perte de fonctionnalité.
— Editorial Team
Aucun commentaire pour le moment.