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:
- Protección del espacio de nombres global: Node importa primordiales (p. ej.,
Map) para evitar roturas por sobrescrituras. Paquetes comomath-intrinsicsreexportanMath.*con fines similares. - Compatibilidad entre ámbitos:
instanceofno funciona entre un iframe y su padre (diferentes constructores deRegExp). Una alternativa esObject.prototype.toString.call(val) === '[object RegExp]', como se usa enchaiois-stringparanew 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:
arrify:Array.isArray(val) ? val : [val]slash: normalización de barras en rutascli-boxes: JSON con bordes de elementos de interfazpath-key:env['PATH'] || env['Path']onetime: llamada única a funciónis-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-regexsolo lo usashebang-command(mismo autor);cli-boxes— soloboxen/ink. - Duplicados por elevación: En
nuxt, duplicados comois-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.
Problema: no se eliminan tras llegar el soporte nativo.
Ejemplos de ponyfills obsoletos (con descargas semanales):
globalthis— paraglobalThis(soportado desde 2019, 49M descargas/semana)indexof— paraArray.prototype.indexOf(desde 2010, 2.3M/semana)object.entries— paraObject.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
typeofen lugar deis-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-updatespara análisis. - Iniciativa e18e: Enfócate en limpiar dependencias obsoletas para rendimiento.
Pasos prácticos de limpieza
- Ejecuta
npm dedupeynpm prune. - Añade
overridesapackage.jsonpara elevación forzada. - Usa
esbuild/vitecon 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
Aún no hay comentarios.