Metro Bundler: cos’è, il bundling di progetto e principio di funzionamento

Autore: IT Sectr Pubblicato: 2026-07-06 Tempo di lettura: 8 min

Metro Bundler è un bundler JavaScript specializzato di Meta, sviluppato esclusivamente per React Native e incluso nel cuore del framework. Secondo la documentazione ufficiale di React Native 0.76 (2025), Metro fornisce build incrementali con Fast Refresh e risoluzione dei moduli con estensioni specifiche della piattaforma .native.js, .ios.js e .android.js. A differenza di Webpack, Metro non utilizza una cache del grafo dei moduli a lungo termine — invece ricostruisce il grafo ogni volta che i file cambiano, offrendo Hot Reload istantaneo durante lo sviluppo.

Punti chiave

  • Metro Bundler — il bundler JavaScript ufficiale di React Native con supporto per estensioni specifiche della piattaforma
  • Fast Refresh — ricaricamento a caldo con preservazione dello stato dei componenti alla modifica del codice
  • Haste Module System — sistema di ID modulo stabili per build incrementali
  • Estensioni di piattaforma — .native.js, .ios.js, .android.js per la separazione del codice per piattaforma
  • Hermes bytecode — modalità di build direttamente in bytecode per il motore Hermes

Cos’è Metro Bundler

Metro Bundler è un bundler JavaScript open source sviluppato da Meta per React Native e utilizzato per impostazione predefinita in tutti i progetti del framework. Il compito di Metro è prendere il codice JavaScript del progetto insieme alle dipendenze e raggrupparlo in uno o più bundle che vengono eseguiti sul dispositivo. A differenza dei bundler universali (Webpack, Rollup, Parcel), Metro è ottimizzato per le specificità dello sviluppo mobile: tempi di build minimi, aggiornamenti incrementali durante lo sviluppo e gestione corretta dei moduli di piattaforma (moduli nativi Objective-C, Swift, Java, Kotlin). Metro è incluso in React Native CLI e non richiede installazione separata. A partire da React Native 0.72, Metro versione 0.80+ supporta la transpilazione parallela dei moduli, accelerando le build su processori multi-core fino al 40%.

Architettura di Metro: Resolver, Transformer e Bundler

L’architettura di Metro è suddivisa in tre componenti indipendenti: Resolver, Transformer e Bundler. Il Resolver è responsabile della ricerca e risoluzione dei moduli — legge le espressioni import/require, trova i file corrispondenti considerando le estensioni di piattaforma e restituisce percorsi assoluti. Il Transformer esegue la transpilazione: applica Babel con presets e plugins, trasforma JSX, TypeScript o Flow in JavaScript puro. Il Bundler è la fase finale: prende il grafo delle dipendenze dal Resolver e i file trasformati dal Transformer, poi li serializza in uno o più bundle (module bundles). La separazione in tre fasi consente a Metro di memorizzare nella cache i risultati di ogni fase: se solo un file è cambiato, il Resolver e il Bundler possono utilizzare la cache per i moduli rimanenti, offrendo un aumento della velocità di build fino a 10 volte in modalità sviluppo.

Resolver: risoluzione dei moduli e ricerca consapevole della piattaforma

Il Resolver in Metro implementa un algoritmo di risoluzione dei moduli parzialmente compatibile con la risoluzione dei moduli di Node.js. La differenza chiave rispetto a Node.js è il supporto per le estensioni di piattaforma: require(‘./Component’) cerca Component.native.js, Component.ios.js, Component.android.js nell’ordine di priorità specificato. Il Resolver supporta anche il campo package.json “react-native” per mappare i moduli a implementazioni alternative — questo è il meccanismo standard per le librerie con codice specifico della piattaforma. Se un file non viene trovato, il Resolver genera un errore con lo stack di ricerca completo.

Transformer: Babel e transpilazione

Il Transformer all’interno di Metro utilizza Babel con il preset metro-react-native-babel-preset. La configurazione standard include: trasformazione di JSX in React.createElement, supporto TypeScript (rimozione dei tipi), supporto Flow e polyfill per gli standard JavaScript moderni (async/await, optional chaining, nullish coalescing). Il Transformer funziona in modalità parallela: ogni modulo viene transpilato indipendentemente, utilizzando un pool di processi worker (per impostazione predefinita, il numero corrisponde al numero di CPU). A partire da Metro 0.80, è supportato Granular Transformer Cache — invalidamento della cache a livello di singolo file.

Estensioni specifiche della piattaforma in Metro

