Metro — је JavaScript бандлер развијен посебно за React Native и подразумевано кориштен за изградњу мобилних апликација на овој платформи. За разлику од универзалних бандлера, Metro је оптимизован за ограничене ресурсе мобилних уређаја и обезбеђује интеграцију са Hermes engine и Fast Refresh. Према Metro Documentation (2026), бандлер обрађује преко 90% React Native пројеката у свету.
Главно
Metro је JavaScript бандлер отвореног кода, креиран од стране Meta тима за React Native. Заменио је Packager из ранијих верзија React Native и постао стандардни алат за изградњу за ову платформу. Metro није намењен за веб развој: његова архитектура је оријентисана искључиво на мобилне апликације које раде под JSC (JavaScriptCore) или Hermes JavaScript погонским двигачима.
Metro се појавио 2018. године као замена за стари React Native Packager. Главни разлоз настанка била је потреба за бандлером који ефикасно ради са милионима модула у великим мобилним апликацијама. За разлику од Webpack-а, Metro не подржава CSS, HTML или слике као модуле — ови ресурси се обрађују од стране посебних React Native алата. Facebook користи Metro за изградњу своје главне апликације која садржи преко 100 хиљада датотека.
Metro се дистрибуира путем npm-а као пакет metro и инсталира се аутоматски заједно са React Native CLI. Верзија Metro-а је повезана са верзијом React Native-а, па се ажурирање бандлера дешава заједно са ажурирањем платформе.
Metro на улазу прима улазну тачку апликације, гради граф зависности, трансформише сваки модул и серијализује резултат у јединствени бандл. Процес пролази кроз три фазе: Resolve (решавање модула), Transform (трансформација) и Serialize (серијализација).
// Пример конфигурације Metro-а за прилагођену трансформацију
const metroConfig = {
transformer: {
babelTransformerPath: require('metro-babel-transformer'),
async transform({ src, filename, options }) {
const result = await babelTransform({ src, filename, options });
return {
ast: result.ast,
code: result.code,
map: result.map,
dependencies: [],
};
},
},
serializer: {
createModuleIdFactory() {
let nextId = 0;
const moduleIds = new Map();
return ({ path }) => {
if (!moduleIds.has(path)) {
moduleIds.set(path, nextId++);
}
return moduleIds.get(path);
};
},
},
};
У фази Resolve, Metro одређује локацију сваког импортованог модула, узимајући у обзир алијасе и node_modules. У фази Transform, свака датотека пролази кроз Babel трансформер за конверзију JSX, TypeScript и других екстензија у чисти JavaScript. Завршна фаза Serialize сакупља све трансформисане модуле у један или више бандл фајлова.
Metro је изграђен на модулној архитектури, где је свака фаза компилације имплементирана као посебан компонента. Ово омогућава замену стандардних модула прилагођеним без промене језгра бандлера. Архитектура Metro-а укључује три главна пакета: metro, metro-config и metro-resolver.
Metro Server — развојни сервер који се покреће командом npx react-native start. Он опслужује захтеве за трансформацију модула у реалном времену, обезбеђујући Fast Refresh. Module Store — кеш који чува трансформисане модуле у меморији ради убрзавања поновних компилација. Dependency Graph — граф зависности који се ажурира инкрементално при промени датотека.
Watchman — надзирач датотека од Meta-а који Metro користи за откривање промена у фајл систему. Без Watchman-а, Metro мора поново да скенира целокупну структуру датотека при свакој промени, што значајно успорава развој. Инсталација Watchman-а је обавезна за комфортан рад са Metro-ом на пројектима било које величине.
Подешавање Metro-а се дефинише у датотеци metro.config.js у корену пројекта. Типична датотека дефинише додатне фасцикле за претрагу модула, блокаде за искључивање непотребних датотека и прилагођене трансформере. У React Native 0.72+ користи се аутоматско откривање конфигурације, али за монорепозиторијуме је подешавање обавезно.
// metro.config.js
const config = {
resolver: {
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'],
nodeModulesPaths: ['node_modules'],
blockList: [/\.test\.js$/, /__tests__\/.*/],
extraNodeModules: {
'shared-components': path.resolve(__dirname, '../shared/src'),
},
},
transformer: {
minifierConfig: {
keep_classnames: true,
keep_fnames: true,
mangle: { reserved: ['React', 'Component'] },
},
},
};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
blockList искључује тестне датотеке из компилације, смањујући величину бандла. nodeModulesPaths указује додатне путање за претрагу пакета — критично за монорепозиторијуме. extraNodeModules креира алијасе за заједничке пакете који се користе у различитим пројектима монорепозиторијума.
Metro пружа више механизама за оптимизацију величине бандла и брзине компилације. Inline Requires — најефикаснија техника, која претвара импорте на највишем нивоу у локалне require унутар функција. RAM bundles омогућавају инкрементално учитавање модула. Hermes компилира JavaScript у бајт код, смањујући величину апликације за 20–30%.
// metro.config.js — оптимизација за производњу
const config = {
transformer: {
async transform({ src, filename, options }) {
const inlineRequires = options.dev ? false : true;
return await defaultTransform({ src, filename, options: { ...options, inlineRequires } });
},
},
serializer: {
polyfillModuleNames: [],
},
};
// За укључивање Hermes-а — у build.gradle (Android):
// project.ext.react = [enableHermes: true, bundleInRelease: true]
// За iOS — у Podfile: :hermes_enabled => true
За дијагностику величине бандла, Metro пружа заставицу --bundle-output са статистичким излазом. Користите bundle-visualizer за анализу састава бандла и проналажење великих модула који се могу лењено учитавати. Редовна провера величине бандла треба да буде део пипејна CI/CD React Native пројекта.
Metro подржава делта-бандлове — механизам при којем након прве пуне компилације сервер шаље само промјене (делта) између старе и нове верзије бандла. Ово радикално убрзава касније компилације: време ажурирања се смањује са секунди на десетине милисекунди. Делта-бандлови су посебно ефикасни у фази развоја, кад програмер често чува промене и поново учитава апликацију.
За укључивање делта-бандлова у React Native-у користи се заставица --delta у команди npx react-native bundle. На страни клијента, делта-бандлови су подржани од React Native 0.64. У производним компилацијама, делта-бандлови се не примењују — уместо њих користи се пуни бандл са Hermes бајт кодом за максималну перформансу покретања. Ово се постиже јер повећање брзине развоја компензира трошкове прве пуне компилације.
Hermes — JavaScript погонски двигач развијен од стране Meta-а посебно за React Native. Metro генерише Hermes бајт код у фази компилације, што омогућава апликацији да се покрене без скупе Компилације JavaScript-а на уређају. За укључивање Hermes-а довољно је додати enableHermes: true у metro.config.js и подесити build.gradle или Podfile. Hermes смањује време покретања апликације за 30–50% и величину APK-а за 20–30% у поређењу са JavaScriptCore.
Кад користите Hermes, важно је имати на уму ограничења: погонски двигач не подржава Proxy, Reflect и неке могућности ES6. Већина React Native апликација не користи ове могућности директно, али неке библиотеке могу бити у сукобу. Пре укључивања Hermes-а, проверите компатибилност свих зависности пројекта путем званичне листе компатибилности. Metro се аутоматски пребацује у режим генерације бајт кода при активацији Hermes-а.
За праћење ефикасности компилације Metro-а, користите уграђене метрике које су доступне путем Flipper-а — алата за отклањање React Native. Metro објављује догађаје: bundle_request, transform, resolve са временом извршења сваке фазе. Анализа ових података помаже да се идентификују уска грла: ако фаза transform заузима више од 70% времена, проблем је у Babel трансформеру. Укључите вођење Metro логова путем заставице --verbose за детаљну дијагностику.
Често постављана питања
Технички да — постоје експериментални пројекти попут react-native-webpack, али нису званично подржани. Metro је интегрисан са React Native bridge, Turbo Modules и Hermes на нивоу који је недоступан Webpack-у. Замена Metro-а ће довести до губитка Fast Refresh-а и званичне подршке.
React Native не користи CSS за стилизацију — уместо тога примењује се JavaScript стилизација путем StyleSheet.create. Пошто је Metro креиран искључиво за React Native, подршка за CSS није потребна. За веб рендеровање кроз React Native Web, CSS се обрађује посебним алатима изван Metro-а.
Metro не обрађује слике или фонтове као модуле. Ресурси се повезују путем require('./image.png'), али Metro их само региструје као низне зависности. Стварно учитавање слика обавља се нативним кодом React Native-а кроз Image компоненту, а Metro копира ресурсе у бандл.
Rollup генерише ES модуле са tree shaking-ом на нивоу модула, што даје минималну величину бандла за библиотеке. Metro генерише CommonJS бандл са inline трансформацијом и оптимизацијом за мобилне погонске двигаче. Rollup не подржава Fast Refresh и не може да ради са нативним модулима React Native-а.
Хладна компилација Metro-а је спора због пуног скенирања node_modules. Решења: додајте watchFolders за монорепозиторијуме, користите maxWorkers за паралелну трансформацију и инсталирајте Watchman. За пројекте са 10 000+ датотека, размотрите metro-memory-fs за кеширање у меморији.
Закључак
watchFolders и extraNodeModules за исправно решавање модула.Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође