Metro: что это, ключевые возможности и принцип работы

Автор: IT Sectr Опубликовано: 2026-05-19 Время чтения: 8 мин

Metro — бандлер JavaScript, разработанный специально для React Native и используемый по умолчанию для сборки мобильных приложений на этой платформе. В отличие от универсальных бандлеров, Metro оптимизирован под ограниченные ресурсы мобильных устройств и обеспечивает интеграцию с Hermes engine и Fast Refresh. По данным Metro Documentation (2026), бандлер обрабатывает более 90% React Native проектов в мире.

Главное

  • Metro — бандлер по умолчанию для React Native, оптимизированный для мобильной разработки под iOS и Android.
  • Трёхфазная архитектура Metro включает разрешение модулей, трансформацию и сериализацию в выходной бандл.
  • Fast Refresh — механизм горячей перезагрузки компонентов без потери состояния приложения.
  • Inline Requires откладывают загрузку модулей до момента их первого вызова, уменьшая стартовый бандл.
  • Hermes — JavaScript-движок от Meta, использующий Metro для генерации предварительно откомпилированного байт-кода.

Что такое Metro?

Metro — это бандлер JavaScript с открытым исходным кодом, созданный командой Meta для React Native. Он заменил Packager из ранних версий React Native и стал стандартным инструментом сборки для этой платформы. Metro не предназначен для веб-разработки: его архитектура ориентирована исключительно на мобильные приложения, работающие под управлением JavaScript-движков JSC (JavaScriptCore) или Hermes.

История создания и позиционирование

Metro появился в 2018 году как замена старому React Native Packager. Основная причина создания — необходимость в бандлере, который эффективно работает с миллионами модулей в крупных мобильных приложениях. В отличие от Webpack, Metro не поддерживает CSS, HTML или изображения как модули — эти ресурсы обрабатываются отдельными инструментами React Native. Facebook использует Metro для сборки своего основного приложения, которое содержит более 100 тысяч файлов.

Metro распространяется через npm как пакет metro и устанавливается автоматически вместе с React Native CLI. Версия Metro привязана к версии React Native, поэтому обновление бандлера происходит вместе с обновлением платформы.

Как работает бандлер Metro?

Metro получает на вход точку входа приложения, строит граф зависимостей, трансформирует каждый модуль и сериализует результат в единый бандл. Процесс проходит три фазы: Resolve (разрешение модулей), Transform (трансформация) и Serialize (сериализация).

Процесс сборки в Metro

js
// Пример конфигурации 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, metro-config и metro-resolver.

Ключевые компоненты Metro

Metro Server — dev-сервер, который запускается при команде npx react-native start. Он обслуживает запросы на трансформацию модулей в реальном времени, обеспечивая Fast Refresh. Module Store — кэш, хранящий трансформированные модули в памяти для ускорения повторных сборок. Dependency Graph — граф зависимостей, который обновляется инкрементально при изменении файлов.

Watchman — файловый наблюдатель от Meta, который Metro использует для обнаружения изменений в файловой системе. Без Watchman Metro приходится пересканировать всю файловую структуру при каждом изменении, что значительно замедляет разработку. Установка Watchman обязательна для комфортной работы с Metro на проектах любого размера.

Настройка Metro в React Native проекте

Конфигурация Metro задаётся в файле metro.config.js в корне проекта. Типовой файл определяет дополнительные папки для поиска модулей, блокировки для исключения ненужных файлов и кастомные трансформеры. В React Native 0.72+ используется автообнаружение конфигурации, но для монорепозиториев настройка обязательна.

Базовая конфигурация Metro для React Native

js
// 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

Metro предоставляет несколько механизмов для оптимизации размера бандла и скорости сборки. Inline Requires — наиболее эффективная техника, превращающая импорты на верхнем уровне в локальные require внутри функций. RAM bundles позволяют загружать модули инкрементально. Hermes компилирует JavaScript в байт-код, уменьшая размер приложения на 20–30%.