Una delle caratteristiche principali di Metro è il supporto per le estensioni di file di piattaforma. Un progetto React Native può contenere tre versioni dello stesso modulo: Component.ios.js (iOS), Component.android.js (Android) e Component.native.js (entrambe le piattaforme). Durante l’importazione di require(‘./Component’), il Resolver seleziona automaticamente la versione corretta in base alla piattaforma di build target. Ciò consente di scrivere codice dipendente dalla piattaforma senza costrutti condizionali Platform.OS. Ordine di priorità: nome.piattaforma.js > nome.native.js > nome.js. L’estensione .native.js viene utilizzata per codice comune che funziona su entrambe le piattaforme ma è incompatibile con il web. Le estensioni .ios.js e .android.js servono per implementare funzionalità specifiche — navigazione, gesti, operazioni del file system. Metro supporta estensioni personalizzate tramite la configurazione resolver.sourceExts.

js
// metro.config.js — configurazione di sourceExts e watchFolders
const config = {
  resolver: {
    sourceExts: ['jsx', 'js', 'tsx', 'ts', 'json'],
    platformExtensions: ['ios', 'android', 'native'],
  },
  transformer: {
    babelTransformerPath: require('metro-react-native-babel-transformer'),
  },
  watchFolders: [path.resolve('../shared')],
};

Hot Reload e Fast Refresh in Metro

Fast Refresh è un meccanismo di ricaricamento a caldo per React Native costruito sopra Metro. Quando uno sviluppatore modifica un file, Metro ri-transpila solo il modulo modificato e invia l’aggiornamento all’app tramite WebSocket. Fast Refresh aggiorna l’interfaccia senza ricaricare l’intera applicazione e preserva lo stato dei componenti React se solo JSX o stili sono stati modificati. Se viene modificato codice con hook o stato, Fast Refresh rimonta solo il componente modificato. Metro supporta due modalità: Hot Module Replacement (HMR) per la sostituzione dei moduli al volo e Live Reload per il ricaricamento completo dell’applicazione quando cambiano moduli nativi o configurazione. Fast Refresh è abilitato per impostazione predefinita in React Native 0.76 e non richiede configurazione aggiuntiva — basta eseguire npx react-native start.

ModalitàVelocitàPreserva statoInnesco
Fast Refresh200-500msModifica file JS/TS
HMR100-300msModifica CSS/stili
Live Reload1-3sNoModifica config nativa
Full Rebuild10-60sNoModifica podspec/build.gradle

Configurazione di Metro: metro.config.js

Il file metro.config.js è il file di configurazione di Metro situato nella radice di un progetto React Native. In esso si configurano: resolver (sourceExts, platformExtensions, extraNodeModules), transformer (babelTransformerPath, minifierConfig), server (port, host, enableFastRefresh) e watcher (watchFolders, healthCheck). La configurazione standard di Metro eredita dal pacchetto @react-native/metro-config (React Native 0.76+). Per progetti con monorepository, aggiungete watchFolders — ciò consente a Metro di tracciare le modifiche nei pacchetti al di fuori della radice del progetto. Per configurare sourceExts, aggiungete ‘svg’, ‘png’, ‘gql’ per trasformatori personalizzati. Metro supporta configurazioni asincrone tramite async function — utile per la generazione dinamica della configurazione basata sull’ambiente.

Ottimizzazione della build tramite configurazione

L’ottimizzazione delle build di Metro inizia con una corretta configurazione della cache. Impostate maxWorkers al numero di CPU meno 1. Per le distribuzioni, utilizzate resetCache su CI. Minimizzate sourceExts — le estensioni extra rallentano la risoluzione dei moduli. Per progetti grandi, configurate watchFolders solo per le directory necessarie. Metro supporta la minificazione Hermes bytecode, che produce una dimensione del bundle inferiore rispetto al Terser standard — utilizzate minifierPath: ‘metro-minify-terser’.

Hermes bundling: build in bytecode

Metro supporta una modalità di build direttamente in Hermes bytecode — saltando la fase AST di JavaScript. Durante la build con HermesTransformer, i moduli vengono compilati in HBC (Hermes ByteCode) invece che in JavaScript semplice. Ciò offre: dimensione del bundle inferiore (30-40%), avvio dell’applicazione più veloce (20-30%) e consumo di memoria ridotto. Per abilitare, impostate hermesCommand in metro.config.js e attivate il flag Hermes in build.gradle (Android) o Podfile (iOS). La build del bundle Hermes viene eseguita in due fasi: prima Metro costruisce il bundle JavaScript, poi Hermes CLI lo converte in HBC. A partire da React Native 0.70, Hermes è il motore predefinito su Android, su iOS richiede un’attivazione esplicita.

Metro vs Webpack: confronto degli approcci

