Metro é um bundler JavaScript desenvolvido especificamente para React Native e usado por padrão para compilar aplicativos móveis nesta plataforma. Ao contrário dos bundlers universais, o Metro é otimizado para os recursos limitados de dispositivos móveis e fornece integração com o motor Hermes e Fast Refresh. De acordo com Metro Documentation (2026), o bundler lida com mais de 90% dos projetos React Native no mundo.
Principais pontos
Metro é um bundler JavaScript de código aberto criado pela equipe da Meta para React Native. Ele substituiu o Packager das versões anteriores do React Native e se tornou a ferramenta de compilação padrão para esta plataforma. O Metro não foi projetado para desenvolvimento web: sua arquitetura é focada exclusivamente em aplicativos móveis executados nos motores JavaScript JSC (JavaScriptCore) ou Hermes.
Metro surgiu em 2018 como substituto do antigo React Native Packager. A principal razão para sua criação foi a necessidade de um bundler que funcionasse eficientemente com milhões de módulos em grandes aplicativos móveis. Ao contrário do Webpack, o Metro não suporta CSS, HTML ou imagens como módulos — esses recursos são tratados por ferramentas separadas do React Native. O Facebook usa o Metro para compilar seu aplicativo principal, que contém mais de 100 mil arquivos.
O Metro é distribuído via npm como pacote metro e é instalado automaticamente com o React Native CLI. A versão do Metro está vinculada à versão do React Native, portanto, a atualização do bundler ocorre junto com a atualização da plataforma.
Metro recebe como entrada o ponto de entrada da aplicação, constrói um grafo de dependências, transforma cada módulo e serializa o resultado em um único bundle. O processo passa por três fases: Resolve (resolução de módulos), Transform (transformação) e Serialize (serialização).
// Exemplo de configuração do Metro para transformação personalizada
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);
};
},
},
};
Na fase Resolve, o Metro determina a localização de cada módulo importado, levando em conta aliases e node_modules. Na fase Transform, cada arquivo passa por um transformador Babel para converter JSX, TypeScript e outras extensões em JavaScript puro. A fase final Serialize coleta todos os módulos transformados em um ou mais arquivos bundle.
Metro é construído sobre uma arquitetura modular onde cada etapa de compilação é implementada como um componente independente. Isso permite substituir módulos padrão por personalizados sem alterar o núcleo do bundler. A arquitetura do Metro inclui três pacotes principais: metro, metro-config e metro-resolver.
Metro Server — um servidor de desenvolvimento que inicia com o comando npx react-native start. Ele atende solicitações de transformação de módulos em tempo real, fornecendo Fast Refresh. Module Store — um cache que armazena módulos transformados em memória para acelerar recompilações. Dependency Graph — um grafo de dependências que é atualizado incrementalmente quando os arquivos mudam.
Watchman — um observador de arquivos da Meta que o Metro usa para detectar alterações no sistema de arquivos. Sem o Watchman, o Metro precisa escanear toda a estrutura de arquivos a cada mudança, o que retarda significativamente o desenvolvimento. A instalação do Watchman é obrigatória para trabalhar confortavelmente com o Metro em projetos de qualquer tamanho.
A configuração do Metro é definida no arquivo metro.config.js na raiz do projeto. Um arquivo típico define pastas adicionais para busca de módulos, listas de bloqueio para excluir arquivos desnecessários e transformadores personalizados. No React Native 0.72+, é usada a detecção automática de configuração, mas para monorepos a configuração é obrigatória.
// 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 exclui arquivos de teste da compilação, reduzindo o tamanho do bundle. nodeModulesPaths especifica caminhos adicionais para busca de pacotes — crítico para monorepos. extraNodeModules cria aliases para pacotes compartilhados usados em diferentes projetos do monorepo.
Metro fornece vários mecanismos para otimizar o tamanho do bundle e a velocidade de compilação. Inline Requires — a técnica mais eficaz, que converte importações de nível superior em chamadas require locais dentro de funções. RAM bundles permitem carregar módulos incrementalmente. Hermes compila JavaScript em bytecode, reduzindo o tamanho da aplicação em 20–30%.
// metro.config.js — otimização para produção
const config = {
transformer: {
async transform({ src, filename, options }) {
const inlineRequires = options.dev ? false : true;
return await defaultTransform({ src, filename, options: { ...options, inlineRequires } });
},
},
serializer: {
polyfillModuleNames: [],
},
};
// Para habilitar o Hermes — no build.gradle (Android):
// project.ext.react = [enableHermes: true, bundleInRelease: true]
// Para iOS — no Podfile: :hermes_enabled => true
Para diagnóstico do tamanho do bundle, o Metro fornece a flag --bundle-output com saída de estatísticas. Use bundle-visualizer para analisar a composição do bundle e encontrar módulos grandes que podem ser carregados de forma preguiçosa. A verificação regular do tamanho do bundle deve fazer parte do pipeline CI/CD do projeto React Native.
Metro suporta delta bundles — um mecanismo onde, após a primeira compilação completa, o servidor envia apenas as alterações (delta) entre as versões antiga e nova do bundle. Isso acelera radicalmente as compilações subsequentes: o tempo de atualização cai de segundos para dezenas de milissegundos. Delta bundles são especialmente eficazes durante o desenvolvimento, quando o desenvolvedor salva alterações com frequência e recarrega a aplicação.
Para habilitar delta bundles no React Native, usa-se a flag --delta no comando npx react-native bundle. No lado do cliente, delta bundles são suportados a partir do React Native 0.64. Em compilações de produção, delta bundles não são usados — em vez disso, é usado um bundle completo com bytecode Hermes para máximo desempenho de inicialização. Isso é alcançado porque o ganho de velocidade no desenvolvimento compensa o custo da primeira compilação completa.
Hermes é um motor JavaScript desenvolvido pela Meta especificamente para React Native. O Metro gera bytecode Hermes durante a compilação, permitindo que a aplicação inicie sem uma compilação JavaScript cara no dispositivo. Para habilitar o Hermes, basta adicionar enableHermes: true no metro.config.js e configurar o build.gradle ou Podfile. O Hermes reduz o tempo de inicialização da aplicação em 30–50% e reduz o tamanho do APK em 20–30% em comparação com o JavaScriptCore.
Ao usar o Hermes, é importante lembrar das limitações: o motor não suporta Proxy, Reflect e alguns recursos do ES6. A maioria das aplicações React Native não usa esses recursos diretamente, mas algumas bibliotecas podem entrar em conflito. Antes de habilitar o Hermes, verifique a compatibilidade de todas as dependências do projeto através da lista de verificação oficial de compatibilidade. O Metro muda automaticamente para o modo de geração de bytecode quando o Hermes é ativado.
Para acompanhar a eficiência de compilação do Metro, use as métricas integradas disponíveis através do Flipper — a ferramenta de depuração do React Native. O Metro publica eventos: bundle_request, transform, resolve com tempo de execução de cada etapa. A análise desses dados ajuda a identificar gargalos: se a fase de transformação levar mais de 70% do tempo, o problema está no transformador Babel. Ative o registro de logs do Metro através da flag --verbose para diagnóstico detalhado.
Perguntas frequentes
Tecnicamente sim — existem projetos experimentais como react-native-webpack, mas eles não são suportados oficialmente. Metro está integrado com a bridge do React Native, Turbo Modules e Hermes em um nível inacessível para o Webpack. Substituir o Metro resultaria na perda do Fast Refresh e do suporte oficial.
React Native não usa CSS para estilização — em vez disso, a estilização JavaScript é aplicada através de StyleSheet.create. Como o Metro foi criado exclusivamente para React Native, o suporte a CSS não é necessário. Para renderização web através do React Native Web, o CSS é tratado por ferramentas separadas fora do Metro.
Metro não processa imagens ou fontes como módulos. Os recursos são importados via require('./image.png'), mas o Metro apenas os registra como dependências de string. O carregamento real de imagens é realizado pelo código nativo do React Native através do componente Image, e o Metro copia os recursos para o bundle.
Rollup gera módulos ES com tree shaking em nível de módulo, resultando em tamanho mínimo de bundle para bibliotecas. Metro gera um bundle CommonJS com transformação inline e otimização para motores móveis. Rollup não suporta Fast Refresh e não pode trabalhar com módulos nativos do React Native.
A compilação a frio do Metro é lenta devido à varredura completa de node_modules. Soluções: adicione watchFolders para monorepos, use maxWorkers para transformação paralela e instale Watchman. Para projetos com mais de 10.000 arquivos, considere metro-memory-fs para cache em memória.
Resumo
watchFolders e extraNodeModules para resolução correta de módulos.Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também