Saltar al contenido

Analizar el bundle: chunks, dependencias y división

Leer el grafo de código que el build entrega: qué es un chunk y cómo Astro los agrupa, cómo visualizar el bundle en un treemap para descubrir dependencias pesadas escondidas, cómo trocear con dynamic import lo que solo hace falta a veces, y cómo aislar las librerías comunes en un chunk de vendor que se cachea entre páginas.

Anatomía de la salida: qué es un chunk

Un chunk es una unidad de código que el bundler decide agrupar y emitir junta. Astro, sobre Vite 8 y Rolldown, produce varios tipos: el runtime compartido de un framework, el código propio de cada isla, y los trozos que resultan de un import dinámico. Cada archivo lleva un hash de contenido en el nombre, y ese detalle no es cosmético: es lo que permite cachearlo para siempre, porque si el contenido cambia, cambia el nombre.

Shell
npm run build# dist/_astro/ agrupa los chunks con hash de contenido# client.9f2a1c.js     3.7 kB gzip   runtime compartido# Comentarios.4b8e0d.js 14.8 kB gzip  isla concreta# vendor.c1d7a9.js     38.2 kB gzip   librerias comunes

La clave conceptual es que el bundler intenta que el código compartido por varias páginas viva en un chunk común, para descargarlo una vez y reutilizarlo. Cuando dos páginas usan la misma isla, su código no se duplica: se emite en un trozo que ambas referencian. Entender esa lógica de agrupación es el primer paso para influir en ella.

Visualizar: el treemap no miente

La salida de texto dice cuánto pesa cada chunk, pero no qué lo infla. Para eso está el mapa de áreas, donde cada módulo es un rectángulo cuya superficie es proporcional a su peso. Un vistazo basta para que el culpable salte: casi siempre es un rectángulo enorme con el nombre de una dependencia que no esperabas tan cara.

Shell
npx vite-bundle-visualizer# abre un treemap navegable del bundle completo

import dinámico: cargar cuando hace falta

No todo el código de una isla se usa siempre. Un editor de texto enriquecido, un selector de emojis, una librería de gráficos: cosas caras que solo entran en juego tras una acción del usuario. El import dinámico —import() como función que devuelve una promesa— le dice al bundler que separe ese código en su propio chunk y lo descargue solo cuando se invoque.

TSX
export default function Nota() {  async function abrirEditor() {    // El editor pesado no viaja en la carga inicial:    // se descarga en su propio chunk al pulsar    const { montarEditor } = await import('./editor-pesado');    montarEditor();  }  return <button onClick={abrirEditor}>Editar</button>;}

El efecto sobre el presupuesto es directo: la isla se hidrata con un botón diminuto, y el peso grande solo llega si el visitante lo pide. Es la misma filosofía de las directivas perezosas —el coste que no se paga— llevada al interior de una isla, a la granularidad de una función.

Dividir el vendor con manualChunks

Por defecto el bundler decide la agrupación, pero a veces conviene guiarlo. Aislar las librerías de terceros —el vendor— en su propio chunk estable tiene una ventaja de caché: mientras tu código cambia en cada despliegue y renueva su hash, el vendor permanece idéntico y el navegador lo reutiliza de una visita a otra sin volver a descargarlo.

TypeScript
// astro.config.mjsimport { defineConfig } from 'astro/config';export default defineConfig({  vite: {    build: {      rollupOptions: {        output: {          manualChunks: {            vendor: ['react', 'react-dom'],          },        },      },    },  },});

Medir el coste antes de instalar

El mejor momento para analizar una dependencia no es después de que engorde el bundle, sino antes de añadirla. Cada npm install es una decisión de rendimiento disfrazada de comodidad, y conviene tomarla con el dato delante: cuánto pesa la librería una vez empaquetada, si permite importar solo una parte, y si arrastra dependencias propias.

Servicios como Bundlephobia estiman el peso gzip de un paquete y su efecto antes de instalarlo, y el propio treemap confirma después la realidad. La regla sana es tratar una dependencia de cliente como un cargo permanente: entra en el presupuesto y se paga en cada visita, así que su valor debe justificar su peso.

  • ¿Se puede importar solo la función que uso, o la librería es indivisible?
  • ¿Existe una alternativa nativa del navegador que evite la dependencia entera?
  • ¿Vive este trabajo mejor en el servidor, donde no cuesta nada al visitante?

Preguntarlo antes de instalar es más barato que arrepentirse después de desplegar. El análisis del bundle no es solo una autopsia que se hace al final; es también una prueba previa que evita el peso muerto antes de que exista.