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 з presets та plugins, перетворює 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 з пресетом metro-react-native-babel-preset. Стандартна конфігурація включає: перетворення JSX в React.createElement, підтримку TypeScript (видалення типів), підтримку Flow та поліфіли для сучасних JavaScript-стандартів (async/await, optional chaining, nullish coalescing). Transformer працює в паралельному режимі: кожен модуль транспілюється незалежно, використовуючи пул worker-процесів (за замовчуванням кількість відповідає числу 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 оновлює UI без перезавантаження всього додатку і зберігає React-стан компонентів, якщо змінено тільки JSX або стилі. Якщо змінено код з хуками або станом, Fast Refresh виконує перемонтування тільки зміненого компонента. Metro підтримує два режими: Hot Module Replacement (HMR) для заміни модулів на льоту та Live Reload для повного перезавантаження додатку при зміні нативних модулів або конфігурації. Fast Refresh включений за замовчуванням в React Native 0.76 та не вимагає додаткового налаштування — достатньо запустити npx react-native start.
| Режим | Швидкість | Зберігає state | Тригер |
|---|---|---|---|
| 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) замість plain 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 — універсальний бандлер для веба з величезною екосистемою плагінів та лоадерів. Metro — спеціалізований бандлер для React Native, де пріоритет — швидкість інкрементальної збірки та коректна робота з нативними модулями. Webpack використовує довготривалий граф модулів з розумною інвалідацією кеша — це дає швидкі повторні збірки в вебі, але створює проблеми з платформеними розширеннями. Metro не кешує граф між збірками, а будує його кожного разу — це спрощує обробку платформених розширень та Haste модулів. Webpack підтримує динамічні імпорти з чанками, Metro — теж, через React.lazy() та Suspense, але з обмеженням на один активний requests. Екосистема 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 map. Після очищення перша збірка буде повною (60-120 секунд), але наступні інкрементальні збірки повернуться до нормальної швидкості.
Перевірте наявність пакета в package.json dependencies (не devDependencies). Якщо модуль знаходиться в монорепозиторії, додайте шлях в watchFolders metro.config.js. Metro не слідує symlinks за замовчуванням — використовуйте 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, і спроба адаптувати його під веб призведе до втрати продуктивності та відсутності екосистеми лоадерів.
Re.Pack — це community-інструмент для заміни Metro на Webpack в React Native проектах. Він дає доступ до екосистеми Webpack лоадерів (css-loader, svg-loader) та просунутого code splitting. Однак Re.Pack складніший в налаштуванні, не підтримується офіційно Meta та не гарантує сумісність з новими версіями React Native. Metro залишається єдиним офіційно підтримуваним бандлером, що дає стабільність та гарантію сумісності з кожним релізом.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також