# Route-level code splitting: load only the code a page needs

Route-level code splitting splits the bundle into one file per page, so a first visit downloads only what it needs. How to set it up and what to measure.

> Page: https://ui.eneawork.it/blog/code-splitting-route
> Markdown: https://ui.eneawork.it/blog/code-splitting-route.md

*2026-11-01*

Il code splitting per route divide il bundle in un file per pagina, così la prima visita scarica solo il codice che le serve. Il build di questo sito produce 48 file JavaScript, ma la home ne richiede uno solo.

Il build del 1 novembre 2026, letto da client/dist/assets dopo npm run build, ha prodotto 48 file JavaScript per 523.037 byte, 176.211 in gzip, e 17 file CSS per 149.281 byte. L'entry index-D_hsgu54.js pesa 141.302 byte, 44.281 in gzip, e 46 chunk di route restano sotto i 25 KB. In produzione la home serve /assets/index-6WZgfxzm.js da 142.151 byte. Il catalogo EneUI misura 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026. Documentazione Vite, licenza MIT.

## Un import dinamico per route

import { lazy, Suspense } from "react"; const Components = lazy(() => import("./pages/Components")); const Blocks = lazy(() => import("./pages/Blocks")); export function Routes({ tab }) { return ( Loading}> {tab === "components" ? : } ); }

Ogni import() crea un punto di separazione: Vite emette un file per il modulo raggiunto solo da quel punto. Il codice condiviso da più route finisce nel chunk comune, non duplicato in ognuna.

## Quattro modi di spezzare

## Dove si vede il guadagno

L'entry non si restringe: resta a 141.302 byte perché contiene React e il router. Il guadagno è nei chunk che la home non richiede: Blocks pesa 22.130 byte e arriva solo quando apri quella pagina. Su una visita alla home il risparmio è la somma dei chunk che non scarichi.

## Il comando

npx vite build --mode production

L'output elenca ogni file con la dimensione in kB e scrive client/dist. Aggiungi --sourcemap quando devi capire quale modulo finisce in quale chunk.

## La limitazione

Le dimensioni del build non sono byte trasferiti: 48 file esistono su disco, ma una visita ne scarica pochi. Spezzare troppo crea round trip in più sulle route profonde, e un chunk duplicato pesa più dell'entry che volevi evitare. Leggi le richieste nel pannello Network, non la cartella dist.

## Dove continuare

Il catalogo EneUI indicizza 111.985 componenti e 1.556 blocchi con preview. Il record sidebar è un componente fatto di più file: importato staticamente finisce nell'entry. Per il peso di un singolo import leggi un import che aumenta il bundle, per la compressione Brotli contro gzip, per il confronto tra librerie il peso delle librerie UI, per la parte di CSS che blocca il paint il CSS critico.

## FAQ

### Che differenza c'è tra code splitting e tree shaking?

Il tree shaking toglie dal bundle il codice mai importato, il code splitting divide ciò che resta in file caricati su richiesta. Servono entrambi: il primo riduce il totale, il secondo riduce ciò che parte subito.

### Ogni route deve avere il suo file?

No. Conviene separare le route pesanti e quelle visitate di rado; una route da 3 KB non guadagna nulla da un file in più. Raggruppa le viste piccole e lascia un chunk per le grandi.

### Il chunk separato arriva prima o dopo il primo paint?

Dopo, perché il browser lo chiede quando il componente viene montato. Con React.lazy la richiesta parte al primo render della route, quindi il fallback di Suspense è ciò che l'utente vede nel frattempo.

### Come evito che una libreria finisca in più chunk?

Dichiara un gruppo manuale in build.rollupOptions.output.manualChunks per le dipendenze condivise. Rollup estrae il modulo in un chunk comune e ogni route lo importa da lì.

### Il code splitting peggiora le metriche di caricamento?

Può peggiorare l'LCP se il contenuto principale è dentro un chunk caricato tardi. Tieni nell'entry ciò che disegna il primo schermo e separa il resto.
