Metro Bundler este un bundler JavaScript specializat de la Meta, dezvoltat exclusiv pentru React Native și care face parte din nucleul framework-ului. Conform documentației oficiale React Native 0.76 (2025), Metro oferă construire incrementală cu Fast Refresh și rezolvarea modulelor ținând cont de extensiile de platformă .native.js, .ios.js și .android.js. Spre deosebire de Webpack, Metro nu folosește cache-ul de lungă durată module graph — în schimb reconstruiește graful de fiecare dată când fișierele se modifică, ceea ce oferă Hot Reload instantaneu în timpul dezvoltării.
Principalele puncte
Metro Bundler este un bundler JavaScript cu sursă deschisă, dezvoltat de Meta pentru React Native și folosit implicit în toate proiectele framework-ului. Sarcina Metro este de a lua codul JavaScript al proiectului împreună cu dependențele și de a construi unul sau mai multe bundle-uri care sunt executate pe dispozitiv. Spre deosebire de bundler-ii universali (Webpack, Rollup, Parcel), Metro este optimizat pentru specificul dezvoltării mobile: timp minim de construire, actualizări incrementale în timpul dezvoltării și funcționare corectă cu modulele de platformă (module native Objective-C, Swift, Java, Kotlin). Metro este livrat în cadrul React Native CLI și nu necesită instalare separată. Începând cu React Native 0.72, Metro versiunea 0.80+ suportă transpilarea paralelă a modulelor, ceea ce accelerează construirea pe procesoare multi-core cu până la 40%.
Arhitectura Metro este împărțită în trei componente independente: Resolver, Transformer și Bundler. Resolver se ocupă de căutarea și rezolvarea modulelor — citește expresiile import/require, găsește fișierele corespunzătoare ținând cont de extensiile de platformă și returnează căi absolute. Transformer efectuează transpilarea: aplică Babel cu preset-uri și plugin-uri, transformă JSX, TypeScript sau Flow în JavaScript pur. Bundler este etapa finală: primește graful de dependențe de la Resolver și fișierele transformate de la Transformer, apoi le serializează într-unul sau mai multe bundle-uri (module bundles). Împărțirea în trei etape permite Metro să cache-uiască rezultatele fiecărei etape: dacă s-a modificat un singur fișier, Resolver și Bundler pot folosi cache-ul pentru modulele rămase, ceea ce oferă o creștere a vitezei de construire de până la 10 ori în modul de dezvoltare.
Resolver în Metro implementează algoritmul de rezolvare a modulelor, parțial compatibil cu Node.js module resolution. Diferența cheie față de Node.js — suportul pentru extensii de platformă: require('./Component') caută Component.native.js, Component.ios.js, Component.android.js în ordinea de prioritate specificată. Resolver suportă și câmpul package.json "react-native" pentru maparea modulelor la implementări alternative — acesta este mecanismul standard pentru bibliotecile cu cod de platformă. Dacă fișierul nu este găsit, Resolver aruncă o eroare cu stiva completă de căutare.
Transformer în interiorul Metro folosește Babel cu preset-ul metro-react-native-babel-preset. Configurația standard include: transformarea JSX în React.createElement, suport pentru TypeScript (eliminarea tipurilor), suport pentru Flow și polyfill-uri pentru standardele moderne JavaScript (async/await, optional chaining, nullish coalescing). Transformer funcționează în mod paralel: fiecare modul este transpilat independent, folosind un pool de procese worker (implicit numărul corespunde numărului de CPU). Începând cu Metro 0.80, este suportat Granular Transformer Cache — invalidarea cache-ului la nivel de fișier individual.
Una dintre caracteristicile cheie ale Metro este suportul pentru extensii de fișiere de platformă. Un proiect React Native poate conține trei versiuni ale unui modul: Component.ios.js (iOS), Component.android.js (Android) și Component.native.js (ambele platforme). La importul require('./Component'), Resolver alege automat versiunea corectă în funcție de platforma țintă de construire. Acest lucru permite scrierea codului dependent de platformă fără construcții condiționale Platform.OS. Ordinea de prioritate: nume.platforma.js > nume.native.js > nume.js. Extensia .native.js este folosită pentru codul comun care funcționează pe ambele platforme, dar incompatibil cu web-ul. Extensiile .ios.js și .android.js servesc pentru implementarea caracteristicilor specifice — navigare, gesturi, lucrul cu sistemul de fișiere. Metro suportă extensii personalizate prin configurația resolver.sourceExts.
// metro.config.js — configurarea sourceExts și 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')],
};
Fast Refresh este mecanismul de reîncărcare la cald React Native implementat pe baza Metro. Când dezvoltatorul modifică un fișier, Metro retranspilează doar modulul modificat și trimite actualizarea către aplicație prin WebSocket. Fast Refresh actualizează interfața fără a reîncărca întreaga aplicație și păstrează starea componentelor React dacă s-au modificat doar JSX sau stilurile. Dacă s-a modificat codul cu hook-uri sau stare, Fast Refresh efectuează remontarea doar a componentului modificat. Metro suportă două moduri: Hot Module Replacement (HMR) pentru înlocuirea modulelor pe loc și Live Reload pentru reîncărcarea completă a aplicației la modificarea modulelor native sau a configurației. Fast Refresh este activat implicit în React Native 0.76 și nu necesită configurare suplimentară — este suficient să rulați npx react-native start.
| Mod | Viteză | Păstrează starea | Declanșator |
|---|---|---|---|
| Fast Refresh | 200-500ms | Da | Modificarea fișierelor JS/TS |
| HMR | 100-300ms | Da | Modificarea CSS/stilurilor |
| Live Reload | 1-3s | Nu | Modificarea native config |
| Full Rebuild | 10-60s | Nu | Modificarea podspec/build.gradle |
metro.config.js este fișierul de configurare Metro, situat în rădăcina proiectului React Native. În el se configurează: resolver (sourceExts, platformExtensions, extraNodeModules), transformer (babelTransformerPath, minifierConfig), server (port, host, enableFastRefresh) și watcher (watchFolders, healthCheck). Configurația standard Metro este moștenită de la pachetul @react-native/metro-config (React Native 0.76+). Pentru proiecte cu monorepozitoriu, adăugați watchFolders — acest lucru va permite Metro să urmărească modificările în pachetele din afara rădăcinii proiectului. Pentru configurarea sourceExts, adăugați 'svg', 'png', 'gql' pentru transformatoare personalizate. Metro suportă configurații asincrone prin async function — acest lucru este util pentru generarea dinamică a configurației pe baza mediului.
Optimizarea construirii Metro începe cu configurarea corectă a cache-ului. Setați maxWorkers la numărul de CPU minus 1. Pentru distribuții, utilizați resetCache pe CI. Minimizați sourceExts — extensiile suplimentare încetinesc rezolvarea modulelor. Pentru proiecte mari, configurați watchFolders doar pe directoarele necesare. Metro suportă Hermes bytecode minification, care oferă o dimensiune mai mică a bundle-ului decât Terser standard — utilizați minifierPath: 'metro-minify-terser'.
Metro suportă modul de construire direct în Hermes bytecode — sărind etapa JavaScript AST. La construirea cu HermesTransformer, modulele sunt compilate în HBC (Hermes ByteCode) în loc de JavaScript simplu. Acest lucru oferă: dimensiune mai mică a bundle-ului (cu 30-40%), pornire mai rapidă a aplicației (cu 20-30%) și consum mai mic de memorie. Pentru activare, setați hermesCommand în metro.config.js și activați flag-ul Hermes în build.gradle (Android) sau Podfile (iOS). Construirea bundle-urilor Hermes se realizează în două etape: mai întâi Metro construiește bundle-ul JavaScript, apoi Hermes CLI îl convertește în HBC. Începând cu React Native 0.70, Hermes este motorul implicit pe Android, pe iOS necesită activare explicită.
Diferența dintre Metro și Webpack se datorează obiectivelor diferite. Webpack este un bundler universal pentru web cu un ecosistem imens de plugin-uri și loadere. Metro este un bundler specializat pentru React Native, unde prioritatea este viteza construirii incrementale și funcționarea corectă cu modulele native. Webpack folosește un graf de module de lungă durată cu invalidare inteligentă a cache-ului — acest lucru oferă reconstruiri rapide pe web, dar creează probleme cu extensiile de platformă. Metro nu cache-uiește graful între construiri, ci îl construiește de fiecare dată — acest lucru simplifică procesarea extensiilor de platformă și a modulelor Haste. Webpack suportă importuri dinamice cu chunk-uri, Metro de asemenea — prin React.lazy() și Suspense, dar cu limitarea la o singură cerere activă. Ecosistemul Metro este semnificativ mai mic: nu există înlocuitor pentru style-loader, css-loader, file-loader — aceste sarcini se rezolvă altfel în React Native.
Metro este singura alegere corectă pentru proiectele React Native. Webpack nu suportă platform-aware resolution din cutie, iar configurarea React Native cu Webpack necesită eforturi semnificative (haul bundler, expo web packager). Metro este integrat în React Native CLI, este suportat de echipa oficială Meta și primește actualizări cu fiecare lansare React Native. Pentru proiectele React Native Web, puteți folosi Webpack pentru construirea web, păstrând Metro pentru bundle-urile mobile.
Întrebări frecvente
Rulați npx react-native start --reset-cache sau ștergeți folderul $TMPDIR/metro-* și directorul .metro-health-check* din rădăcina proiectului. Alternativ: npx react-native clean — această comandă șterge toate fișierele temporare Metro, inclusiv cache-ul Babel și harta Haste. După curățare, prima construire va fi completă (60-120 secunde), dar construiriile incrementale ulterioare vor reveni la viteza normală.
Verificați prezența pachetului în package.json dependencies (nu devDependencies). Dacă modulul se află într-un monorepozitoriu, adăugați calea în watchFolders din metro.config.js. Metro nu urmărește symlink-urile implicit — utilizați resolver.extraNodeModules pentru mapare explicită. Pentru Yarn PnM, setați resolver.useWatchman: false. Dacă modulul folosește extensii de platformă, asigurați-vă că fișierele .ios.js sau .android.js există în calea specificată.
Măriți maxWorkers în metro.config.js la numărul de CPU minus 1. Configurați watchFolders doar pe directoarele necesare. Utilizați Hermes bytecode pentru construiri de producție — acest lucru accelerează construirea finală prin omiterea minificării JS. Pentru dezvoltare, activați Fast Refresh (este activat implicit). Limitați sourceExts doar la extensiile necesare. Luați în considerare împărțirea bundle-ului în chunk-uri prin lazy loading.
Tehnic da, dar nu este recomandat. Metro nu este optimizat pentru construiri web: nu există suport pentru CSS, HTML, imagini ca module, nu există code splitting cu import dinamic la nivel de browser. Pentru web, folosiți Webpack, Vite sau Parcel. Metro este o soluție specializată pentru React Native, iar încercarea de a-l adapta pentru web va duce la pierderea performanței și lipsa ecosistemului de loadere.
Re.Pack este un instrument comunitar pentru înlocuirea Metro cu Webpack în proiectele React Native. Oferă acces la ecosistemul de loadere Webpack (css-loader, svg-loader) și la code splitting avansat. Cu toate acestea, Re.Pack este mai complex în configurare, nu este suportat oficial de Meta și nu garantează compatibilitatea cu noile versiuni React Native. Metro rămâne singurul bundler suportat oficial, ceea ce oferă stabilitate și garanția compatibilității cu fiecare lansare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și