Metro es un bundler de JavaScript desarrollado específicamente para React Native y utilizado por defecto para compilar aplicaciones móviles en esta plataforma. A diferencia de los bundlers universales, Metro está optimizado para los recursos limitados de los dispositivos móviles y proporciona integración con el motor Hermes y Fast Refresh. Según Metro Documentation (2026), el bundler maneja más del 90% de los proyectos React Native en el mundo.
Puntos clave
Metro es un bundler de JavaScript de código abierto creado por el equipo de Meta para React Native. Reemplazó al Packager de las versiones anteriores de React Native y se convirtió en la herramienta de compilación estándar para esta plataforma. Metro no está diseñado para el desarrollo web: su arquitectura está orientada exclusivamente a aplicaciones móviles que funcionan con los motores JavaScript JSC (JavaScriptCore) o Hermes.
Metro apareció en 2018 como reemplazo del antiguo React Native Packager. La razón principal de su creación fue la necesidad de un bundler que funcione eficientemente con millones de módulos en grandes aplicaciones móviles. A diferencia de Webpack, Metro no admite CSS, HTML ni imágenes como módulos — estos recursos se gestionan con herramientas separadas de React Native. Facebook utiliza Metro para compilar su aplicación principal, que contiene más de 100 mil archivos.
Metro se distribuye a través de npm como paquete metro y se instala automáticamente junto con React Native CLI. La versión de Metro está vinculada a la versión de React Native, por lo que la actualización del bundler ocurre junto con la actualización de la plataforma.
Metro recibe como entrada el punto de entrada de la aplicación, construye un grafo de dependencias, transforma cada módulo y serializa el resultado en un único bundle. El proceso pasa por tres fases: Resolve (resolución de módulos), Transform (transformación) y Serialize (serialización).
// Ejemplo de configuración de Metro para transformación 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);
};
},
},
};
En la fase Resolve, Metro determina la ubicación de cada módulo importado, teniendo en cuenta los alias y node_modules. En la fase Transform, cada archivo pasa por un transformador Babel para convertir JSX, TypeScript y otras extensiones a JavaScript puro. La fase final Serialize recoge todos los módulos transformados en uno o varios archivos bundle.
Metro está construido sobre una arquitectura modular donde cada etapa de compilación se implementa como un componente independiente. Esto permite reemplazar los módulos estándar por personalizados sin cambiar el núcleo del bundler. La arquitectura de Metro incluye tres paquetes principales: metro, metro-config y metro-resolver.
Metro Server — un servidor de desarrollo que se inicia con el comando npx react-native start. Gestiona las solicitudes de transformación de módulos en tiempo real, proporcionando Fast Refresh. Module Store — un caché que almacena los módulos transformados en memoria para acelerar las recompilaciones. Dependency Graph — un grafo de dependencias que se actualiza incrementalmente cuando los archivos cambian.
Watchman — un observador de archivos de Meta que Metro utiliza para detectar cambios en el sistema de archivos. Sin Watchman, Metro tiene que escanear toda la estructura de archivos en cada cambio, lo que ralentiza significativamente el desarrollo. La instalación de Watchman es obligatoria para trabajar cómodamente con Metro en proyectos de cualquier tamaño.
La configuración de Metro se define en el archivo metro.config.js en la raíz del proyecto. Un archivo típico define carpetas adicionales para la búsqueda de módulos, listas de bloqueo para excluir archivos innecesarios y transformadores personalizados. En React Native 0.72+ se utiliza la detección automática de configuración, pero para monorepos la configuración es obligatoria.
// 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 excluye los archivos de prueba de la compilación, reduciendo el tamaño del bundle. nodeModulesPaths especifica rutas adicionales para la búsqueda de paquetes — es crítico para monorepos. extraNodeModules crea alias para paquetes compartidos utilizados en diferentes proyectos del monorepo.
Metro proporciona varios mecanismos para optimizar el tamaño del bundle y la velocidad de compilación. Inline Requires — la técnica más efectiva, que convierte las importaciones de nivel superior en llamadas require locales dentro de funciones. RAM bundles permiten cargar módulos incrementalmente. Hermes compila JavaScript a bytecode, reduciendo el tamaño de la aplicación entre un 20 y un 30%.
// metro.config.js — optimización para producción
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 Hermes — en build.gradle (Android):
// project.ext.react = [enableHermes: true, bundleInRelease: true]
// Para iOS — en Podfile: :hermes_enabled => true
Para el diagnóstico del tamaño del bundle, Metro proporciona la bandera --bundle-output con salida de estadísticas. Utilice bundle-visualizer para analizar la composición del bundle y encontrar módulos grandes que se puedan cargar de forma diferida. La verificación regular del tamaño del bundle debe ser parte del pipeline CI/CD del proyecto React Native.
Metro admite delta bundles — un mecanismo en el que, después de la primera compilación completa, el servidor envía solo los cambios (delta) entre las versiones antigua y nueva del bundle. Esto acelera radicalmente las compilaciones posteriores: el tiempo de actualización se reduce de segundos a decenas de milisegundos. Los delta bundles son especialmente efectivos durante el desarrollo, cuando el desarrollador guarda cambios frecuentemente y recarga la aplicación.
Para habilitar delta bundles en React Native se utiliza la bandera --delta en el comando npx react-native bundle. En el lado del cliente, los delta bundles son compatibles a partir de React Native 0.64. En las compilaciones de producción no se utilizan delta bundles — en su lugar se emplea un bundle completo con bytecode de Hermes para máximo rendimiento de inicio. Esto se logra porque la ganancia en velocidad de desarrollo compensa el costo de la primera compilación completa.
Hermes es un motor JavaScript desarrollado por Meta específicamente para React Native. Metro genera bytecode de Hermes durante la compilación, lo que permite que la aplicación se inicie sin una costosa compilación de JavaScript en el dispositivo. Para habilitar Hermes, basta con añadir enableHermes: true en metro.config.js y configurar build.gradle o Podfile. Hermes reduce el tiempo de inicio de la aplicación entre un 30 y un 50% y reduce el tamaño del APK entre un 20 y un 30% en comparación con JavaScriptCore.
Al usar Hermes, es importante recordar sus limitaciones: el motor no admite Proxy, Reflect y algunas características de ES6. La mayoría de las aplicaciones React Native no utilizan estas características directamente, pero algunas bibliotecas pueden entrar en conflicto. Antes de habilitar Hermes, verifique la compatibilidad de todas las dependencias del proyecto a través de la lista de verificación oficial de compatibilidad. Metro cambia automáticamente al modo de generación de bytecode cuando se activa Hermes.
Para realizar un seguimiento de la eficiencia de compilación de Metro, utilice las métricas integradas disponibles a través de Flipper — la herramienta de depuración de React Native. Metro publica eventos: bundle_request, transform, resolve con el tiempo de ejecución de cada etapa. El análisis de estos datos ayuda a identificar cuellos de botella: si la fase de transformación ocupa más del 70% del tiempo, el problema está en el transformador Babel. Active el registro de logs de Metro mediante la bandera --verbose para un diagnóstico detallado.
Preguntas frecuentes
Técnicamente sí — existen proyectos experimentales como react-native-webpack, pero no tienen soporte oficial. Metro está integrado con el puente de React Native, Turbo Modules y Hermes a un nivel inaccesible para Webpack. Reemplazar Metro provocaría la pérdida de Fast Refresh y del soporte oficial.
React Native no utiliza CSS para los estilos — en su lugar se aplica la estilización mediante JavaScript a través de StyleSheet.create. Dado que Metro está creado exclusivamente para React Native, no necesita soporte de CSS. Para la renderización web a través de React Native Web, el CSS se maneja con herramientas independientes fuera de Metro.
Metro no procesa imágenes ni fuentes como módulos. Los recursos se importan mediante require('./image.png'), pero Metro solo los registra como dependencias de cadena. La carga real de imágenes se realiza mediante código nativo de React Native a través del componente Image, y Metro copia los recursos en el bundle.
Rollup genera módulos ES con tree shaking a nivel de módulos, lo que proporciona un tamaño mínimo de bundle para bibliotecas. Metro genera un bundle CommonJS con transformación en línea y optimización para motores móviles. Rollup no admite Fast Refresh y no puede trabajar con módulos nativos de React Native.
La compilación en frío de Metro se ralentiza debido al escaneo completo de node_modules. Soluciones: añada watchFolders para monorepos, use maxWorkers para transformación paralela e instale Watchman. Para proyectos con más de 10,000 archivos, considere metro-memory-fs para almacenamiento en caché en memoria.
Resumen
watchFolders y extraNodeModules para la resolución correcta de módulos.Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también