Включение Inline Requires и Hermes

js
// metro.config.js — оптимизация для production
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 проекта.

Delta Bundles и инкрементальная сборка

Metro поддерживает delta-бандлы — механизм, при котором после первой полной сборки сервер отправляет только изменения (дельта) между старой и новой версиями бандла. Это радикально ускоряет последующие сборки: время обновления сокращается с секунд до десятков миллисекунд. Delta-бандлы особенно эффективны на этапе разработки, когда разработчик часто сохраняет изменения и перезагружает приложение.

Для включения delta-бандлов в React Native используется флаг --delta в команде npx react-native bundle. На стороне клиента delta-бандлы поддерживаются начиная с React Native 0.64. В production-сборках delta-бандлы не применяются — вместо них используется полноценный бандл с Hermes-байткодом для максимальной производительности запуска. Это достигается за счёт того, что прирост скорости разработки компенсирует затраты на первую полную сборку.

Hermes и Metro: совместная работа

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

Для отслеживания эффективности сборки Metro используйте встроенные метрики, доступные через Flipper — инструмент отладки React Native. Metro публикует события: bundle_request, transform, resolve с временем выполнения каждого этапа. Анализ этих данных помогает выявить узкие места: если фаза transform занимает более 70% времени, проблема в Babel-трансформере. Включите ведение логов Metro через флаг --verbose для детальной диагностики.

Часто задаваемые вопросы

Можно ли заменить Metro на Webpack в React Native?

Технически да — существуют экспериментальные проекты вроде react-native-webpack, но они не поддерживаются официально. Metro интегрирован с React Native bridge, Turbo Modules и Hermes на уровне, недоступном для Webpack. Замена Metro приведёт к потере Fast Refresh и официальной поддержки.

Почему Metro не поддерживает CSS?

React Native не использует CSS для стилизации — вместо этого применяется JavaScript-стилизация через StyleSheet.create. Поскольку Metro создан эксклюзивно для React Native, поддержка CSS не нужна. Для веб-рендеринга через React Native Web CSS обрабатывается отдельными инструментами вне Metro.

Как Metro обрабатывает изображения и шрифты?

Metro не обрабатывает изображения или шрифты как модули. Ресурсы подключаются через require('./image.png'), но Metro лишь регистрирует их как строковые зависимости. Фактическая загрузка изображений выполняется нативным кодом React Native через Image компонент, а Metro копирует ресурсы в bundle.

Чем отличается Metro от Rollup?

Rollup генерирует ES-модули с tree shaking на уровне модулей, что даёт минимальный размер бандла для библиотек. Metro генерирует CommonJS-бандл с инлайн-трансформацией и оптимизацией под мобильные движки. Rollup не поддерживает Fast Refresh и не может работать с нативными модулями React Native.

Как ускорить холодную сборку Metro?

Холодная сборка Metro замедляется из-за полного сканирования node_modules. Решения: добавьте watchFolders для монорепозиториев, используйте maxWorkers для параллельной трансформации и установите Watchman. Для проектов с 10 000+ файлов рассмотрите metro-memory-fs для кэширования в памяти.

Итоги

  • Metro — стандартный бандлер React Native, оптимизированный для мобильных платформ с ограниченными ресурсами.
  • Трёхфазная архитектура (Resolve, Transform, Serialize) обеспечивает инкрементальную сборку и Fast Refresh.
  • Fast Refresh — горячая перезагрузка изменённых компонентов без потери состояния приложения.
  • Inline Requires откладывают загрузку модулей до первого вызова, уменьшая стартовый бандл на 15–30%.
  • Hermes — JavaScript-движок от Meta, компилирующий JS в байт-код через Metro для ускорения запуска.
  • Watchman — файловый наблюдатель, обязательный для комфортной работы Metro на проектах с большим количеством файлов.
  • Для монорепозиториев требуется настройка watchFolders и extraNodeModules для корректного разрешения модулей.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также