Metro Bundler е специализиран JavaScript пакетировчик от Meta, разработен изключително за React Native и влизащ в ядрото на рамката. Според официалната документация на React Native 0.76 (2025), Metro осигурява инкрементално изграждане с Fast Refresh и разрешаване на модули, като взема предвид платформените разширения .native.js, .ios.js и .android.js. За разлика от Webpack, Metro не използва дълготраен кеш на module graph — вместо това той преизгражда графа всеки път при промяна на файлове, което дава незабавен Hot Reload по време на разработка.
Основни точки
Metro Bundler е JavaScript пакетировчик с отворен код, разработен от Meta за React Native и използван по подразбиране във всички проекти на рамката. Задачата на Metro е да вземе JavaScript кода на проекта заедно със зависимостите и да изгради един или повече пакета, които се изпълняват на устройството. За разлика от универсалните пакетировчици (Webpack, Rollup, Parcel), Metro е оптимизиран за спецификата на мобилното разработване: минимално време за изграждане, инкрементални актуализации по време на разработка и правилна работа с платформени модули (родни модули Objective-C, Swift, Java, Kotlin). Metro се доставя в състава на React Native CLI и не изисква отделна инсталация. От React Native 0.72 нататък, Metro версия 0.80+ поддържа паралелна транспилация на модули, което ускорява изграждането на многоядрени процесори до 40%.
Архитектурата на Metro е разделена на три независими компонента: Resolver, Transformer и Bundler. Resolver отговаря за търсене и разрешаване на модули — чете import/require изрази, намира съответните файлове, като взема предвид платформените разширения, и връща абсолютни пътища. Transformer извършва транспилация: прилага Babel с preset-ове и plugin-ове, преобразува JSX, TypeScript или Flow в чист JavaScript. Bundler е крайният етап: приема графа на зависимостите от Resolver и трансформираните файлове от Transformer, след което ги сериализира в един или повече пакета (module bundles). Разделянето на три стъпки позволява на Metro да кешира резултатите от всеки етап: ако само един файл се е променил, Resolver и Bundler могат да използват кеша за останалите модули, което дава увеличение на скоростта на изграждане до 10 пъти в режим на разработка.
Resolver в Metro имплементира алгоритъм за разрешаване на модули, частично съвместим с Node.js module resolution. Ключовата разлика от Node.js — поддръжка за платформени разширения: require('./Component') търси Component.native.js, Component.ios.js, Component.android.js в определения приоритетен ред. Resolver също поддържа полето package.json "react-native" за картографиране на модули към алтернативни имплементации — това е стандартният механизъм за библиотеки с платформен код. Ако файлът не бъде намерен, Resolver хвърля грешка с пълния стек за търсене.
Transformer вътре в Metro използва Babel с preset metro-react-native-babel-preset. Стандартната конфигурация включва: преобразуване на JSX в React.createElement, поддръжка на TypeScript (премахване на типове), поддръжка на Flow и polyfill за съвременни JavaScript стандарти (async/await, optional chaining, nullish coalescing). Transformer работи в паралелен режим: всеки модул се транспилира независимо, използвайки пул от работни процеси (по подразбиране броят съответства на броя CPU). От Metro 0.80 нататък се поддържа Granular Transformer Cache — инвалидиране на кеш на ниво отделен файл.
Една от ключовите характеристики на Metro е поддръжката на платформени файлови разширения. React Native проект може да съдържа три версии на един модул: Component.ios.js (iOS), Component.android.js (Android) и Component.native.js (и двете платформи). При импорт на require('./Component') Resolver автоматично избира правилната версия в зависимост от целевата платформа за изграждане. Това позволява писане на код, зависим от платформата, без условни конструкции Platform.OS. Редът на приоритет: име.платформа.js > име.native.js > име.js. Разширението .native.js се използва за общ код, работещ на двете платформи, но несъвместим с уеб. Разширенията .ios.js и .android.js служат за имплементиране на специфични функции — навигация, жестове, работа с файлова система. Metro поддържа персонализирани разширения чрез конфигурация resolver.sourceExts.
// metro.config.js — настройка на sourceExts и 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 е механизмът за горещо презареждане на React Native, имплементиран върху Metro. Когато разработчик промени файл, Metro транспилира отново само променения модул и изпраща актуализацията до приложението чрез WebSocket. Fast Refresh актуализира интерфейса без презареждане на цялото приложение и запазва React състоянието на компонентите, ако са променени само JSX или стилове. Ако е променен код с hooks или състояние, Fast Refresh извършва повторно монтиране само на променения компонент. Metro поддържа два режима: Hot Module Replacement (HMR) за подмяна на модули на място и Live Reload за пълно презареждане на приложението при промяна на родни модули или конфигурация. Fast Refresh е активиран по подразбиране в React Native 0.76 и не изисква допълнителна конфигурация — достатъчно е да стартирате npx react-native start.
| Режим | Скорост | Запазва състояние | Задействане |
|---|---|---|---|
| Fast Refresh | 200-500ms | Да | Промяна на JS/TS файлове |
| HMR | 100-300ms | Да | Промяна на CSS/стилове |
| Live Reload | 1-3s | Не | Промяна на native config |
| Full Rebuild | 10-60s | Не | Промяна на podspec/build.gradle |
metro.config.js е конфигурационният файл на Metro, намиращ се в корена на React Native проекта. В него се конфигурират: resolver (sourceExts, platformExtensions, extraNodeModules), transformer (babelTransformerPath, minifierConfig), server (port, host, enableFastRefresh) и watcher (watchFolders, healthCheck). Стандартната конфигурация на Metro се наследява от пакета @react-native/metro-config (React Native 0.76+). За проекти с монорепозиторий добавете watchFolders — това ще позволи на Metro да следи промени в пакети извън корена на проекта. За конфигуриране на sourceExts добавете 'svg', 'png', 'gql' за персонализирани трансформатори. Metro поддържа асинхронни конфигурации чрез async function — това е полезно за динамично генериране на конфигурация на базата на средата.
Оптимизацията на изграждане на Metro започва с правилна конфигурация на кеша. Задайте maxWorkers на броя CPU минус 1. За дистрибуции използвайте resetCache на CI. Минимизирайте sourceExts — допълнителни разширения забавят разрешаването на модули. За големи проекти конфигурирайте watchFolders само на необходимите директории. Metro поддържа Hermes bytecode minification, който дава по-малък размер на пакета от стандартния Terser — използвайте minifierPath: 'metro-minify-terser'.
Metro поддържа режим на изграждане директно в Hermes bytecode — пропускайки етапа JavaScript AST. При изграждане с HermesTransformer модулите се компилират в HBC (Hermes ByteCode) вместо обикновен JavaScript. Това дава: по-малък размер на пакета (с 30-40%), по-бързо стартиране на приложението (с 20-30%) и по-малка консумация на памет. За активиране задайте hermesCommand в metro.config.js и активирайте флага Hermes в build.gradle (Android) или Podfile (iOS). Изграждането на Hermes пакети се извършва в два етапа: първо Metro изгражда JavaScript пакета, след това Hermes CLI го конвертира в HBC. От React Native 0.70 нататък, Hermes е двигателят по подразбиране на Android, на iOS изисква изрично активиране.
Разликата между Metro и Webpack се дължи на различни цели. Webpack е универсален пакетировчик за уеб с огромна екосистема от plugin-ове и loader-и. Metro е специализиран пакетировчик за React Native, където приоритетът е скоростта на инкрементално изграждане и правилната работа с родни модули. Webpack използва дълготраен граф от модули с интелигентно инвалидиране на кеш — това дава бързи преизграждания в уеб, но създава проблеми с платформени разширения. Metro не кешира графа между изгражданията, а го изгражда всеки път — това опростява обработката на платформени разширения и Haste модули. Webpack поддържа динамични импорти с парчета, Metro също — чрез React.lazy() и Suspense, но с ограничение за една активна заявка. Екосистемата на Metro е значително по-малка: няма заместител за style-loader, css-loader, file-loader — тези задачи се решават по различен начин в React Native.
Metro е единственият правилен избор за React Native проекти. Webpack не поддържа platform-aware resolution веднага, а конфигурирането на React Native с Webpack изисква значителни усилия (haul bundler, expo web packager). Metro е интегриран в React Native CLI, поддържа се от официалния екип на Meta и получава актуализации с всяко издание на React Native. За React Native Web проекти можете да използвате Webpack за уеб изграждане, като запазите Metro за мобилни пакети.
Често задавани въпроси
Стартирайте npx react-native start --reset-cache или изтрийте папката $TMPDIR/metro-* и директорията .metro-health-check* в корена на проекта. Алтернативно: npx react-native clean — тази команда изчиства всички временни файлове на Metro, включително кеша на Babel и Haste картата. След изчистването първото изграждане ще бъде пълно (60-120 секунди), но следващите инкрементални изграждания ще се върнат към нормална скорост.
Проверете наличието на пакета в package.json dependencies (не devDependencies). Ако модулът е в монорепозиторий, добавете пътя в watchFolders в metro.config.js. Metro не следва симлинкове по подразбиране — използвайте resolver.extraNodeModules за изрично картографиране. За Yarn PnM задайте resolver.useWatchman: false. Ако модулът използва платформени разширения, уверете се, че файловете .ios.js или .android.js съществуват на посочения път.
Увеличете maxWorkers в metro.config.js на броя CPU минус 1. Конфигурирайте watchFolders само на необходимите директории. Използвайте Hermes bytecode за продукционни изграждания — това ускорява окончателното изграждане чрез пропускане на JS минификация. За разработка включете Fast Refresh (включен е по подразбиране). Ограничете sourceExts само до необходимите разширения. Обмислете разделяне на пакета на парчета чрез lazy loading.
Технически да, но не се препоръчва. Metro не е оптимизиран за уеб изграждания: няма поддръжка за CSS, HTML, изображения като модули, няма code splitting с динамичен импорт на ниво браузър. За уеб използвайте Webpack, Vite или Parcel. Metro е специализирано решение за React Native и опитът за адаптирането му за уеб ще доведе до загуба на производителност и липса на екосистема от loader-и.
Re.Pack е инструмент на общността за замяна на Metro с Webpack в React Native проекти. Той предоставя достъп до екосистемата от Webpack loader-и (css-loader, svg-loader) и разширено code splitting. Въпреки това, Re.Pack е по-сложен за конфигуриране, не се поддържа официално от Meta и не гарантира съвместимост с новите версии на React Native. Metro остава единственият официално поддържан пакетировчик, което дава стабилност и гаранция за съвместимост с всяко издание.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също