Tree Shaking: qué es, mecanismo de eliminación de código muerto y herramientas

Autor: IT Sectr Publicado: 2026-05-18 Tiempo de lectura: 8 min

Tree Shaking es un mecanismo para eliminar código no utilizado (dead code elimination) en la etapa de compilación de la aplicación. Tree Shaking analiza la estructura estática de los módulos ES y excluye funciones, clases y variables exportadas que no se importan en ningún lugar. Según la Documentación de Webpack, una configuración correcta de Tree Shaking puede reducir el tamaño del bundle entre un 30 y un 60% sin cambiar la funcionalidad de la aplicación.

Puntos clave

  • Tree Shaking — eliminación de exportaciones no utilizadas de módulos ES basada en análisis estático de import/export
  • Módulos ES (import/export) — el único formato compatible con Tree Shaking; CommonJS no es compatible
  • Webpack y Rollup — los principales bundlers con soporte de Tree Shaking mediante plugins
  • Side effects — los efectos secundarios en los módulos bloquean Tree Shaking; la bandera sideEffects: false en package.json resuelve el problema
  • Used exports — análisis del uso de exportaciones en modo producción de Webpack para la eliminación precisa de código muerto

¿Qué es Tree Shaking?

Tree Shaking es una técnica de optimización de código que excluye módulos y funciones no utilizados del bundle final. El término fue introducido por el equipo de Rollup en 2015 y describe metafóricamente el proceso: se sacude el árbol de dependencias y las ramas no utilizadas caen. A diferencia de la optimización manual, Tree Shaking se ejecuta automáticamente en la etapa de compilación.

Tree Shaking solo funciona con módulos ES (ECMAScript Modules), donde las dependencias se determinan estáticamente mediante import y export. CommonJS (require/module.exports) no es compatible con Tree Shaking porque require se ejecuta dinámicamente — el bundler no puede determinar de antemano qué funciones se utilizan realmente. Las bibliotecas modernas (Lodash, Moment.js, RxJS) lanzan versiones ES para permitir Tree Shaking.

Rollup: pionero de Tree Shaking

Rollup fue el primer bundler en implementar Tree Shaking en 2015. A diferencia de Webpack, Rollup fue diseñado desde el principio para módulos ES y realiza una eliminación de código muerto más agresiva. Rollup analiza no solo exportaciones individuales sino módulos enteros: si un módulo no tiene efectos secundarios y no se utiliza ninguna exportación, Rollup excluye todo el módulo del bundle.

Rollup es especialmente efectivo para bibliotecas y SDK donde cada kilobyte importa. El framework Vue.js usa Rollup para compilar su versión de producción. React migró a Rollup en 2020. Para aplicaciones, Webpack se usa más comúnmente debido a su ecosistema más rico de plugins (Hot Module Replacement, code splitting, CSS modules), pero para un Tree Shaking máximo al compilar bibliotecas, Rollup sigue siendo el estándar de la industria.

El ahorro de Tree Shaking depende en gran medida de la arquitectura del proyecto. En una aplicación React con la biblioteca Ant Design, Tree Shaking puede eliminar hasta el 70% del código de componentes UI. En un proyecto donde todas las importaciones son específicas y dirigidas, el ahorro será del 5 al 15%. Según las investigaciones de Webpack, el ahorro medio es del 30 al 40% del tamaño del bundle.

Qué es el código muerto

Tipo de código muertoEjemploDetección de Tree Shaking
Exportación no utilizadaexport function unusedHelper()
Importación no utilizadaimport { unused } from "lib"
Rama de condición muertaif (false) { ... }No (eliminada por el minificador)
Función no llamada después de DCEfunction a(){} a() donde a no es llamadaParcialmente

Cómo funciona Tree Shaking: análisis estático de módulos

El mecanismo de Tree Shaking se basa en un grafo de dependencias que el bundler construye a partir de todas las declaraciones import/export del proyecto. En la primera etapa, el bundler recorre todos los archivos desde el punto de entrada y recopila el árbol de módulos. En la segunda etapa, analiza qué exportaciones de cada módulo se importan realmente en otros módulos.

