Command Palette

Search for a command to run...

Tree Shaking en JavaScript

Aprende qué es el tree shaking, cómo funciona y cómo configurarlo para optimizar el tamaño de tus bundles eliminando código no utilizado.

Lectura: 14 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Tree shaking elimina código no utilizado del bundle final
  • Funciona analizando el grafo de dependencias en tiempo de compilación
  • Las funciones puras sin side effects pueden ser eliminadas completamente
  • ES Modules facilitan el tree shaking con su sistema de exportaciones
  • La configuración de production mode activa optimizaciones de tree shaking

Introducción al Tree Shaking

Tree shaking es una técnica de optimización que elimina código no utilizado (dead code) del bundle final. El término proviene de la analogía de sacudir un árbol para que caigan las hojas muertas (código no usado). Esta técnica es fundamental para reducir el tamaño de los bundles y mejorar el rendimiento de las aplicaciones web modernas.

Antes de ES Modules y los bundlers modernos, los desarrolladores debían incluir bibliotecas enteras en sus bundles, incluso si solo usaban una pequeña parte. Tree shaking resuelve este problema analizando el código en tiempo de compilación y eliminando automáticamente todo aquello que nunca se ejecuta.

¿Qué es Tree Shaking?

Tree shaking es el proceso de eliminar código no utilizado del bundle final durante la compilación. El bundler analiza las dependencias del código, identifica qué exportaciones se usan y cuáles no, y elimina todo el código que nunca se ejecuta. Esto reduce significativamente el tamaño del bundle sin afectar la funcionalidad. El término fue popularizado por Rollup, un bundler JavaScript. La analogía es que al sacudir un árbol, las hojas muertas (código no usado) caen, dejando solo el código vivo y necesario.

biblioteca-completa.js
Loading code...

Este ejemplo muestra una biblioteca con múltiples funciones. Si tu aplicación solo usasumar y restar, las otras 8 funciones (multiplicar, dividir, etc.) son código muerto que puede eliminarse mediante tree shaking.

uso-parcial.js
Loading code...

Este ejemplo muestra cómo usar solo las funciones que necesitas de la biblioteca. Al importar solo sumar y restar, el bundler puede eliminar las otras funciones del bundle final, reduciendo su tamaño significativamente.

Impacto en el tamaño

Tree shaking puede reducir el tamaño del bundle entre un 30% y un 60%, dependiendo de cuánto código no utilizado elimines. Esto se traduce en tiempos de carga más rápidos y mejor experiencia de usuario, especialmente en conexiones lentas.

Cómo funciona Tree Shaking

Tree shaking funciona mediante el análisis estático del código en tiempo de compilación. El bundler construye un grafo de dependencias donde cada módulo es un nodo y cada import es una arista. Luego analiza este grafo para identificar qué código es necesario y cuál es código muerto.

Análisis estático de código

El análisis estático es la clave del tree shaking. El bundler examina el código sin ejecutarlo, identificando patrones que indican qué código se usa y cuál no. Este análisis es más preciso que el análisis dinámico en tiempo de ejecución.

analisis-estatico.js
Loading code...

Este ejemplo muestra cómo el bundler analiza el código estáticamente. AunquefuncionNoUsada está definida en el código, nunca se llama desde ningún lugar. El bundler identifica esto mediante el análisis de flujo de datos y puede eliminarla del bundle final. Es importante entender que el bundler analiza el flujo de datos del código, no la estructura sintáctica. Si una función nunca se llama, su código es código muerto independientemente de cómo esté escrita.

Side Effects y Pure Functions

Las side effects son efectos secundarios que ocurren cuando se ejecuta una función, como modificar variables globales, escribir en el DOM o hacer peticiones HTTP. Las funciones puras son aquellas que no tienen side effects y solo dependen de sus argumentos.

side-effects.js
Loading code...

Este ejemplo muestra la diferencia entre funciones con side effects y funciones puras.funcionConSideEffects modifica una variable global, por lo que no puede eliminarse mediante tree shaking. funcionPura no tiene side effects y puede eliminarse si no se usa.

Advertencia sobre side effects

Las funciones con side effects no pueden eliminarse mediante tree shaking porque pueden tener efectos invisibles. Si tu código tiene side effects, el bundler debe conservarlo incluso si parece que no se usa. Esto puede causar que código innecesario se incluya en el bundle final.

Tree Shaking en ES Modules

ES Modules facilitan significativamente el tree shaking mediante su sistema de exportaciones explícitas. A diferencia de CommonJS donde todo el código se ejecuta y es difícil determinar qué se usa, ES Modules permiten un análisis estático preciso de las dependencias.

es-modules-tree-shaking.js
Loading code...

Este ejemplo muestra cómo ES Modules facilitan el tree shaking. Las exportaciones explícitas (export) permiten al bundler analizar exactamente qué código se usa desde cada módulo. Las importaciones estáticas (import) permiten construir un grafo de dependencias preciso.

Ventaja de ES Modules

ES Modules son superiores a CommonJS para tree shaking porque permiten un análisis estático preciso de las dependencias. Las importaciones estáticas se analizan en tiempo de compilación, no en tiempo de ejecución, lo que permite eliminar código muerto con mayor precisión.

