Volver al inicio

Hinchazón de Dependencias npm: 3 Causas y Soluciones

El artículo desglosa tres razones para el crecimiento de las dependencias npm: soporte para entornos legacy, arquitectura atómica y ponyfills obsoletos. Describe problemas de duplicación, riesgos en la cadena de suministro y recomendaciones de limpieza. Material dirigido a desarrolladores middle/senior.

Tres Razones para la 'Hinchazón' de las Dependencias npm en JS
Advertisement 728x90

Por qué se inflan los árboles de dependencias de npm: Tres razones clave

Los árboles de dependencias en proyectos JavaScript a menudo crecen debido a paquetes obsoletos y funciones redundantes de la plataforma. Esto conlleva costes de descarga innecesarios, conflictos de versiones y vulnerabilidades en la cadena de suministro. Exploremos tres escenarios típicos que explican esta situación y cómo solucionarlos.

Compatibilidad con entornos heredados y problemas específicos del ámbito

Muchos paquetes como is-string o hasown existen para compatibilidad con entornos de ejecución antiguos, como ES3 (IE6/7, Node.js temprano). Implementan métodos faltantes: Array.prototype.forEach, Array.prototype.reduce, Object.keys, Object.defineProperty.

Motivaciones adicionales:

Google AdInline article slot
  • Protección del espacio de nombres global: Node importa primordiales (p. ej., Map) para evitar roturas por sobrescrituras. Paquetes como math-intrinsics reexportan Math.* con fines similares.
  • Compatibilidad entre ámbitos: instanceof no funciona entre un iframe y su padre (diferentes constructores de RegExp). Una alternativa es Object.prototype.toString.call(val) === '[object RegExp]', como se usa en chai o is-string para new String(val).
const shebangRegex = /^#!(.*)/;
export default shebangRegex;

Para la mayoría de desarrolladores de nivel medio a senior, esto es excesivo: Node moderno (no más antiguo de 10 años) y los navegadores no requieren tales trucos. Recomendación: revisa tu browserslist y elimina polyfills innecesarios.

Arquitectura atómica: De la teoría a los problemas

La filosofía de los paquetes 'atómicos' implica dividir el código en bloques mínimos para su reutilización. Un ejemplo es el grafo de dependencias de execa con paquetes como shebang-regex (5 líneas de código).

Utilidades atómicas típicas:

Google AdInline article slot
  • arrify: Array.isArray(val) ? val : [val]
  • slash: normalización de barras en rutas
  • cli-boxes: JSON con bordes de elementos de interfaz
  • path-key: env['PATH'] || env['Path']
  • onetime: llamada única a función
  • is-wsl: process.platform === 'linux' && /microsoft/.test(os.release())
  • is-windows: process.platform === 'win32

En teoría, esto simplifica la construcción de CLI. En la práctica:

  • Uso único: shebang-regex solo lo usa shebang-command (mismo autor); cli-boxes — solo boxen/ink.
  • Duplicados por elevación: En nuxt, duplicados como is-docker, is-stream, is-wsl (2 versiones cada uno). Duplicar código en línea es gratis, sin sobrecarga de npm.
  • Riesgos en la cadena de suministro: Más paquetes significan más vulnerabilidades. Comprometer a un mantenedor (como ocurrió el año pasado) afectó a cientos de dependencias.

Solución: incluir funciones simples en línea, usar tree-shaking y pnpm con elevación estricta.

Ponyfills que han sobrevivido a su época

Los ponyfills son polyfills sin mutar globales, importados directamente. Útiles para bibliotecas: @fastly/performance-observer-polyfill permite usar PerformanceObserver sin alterar el entorno.

Google AdInline article slot

Problema: no se eliminan tras llegar el soporte nativo.

Ejemplos de ponyfills obsoletos (con descargas semanales):

  • globalthis — para globalThis (soportado desde 2019, 49M descargas/semana)
  • indexof — para Array.prototype.indexOf (desde 2010, 2.3M/semana)
  • object.entries — para Object.entries (desde 2017, 35M/semana)

En eslint-plugin-react, la mitad del grafo consiste en polyfills heredados. Para bibliotecas: confía en polyfills del lado del consumidor (core-js). Consulta caniuse.com antes de añadir.

Conclusiones clave

  • Optimiza lo heredado: El 90% de los paquetes no necesitan polyfills ES3/ES5; usa typeof en lugar de is-string.
  • La atomicidad perjudica: Incluye funciones de 5 líneas en línea para reducir duplicados y superficie de ataque.
  • Audita ponyfills: Elimina paquetes para funciones soportadas >5 años en el entorno objetivo.
  • Herramientas: Usa npm ls --depth=0, depcheck, npm-check-updates para análisis.
  • Iniciativa e18e: Enfócate en limpiar dependencias obsoletas para rendimiento.

Pasos prácticos de limpieza

  • Ejecuta npm dedupe y npm prune.
  • Añade overrides a package.json para elevación forzada.
  • Usa esbuild/vite con tree-shaking.
  • Monitorea el tamaño del bundle con webpack-bundle-analyzer.

Esto puede reducir el tamaño del bundle en un 20-50% sin perder funcionalidad.

— Editorial Team

Advertisement 728x90

Leer después