Para cada módulo, Webpack o Rollup marca las exportaciones como usadas o no usadas. Las exportaciones no usadas se excluyen del bundle. Sin embargo, el módulo en sí permanece en el bundle si al menos una de sus exportaciones se utiliza. Un módulo solo se puede excluir completamente mediante la bandera sideEffects o si el módulo no contiene ningún efecto secundario.

Ejemplo: antes y después de Tree Shaking

js
// utils.js — módulo con funciones
export function formatDate(date) {
  return date.toISOString().slice(0, 10);
}

export function formatCurrency(amount) {
  return "$" + amount.toFixed(2);
}

export function slugify(text) {
  return text.toLowerCase().replace(/\s+/g, "-");
}
js
// app.js — punto de entrada
import { formatDate } from "./utils";

const today = formatDate(new Date());
console.log(today);
js
// Después de Tree Shaking — solo formatDate en el bundle
function formatDate(date) {
  return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);

Tree Shaking excluyó formatCurrency y slugify del bundle final porque no se importan en app.js. El tamaño del módulo utils.js se redujo de 3 funciones a 1. Si utils.js contiene efectos secundarios (por ejemplo, inicialización global), Tree Shaking no puede eliminar ni siquiera las exportaciones no utilizadas.

Tree Shaking en Webpack: configuración y optimización

Webpack incluye soporte integrado de Tree Shaking a través de TerserPlugin en modo producción. Para habilitar Tree Shaking, dos condiciones son suficientes: mode está configurado en production (mode: "production") y los módulos usan sintaxis ES (import/export). Webpack marca automáticamente las exportaciones no utilizadas y las pasa a Terser para su eliminación.

La configuración adicional de usedExports: true en optimization.webpack.config.js habilita el análisis detallado del uso de exportaciones dentro de un módulo. Esta opción determina qué exportaciones se utilizan realmente y cuáles solo se exportan (provided). La combinación de usedExports y Terser proporciona la máxima eficiencia de eliminación de código muerto.

Configuración de Webpack para Tree Shaking

js
// webpack.config.js — configuración de Tree Shaking
module.exports = {
  mode: "production",
  entry: "./src/app.js",
  output: {
    filename: "bundle.js",
  },
  optimization: {
    usedExports: true,
    minimize: true,
    concatenateModules: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!(my-lib)\/).*/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              ["@babel/preset-env", { modules: false }],
            ],
          },
        },
      },
    ],
  },
};

El parámetro clave es modules: false en @babel/preset-env. Por defecto, Babel transforma los módulos ES a CommonJS, lo que mata Tree Shaking. modules: false evita que Babel transforme import/export, preservando la sintaxis ES para Webpack. concatenateModules además fusiona módulos en un ámbito compartido, reduciendo el número de IIFE y disminuyendo el tamaño del bundle.

El problema de los side effects y la bandera sideEffects

Los side effects (efectos secundarios) son acciones que un módulo realiza al ser importado y que no están relacionadas con los valores exportados: estilos globales (import "./styles.css"), polyfills (import "core-js/stable"), inicialización de variables globales o registro de Service Worker. Si un módulo contiene efectos secundarios, el bundler no puede eliminarlo del bundle de forma segura, incluso si no se utiliza ninguna de sus exportaciones.

La bandera sideEffects en package.json le indica al bundler qué módulos del paquete no tienen efectos secundarios. Para un paquete donde todos los módulos son puros (solo exportaciones de funciones), se debe especificar "sideEffects": false. Para paquetes con CSS o polyfills, una matriz de rutas a archivos con efectos secundarios: "sideEffects": ["*.css"]. Sin esta bandera, Tree Shaking no eliminará ni siquiera las funciones no utilizadas.

Cómo identificar efectos secundarios en tu código

Para verificar si un módulo tiene efectos secundarios, hazte esta pregunta: ¿esta importación realizará alguna acción no relacionada con la exportación de valores? import "./styles.css" agrega CSS al DOM — eso es un efecto secundario. import { throttle } from "lodash-es" no tiene efectos secundarios — solo hace disponible la función throttle. Los polyfills (import "core-js/stable") tienen efectos secundarios — modifican prototipos globales.