Configuración de Tree Shaking

La mayoría de los bundlers modernos tienen tree shaking activado por defecto en modo producción, pero puedes configurarlo manualmente para optimizar aún más tus bundles. La configuración varía según el bundler que estés usando.

Configuración en Webpack

Webpack tiene tree shaking integrado mediante su optimizador Terser. Puedes configurar el nivel de optimización y habilitar o deshabilitar tree shaking según tus necesidades específicas.

webpack-tree-shaking.js
Loading code...

Este ejemplo muestra cómo configurar tree shaking en Webpack. La opciónusedExports permite a Terser analizar qué exportaciones se usan y eliminar las no utilizadas. El nivel de optimización controla cuán agresivo es el tree shaking.

Configuración en Rollup

Rollup está diseñado específicamente para tree shaking y lo tiene activado por defecto. Su algoritmo de tree shaking es uno de los más agresivos y efectivos del ecosistema JavaScript.

rollup-tree-shaking.js
Loading code...

Este ejemplo muestra cómo configurar tree shaking en Rollup. La opcióntreeshake controla si se debe eliminar código no utilizado.moduleSideEffects permite especificar qué módulos tienen side effects y deben conservarse incluso si no se usan explícitamente.

Configuración en Vite

Vite usa Rollup en modo producción, por lo que hereda su potente sistema de tree shaking. En desarrollo, Vite usa esbuild para transformación rápida, pero el tree shaking se aplica en el build de producción.

vite-tree-shaking.js
Loading code...

Este ejemplo muestra cómo configurar tree shaking en Vite. La opciónbuild.rollupOptions.treeshake controla la agresividad del tree shaking. build.rollupOptions.moduleSideEffects permite especificar qué módulos tienen side effects.

Mejores prácticas para Tree Shaking

Para maximizar los beneficios del tree shaking, debes escribir código que facilite el análisis estático y evite side effects innecesarios. Estas prácticas te ayudarán a crear bundles más pequeños y eficientes.

  • <strong>Usa exportaciones nombradas</strong>: Facilita el análisis de dependencias
  • <strong>Escribe funciones puras</strong>: Evita side effects innecesarios
  • <strong>Evita efectos secundarios globales</strong>: No modifiques variables globales
  • <strong>Usa importaciones estáticas</strong>: Permite análisis en tiempo de compilación
  • <strong>Minimiza el uso de require dinámico</strong>: Dificulta el análisis estático

Patrón de diseño

Diseña tus módulos para que cada exportación tenga una responsabilidad única. Esto facilita el tree shaking porque el bundler puede eliminar módulos enteros si ninguna de sus exportaciones se usa. El principio de "un módulo, una responsabilidad" es clave para tree shaking efectivo.

Limitaciones de Tree Shaking

Aunque tree shaking es una técnica poderosa, tiene limitaciones que debes conocer. Comprender estas limitaciones te ayudará a evitar frustraciones y configurar tu código correctamente para maximizar los beneficios.

Limitación con código dinámico

El tree shaking no funciona con código que se carga dinámicamente, como conrequire() o import() dinámico. El análisis estático no puede determinar qué código se usará en tiempo de ejecución.

limitacion-dinamico.js
Loading code...

Este ejemplo muestra la limitación del tree shaking con código dinámico. La funcióncargarModulo usa require() dinámico, por lo que el bundler no puede analizar estáticamente qué módulos se cargarán. Todo el código en el directorio plugins/ debe incluirse en el bundle.

Advertencia importante

El tree shaking solo funciona con importaciones estáticas. Si usas require()dinámico o import() dinámico, el bundler no puede eliminar código de esos módulos porque no puede determinar en tiempo de compilación si se usarán.

Limitación con side effects

Las funciones con side effects no pueden eliminarse mediante tree shaking, incluso si parecen que no se usan. Esto puede causar que código innecesario se incluya en el bundle final, aumentando su tamaño.

limitacion-side-effects.js
Loading code...

Este ejemplo muestra la limitación del tree shaking con side effects. AunqueconfigurarModulos nunca se llama, tiene side effects (modifica una variable global) por lo que no puede eliminarse. El bundler debe conservarla para evitar errores en tiempo de ejecución.

Resumen: Tree Shaking

Conceptos principales:

  • Tree shaking elimina código no utilizado del bundle final
  • Funciona mediante análisis estático del grafo de dependencias
  • Las funciones puras sin side effects pueden eliminarse completamente
  • ES Modules facilitan tree shaking con exportaciones explícitas
  • El modo de producción activa optimizaciones de tree shaking
  • Los bundlers modernos activan tree shaking por defecto en producción

Mejores prácticas:

  • Usa exportaciones nombradas para facilitar el análisis
  • Escribe funciones puras sin side effects innecesarios
  • Evita require dinámico que dificulta el análisis estático
  • Configura moduleSideEffects para módulos con efectos secundarios
  • Usa herramientas de análisis para verificar el tree shaking
  • Diseña módulos con responsabilidad única para facilitar el tree shaking