La differenza tra Metro e Webpack è dovuta a obiettivi diversi. Webpack è un bundler universale per il web con un enorme ecosistema di plugin e loader. Metro è un bundler specializzato per React Native dove la priorità è la velocità di build incrementale e il corretto funzionamento con i moduli nativi. Webpack utilizza un grafo di moduli a lungo termine con invalidamento intelligente della cache — ciò offre ricostruzioni rapide sul web ma crea problemi con le estensioni di piattaforma. Metro non memorizza nella cache il grafo tra le build, ma lo costruisce ogni volta — ciò semplifica la gestione delle estensioni di piattaforma e dei moduli Haste. Webpack supporta import dinamici con chunk, Metro anche — tramite React.lazy() e Suspense, ma con il limite di una richiesta attiva. L’ecosistema di Metro è significativamente più piccolo: non esiste un sostituto per style-loader, css-loader, file-loader — questi compiti vengono risolti diversamente in React Native.

Quando scegliere Metro

Metro è l’unica scelta corretta per i progetti React Native. Webpack non supporta la risoluzione consapevole della piattaforma nativamente, e configurare React Native con Webpack richiede uno sforzo significativo (haul bundler, expo web packager). Metro è integrato in React Native CLI, supportato dal team ufficiale di Meta e riceve aggiornamenti con ogni release di React Native. Per i progetti React Native Web, potete utilizzare Webpack per le build web mantenendo Metro per i bundle mobili.

Domande frequenti

Come pulire la cache di Metro Bundler?

Eseguite npx react-native start --reset-cache o eliminate la cartella $TMPDIR/metro-* e la directory .metro-health-check* nella radice del progetto. In alternativa: npx react-native clean — questo comando pulisce tutti i file temporanei di Metro, inclusi cache Babel e mappa Haste. Dopo la pulizia, la prima build sarà completa (60-120 secondi), ma le build incrementali successive torneranno alla velocità normale.

Perché Metro non vede un modulo da node_modules?

Verificate che il pacchetto sia nelle dependencies di package.json (non devDependencies). Se il modulo si trova in un monorepository, aggiungete il percorso a watchFolders in metro.config.js. Metro non segue i symlink per impostazione predefinita — utilizzate resolver.extraNodeModules per il mapping esplicito. Per Yarn PnM, impostate resolver.useWatchman: false. Se il modulo utilizza estensioni di piattaforma, assicuratevi che i file .ios.js o .android.js esistano nel percorso specificato.

Come velocizzare la build di Metro in un progetto grande?

Aumentate maxWorkers in metro.config.js al numero di CPU meno 1. Configurate watchFolders solo per le directory necessarie. Utilizzate Hermes bytecode per le build di produzione — accelera la build finale saltando la minificazione JS. Per lo sviluppo, abilitate Fast Refresh (è abilitato per impostazione predefinita). Limitate sourceExts solo alle estensioni necessarie. Considerate la suddivisione del bundle in chunk tramite lazy loading.

Si può usare Metro per progetti web?

Tecnicamente sì, ma non è consigliato. Metro non è ottimizzato per build web: non c’è supporto per CSS, HTML, immagini come moduli, né code splitting con import dinamici a livello di browser. Per il web, utilizzate Webpack, Vite o Parcel. Metro è una soluzione specializzata per React Native, e tentare di adattarlo per il web porterà a perdite di prestazioni e mancanza dell’ecosistema di loader.

In cosa Metro si differenzia da Re.Pack?

Re.Pack è uno strumento comunitario per sostituire Metro con Webpack nei progetti React Native. Fornisce accesso all’ecosistema di loader Webpack (css-loader, svg-loader) e al code splitting avanzato. Tuttavia, Re.Pack è più complesso da configurare, non è ufficialmente supportato da Meta e non garantisce compatibilità con le nuove versioni di React Native. Metro rimane l’unico bundler ufficialmente supportato, offrendo stabilità e compatibilità garantita con ogni release.

Riepilogo

  • Metro Bundler — il bundler JavaScript ufficiale di React Native con architettura Resolver-Transformer-Bundler
  • Estensioni di piattaforma (.ios.js, .android.js, .native.js) — caratteristica chiave per la separazione del codice per piattaforma
  • Fast Refresh — ricaricamento a caldo con preservazione dello stato dei componenti, funziona via WebSocket
  • Configurazione tramite metro.config.js: sourceExts, watchFolders, maxWorkers per l’ottimizzazione della build
  • Hermes bytecode — modalità di build in bytecode per avvio più veloce e dimensione del bundle ridotta
  • Resolver utilizza Haste Module System e risoluzione consapevole della piattaforma — incompatibile con Webpack
  • Transformer funziona in parallelo tramite Babel con un pool di processi worker
  • Metro è incluso in React Native CLI e non richiede installazione o configurazione separata per iniziare

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche