Metro Bundler es un agrupador de JavaScript especializado de Meta, desarrollado exclusivamente para React Native e incluido en el núcleo del framework. Según la documentación oficial de React Native 0.76 (2025), Metro proporciona compilaciones incrementales con Fast Refresh y resolución de módulos con extensiones específicas de plataforma .native.js, .ios.js y .android.js. A diferencia de Webpack, Metro no utiliza una caché de grafo de módulos de larga duración, sino que reconstruye el grafo cada vez que los archivos cambian, proporcionando Hot Reload instantáneo durante el desarrollo.
Puntos clave
Metro Bundler es un agrupador de JavaScript de código abierto desarrollado por Meta para React Native y utilizado por defecto en todos los proyectos del framework. La tarea de Metro es tomar el código JavaScript del proyecto junto con las dependencias y agruparlo en uno o varios bundles que se ejecutan en el dispositivo. A diferencia de los agrupadores universales (Webpack, Rollup, Parcel), Metro está optimizado para las especificidades del desarrollo móvil: tiempo mínimo de compilación, actualizaciones incrementales durante el desarrollo y manejo correcto de módulos de plataforma (módulos nativos Objective-C, Swift, Java, Kotlin). Metro se incluye en React Native CLI y no requiere instalación adicional. A partir de React Native 0.72, Metro versión 0.80+ admite transpilación paralela de módulos, acelerando las compilaciones en procesadores multinúcleo hasta en un 40%.
La arquitectura de Metro se divide en tres componentes independientes: Resolver, Transformer y Bundler. El Resolver se encarga de encontrar y resolver módulos: lee expresiones import/require, encuentra los archivos correspondientes considerando las extensiones de plataforma y devuelve rutas absolutas. El Transformer realiza la transpilación: aplica Babel con presets y plugins, transforma JSX, TypeScript o Flow a JavaScript puro. El Bundler es la etapa final: toma el grafo de dependencias del Resolver y los archivos transformados del Transformer, luego los serializa en uno o varios bundles (module bundles). La separación en tres pasos permite a Metro almacenar en caché los resultados de cada etapa: si solo cambió un archivo, el Resolver y el Bundler pueden usar la caché para los módulos restantes, proporcionando un aumento de velocidad de compilación de hasta 10 veces en modo de desarrollo.
El Resolver en Metro implementa un algoritmo de resolución de módulos parcialmente compatible con la resolución de módulos de Node.js. La diferencia clave con Node.js es el soporte para extensiones de plataforma: require(‘./Component’) busca Component.native.js, Component.ios.js, Component.android.js en el orden de prioridad especificado. El Resolver también admite el campo package.json “react-native” para mapear módulos a implementaciones alternativas: este es el mecanismo estándar para bibliotecas con código específico de plataforma. Si no se encuentra un archivo, el Resolver lanza un error con la pila de búsqueda completa.
El Transformer dentro de Metro utiliza Babel con el preset metro-react-native-babel-preset. La configuración estándar incluye: transformación de JSX a React.createElement, soporte de TypeScript (eliminación de tipos), soporte de Flow y polyfills para estándares modernos de JavaScript (async/await, optional chaining, nullish coalescing). El Transformer funciona en modo paralelo: cada módulo se transpila de forma independiente, utilizando un grupo de procesos worker (por defecto, el número corresponde al número de CPU). A partir de Metro 0.80, se admite Granular Transformer Cache: invalidación de caché a nivel de archivo individual.
Una de las características clave de Metro es el soporte para extensiones de archivo de plataforma. Un proyecto de React Native puede contener tres versiones del mismo módulo: Component.ios.js (iOS), Component.android.js (Android) y Component.native.js (ambas plataformas). Al importar require(‘./Component’), el Resolver selecciona automáticamente la versión correcta según la plataforma de compilación objetivo. Esto permite escribir código dependiente de la plataforma sin construcciones condicionales Platform.OS. Orden de prioridad: nombre.plataforma.js > nombre.native.js > nombre.js. La extensión .native.js se utiliza para código común que funciona en ambas plataformas pero es incompatible con la web. Las extensiones .ios.js y .android.js sirven para implementar características específicas: navegación, gestos, operaciones del sistema de archivos. Metro admite extensiones personalizadas a través de la configuración resolver.sourceExts.
// metro.config.js — configuración de sourceExts y 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 es un mecanismo de recarga en caliente para React Native construido sobre Metro. Cuando un desarrollador cambia un archivo, Metro re-transpila solo el módulo modificado y envía la actualización a la aplicación a través de WebSocket. Fast Refresh actualiza la interfaz sin recargar toda la aplicación y conserva el estado de los componentes de React si solo se modificaron JSX o estilos. Si se modifica código con hooks o estado, Fast Refresh vuelve a montar solo el componente modificado. Metro admite dos modos: Hot Module Replacement (HMR) para reemplazo de módulos sobre la marcha y Live Reload para recarga completa de la aplicación cuando cambian módulos nativos o configuración. Fast Refresh está habilitado por defecto en React Native 0.76 y no requiere configuración adicional: basta con ejecutar npx react-native start.
| Modo | Velocidad | Conserva estado | Desencadenante |
|---|---|---|---|
| Fast Refresh | 200-500ms | Sí | Cambios en archivos JS/TS |
| HMR | 100-300ms | Sí | Cambios en CSS/estilos |
| Live Reload | 1-3s | No | Cambios en config nativa |
| Full Rebuild | 10-60s | No | Cambios en podspec/build.gradle |
El archivo metro.config.js es el archivo de configuración de Metro ubicado en la raíz de un proyecto React Native. En él se configuran: resolver (sourceExts, platformExtensions, extraNodeModules), transformer (babelTransformerPath, minifierConfig), server (port, host, enableFastRefresh) y watcher (watchFolders, healthCheck). La configuración estándar de Metro hereda del paquete @react-native/metro-config (React Native 0.76+). Para proyectos con monorepositorio, añada watchFolders: esto permite a Metro rastrear cambios en paquetes fuera de la raíz del proyecto. Para configurar sourceExts, agregue ‘svg’, ‘png’, ‘gql’ para transformadores personalizados. Metro admite configuraciones asíncronas a través de async function: útil para generación dinámica de configuración según el entorno.
La optimización de las compilaciones de Metro comienza con una configuración adecuada de la caché. Establezca maxWorkers al número de CPU menos 1. Para distribuciones, use resetCache en CI. Minimice sourceExts: las extensiones adicionales ralentizan la resolución de módulos. Para proyectos grandes, configure watchFolders solo para los directorios necesarios. Metro admite la minificación Hermes bytecode, que produce un tamaño de bundle menor que Terser estándar: use minifierPath: ‘metro-minify-terser’.
Metro admite un modo de compilación directamente a Hermes bytecode — omitiendo la etapa de AST de JavaScript. Al compilar con HermesTransformer, los módulos se compilan en HBC (Hermes ByteCode) en lugar de JavaScript plano. Esto proporciona: menor tamaño de bundle (30-40%), inicio de aplicación más rápido (20-30%) y menor consumo de memoria. Para habilitarlo, configure hermesCommand en metro.config.js y active la bandera Hermes en build.gradle (Android) o Podfile (iOS). La compilación de bundles Hermes se realiza en dos etapas: primero Metro compila el bundle JavaScript, luego Hermes CLI lo convierte a HBC. A partir de React Native 0.70, Hermes es el motor predeterminado en Android; en iOS requiere habilitación explícita.
La diferencia entre Metro y Webpack se debe a diferentes objetivos. Webpack es un agrupador universal para la web con un enorme ecosistema de plugins y loaders. Metro es un agrupador especializado para React Native donde la prioridad es la velocidad de compilación incremental y el trabajo correcto con módulos nativos. Webpack utiliza un grafo de módulos persistente con invalidación inteligente de caché: esto proporciona reconstrucciones rápidas en la web, pero crea problemas con las extensiones de plataforma. Metro no almacena en caché el grafo entre compilaciones, sino que lo construye cada vez: esto simplifica el manejo de extensiones de plataforma y módulos Haste. Webpack admite importaciones dinámicas con chunks, Metro también: a través de React.lazy() y Suspense, pero con la limitación de una solicitud activa. El ecosistema de Metro es significativamente menor: no hay reemplazo para style-loader, css-loader, file-loader: estas tareas se resuelven de manera diferente en React Native.
Metro es la única opción correcta para proyectos React Native. Webpack no admite la resolución con conocimiento de plataforma de forma nativa, y configurar React Native con Webpack requiere un esfuerzo significativo (haul bundler, expo web packager). Metro está integrado en React Native CLI, es compatible con el equipo oficial de Meta y recibe actualizaciones con cada versión de React Native. Para proyectos React Native Web, puede usar Webpack para compilaciones web mientras mantiene Metro para bundles móviles.
Preguntas frecuentes
Ejecute npx react-native start --reset-cache o elimine la carpeta $TMPDIR/metro-* y el directorio .metro-health-check* en la raíz del proyecto. Alternativamente: npx react-native clean — este comando limpia todos los archivos temporales de Metro, incluida la caché de Babel y el mapa Haste. Después de la limpieza, la primera compilación será completa (60-120 segundos), pero las compilaciones incrementales posteriores volverán a la velocidad normal.
Verifique que el paquete esté en dependencies de package.json (no en devDependencies). Si el módulo está en un monorepositorio, agregue la ruta a watchFolders en metro.config.js. Metro no sigue enlaces simbólicos por defecto: use resolver.extraNodeModules para mapeo explícito. Para Yarn PnM, configure resolver.useWatchman: false. Si el módulo usa extensiones de plataforma, asegúrese de que los archivos .ios.js o .android.js existan en la ruta especificada.
Aumente maxWorkers en metro.config.js al número de CPU menos 1. Configure watchFolders solo para los directorios necesarios. Use Hermes bytecode para compilaciones de producción: acelera la compilación final al omitir la minificación JS. Para desarrollo, habilite Fast Refresh (está habilitado por defecto). Limite sourceExts solo a las extensiones necesarias. Considere dividir el bundle en fragmentos mediante lazy loading.
Técnicamente sí, pero no se recomienda. Metro no está optimizado para compilaciones web: no hay soporte para CSS, HTML, imágenes como módulos, ni code splitting con importaciones dinámicas a nivel de navegador. Para la web, use Webpack, Vite o Parcel. Metro es una solución especializada para React Native, e intentar adaptarlo para la web provocará pérdida de rendimiento y falta de ecosistema de loaders.
Re.Pack es una herramienta comunitaria para reemplazar Metro por Webpack en proyectos React Native. Proporciona acceso al ecosistema de loaders de Webpack (css-loader, svg-loader) y code splitting avanzado. Sin embargo, Re.Pack es más complejo de configurar, no cuenta con soporte oficial de Meta y no garantiza compatibilidad con nuevas versiones de React Native. Metro sigue siendo el único agrupador oficialmente compatible, lo que brinda estabilidad y compatibilidad garantizada con cada versión.
Resumen
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