Para tus propios módulos, se recomienda: extraer estilos y polyfills en puntos de entrada separados, separar utilidades puras (funciones sin efectos secundarios) de módulos con efectos secundarios (inicialización, registro, registro de Service Worker). En el package.json del proyecto de nivel superior, especificar "sideEffects": false solo si todos los módulos son puros. Si hay estilos, especificar "sideEffects": ["*.css"] con precisión.

Ejemplo de configuración de sideEffects

json
{
  "name": "my-ui-lib",
  "version": "2.1.0",
  "sideEffects": [
    "*.css",
    "polyfills.js"
  ],
  "module": "dist/index.esm.js",
  "main": "dist/index.cjs.js"
}

"sideEffects": ["*.css", "polyfills.js"] significa: todos los archivos CSS tienen efectos secundarios (no se pueden eliminar) y polyfills.js también. Todos los demás archivos JS en el paquete son puros — se pueden sacudir de forma segura. El campo module especifica la ruta a la versión ES del paquete que el bundler debe usar en lugar de la versión CommonJS (main) para Tree Shaking.

Tree Shaking en React Native y Metro

React Native con Metro Bundler admite una versión limitada de Tree Shaking. Metro no realiza un análisis estático completo de las exportaciones utilizadas (usedExports) como Webpack. En su lugar, Metro se basa en Terser para eliminar partes no utilizadas de los módulos durante la minificación. La efectividad de este enfoque es menor que la de Tree Shaking completo en Webpack.

Para una optimización máxima de los proyectos de React Native, se recomienda: usar bibliotecas con módulos ES (campo module en package.json), agregar babel-plugin-transform-remove-console para eliminar código de depuración y configurar Metro transformer.minifierConfig para Terser. Además, Ram Bundle (división del bundle en módulos) reduce la carga de pantallas no utilizadas.

Preguntas frecuentes

¿Por qué Tree Shaking no funciona con CommonJS?

CommonJS (require/module.exports) no admite análisis estático — require puede llamarse dinámicamente dentro de condiciones y funciones. El bundler no puede determinar qué partes del módulo se utilizan realmente. Solo los módulos ES con import/export estático permiten Tree Shaking.

¿Se puede usar Tree Shaking con TypeScript?

TypeScript es totalmente compatible con Tree Shaking siempre que tsconfig.json esté configurado para módulos ES: "module": "esnext". El compilador de TypeScript debe conservar import/export sin convertirlos a CommonJS. Babel con @babel/preset-typescript y modules: false también pasa correctamente los módulos ES a Webpack.

¿Cómo verificar si Tree Shaking funcionó?

Webpack Bundle Analyzer es un plugin que visualiza la composición del bundle como un diagrama interactivo. Si una biblioteca está presente en el bundle pero sus funciones no se utilizan, Tree Shaking no funcionó. También puedes analizar el archivo de salida: busca exportaciones no utilizadas en el texto del bundle mediante grep.

¿Por qué Lodash no se tree-shakea por defecto?

Lodash v4 se distribuye como un paquete CommonJS. Para Tree Shaking, debes usar lodash-es, la versión ES de la biblioteca. Reemplaza import throttle from "lodash/throttle" por import { throttle } from "lodash-es" y configura resolve.alias en Webpack para reemplazar lodash por lodash-es.

¿Tree Shaking afecta el tiempo de compilación?

Tree Shaking aumenta ligeramente el tiempo de compilación (entre un 5 y un 15%) porque agrega una etapa de análisis del grafo de dependencias y marcado de exportaciones utilizadas. En modo development, Tree Shaking generalmente está desactivado por velocidad. En producción, el tiempo adicional se justifica por una reducción significativa del tamaño del bundle.

Resumen

  • Tree Shaking — eliminación automática de exportaciones ES no utilizadas en la compilación, reduciendo el tamaño del bundle entre un 30 y un 60%
  • Módulos ES — el único formato que admite análisis estático; CommonJS no es adecuado para Tree Shaking
  • Webpack y Rollup proporcionan Tree Shaking mediante usedExports y Terser en modo producción
  • Los side effects bloquean la eliminación de módulos; la bandera sideEffects: false en package.json resuelve el problema para bibliotecas puras
  • Babel debe configurarse con modules: false para evitar convertir módulos ES a CommonJS
  • React Native Metro tiene Tree Shaking limitado, basándose en Terser en la etapa de minificación

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también