Un monorrepo Turborepo permite que múltiples aplicaciones Expo compartan configuración TypeScript, reglas ESLint y un paquete de UI mientras Turbo cachea tareas de lint y typecheck en CI. Expo SDK 57 detecta espacios de trabajo automáticamente - te enfocas en los límites del paquete, no en el cableado de Metro.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
mkdir mobile-monorepo && cd mobile-monorepopnpm init# Workspace roots (create pnpm-workspace.yaml - see Working Example)npx create-expo-app@latest apps/mobile --template default@sdk-57 --yesmkdir -p packages/ui/srcpnpm add turbo -Dw# Link UI package into the app (from apps/mobile/package.json)# "@repo/ui": "workspace:*"pnpm installpnpm turbo run typecheckpnpm turbo run dev --filter=mobile
Cuándo usarlo:
Dos o más aplicaciones Expo (consumidor + admin, variantes de marca blanca) compartiendo componentes y utilidades.
Un paquete de sistema de diseño consumido por mobile y un futuro admin web.
CI que ejecuta lint/typecheck en aplicaciones y paquetes con caché remoto.
Colocación de módulos nativos o lógica de negocio compartida sin publicar en npm.
// apps/mobile/metro.config.js - SDK 52+ default is usually enoughconst { getDefaultConfig } = require("expo/metro-config");module.exports = getDefaultConfig(__dirname);
Lo que esto demuestra:
pnpm-workspace.yaml declara apps/* y packages/* - Expo detecta el monorrepo y configura Metro automáticamente en SDK 57.
workspace:* vincula mediante symlink @repo/ui en apps/mobile/node_modules - Metro empaqueta el source .tsx del paquete sin un paso de compilación separado.
turbo.json ejecuta typecheck y lint con ordenamiento de dependencias ^ - los paquetes compartidos se verifican antes que las aplicaciones.
peerDependencies en react y react-native en @repo/ui previenen copias duplicadas del renderer dentro del paquete.
Minimal metro.config.js - sin watchFolders manual cuando usas expo/metro-config en SDK 52+.
Workspaces permiten que apps/mobile dependa de paquetes locales mediante symlinks en lugar de publicaciones npm.
Turborepo construye un gráfico de tareas desde los scripts de package.json de cada workspace y cachea salidas de tareas por hash de entrada.
Expo Metro (SDK 52+) detecta automáticamente monorrepos y vigila paquetes de workspace - watchFolders / extraNodeModules manual solo se necesitan para configuraciones legales o layouts no estándar.
Metro empaqueta workspace TSX directamente - a diferencia de Next.js, no hay equivalente a transpilePackages; Babel procesa la fuente vinculada a través de la configuración de la aplicación.
EAS Build se ejecuta desde el directorio de la aplicación (apps/mobile) pero instala dependencias desde la raíz del monorrepo cuando se configura con el directorio de trabajo correcto.
# Ejecuta solo el servidor de desarrollo de la aplicación móvilpnpm turbo run dev --filter=mobile# Typecheck móvil y todo en lo que dependepnpm turbo run typecheck --filter=mobile...# Typecheck solo los paquetes cambiados desde mainpnpm turbo run typecheck --filter="...[origin/main]"
Alinea versiones en pnpm.overrides o resolutions de package.json raíz
Paquete sin peer de react
Agrega peerDependencies en paquetes de workspace; instala peers en la aplicación
Módulos nativos duplicados
Habilita experiments.autolinkingModuleResolution en app.json (SDK 54+; automático en monorrepos SDK 55+)
// package.json raíz - fuerza una sola instancia de React 19 en todos los workspaces (pnpm){ "pnpm": { "overrides": { "react": "19.2.3", "react-native": "0.86.0" } }}
Los paquetes de workspace necesitan su propio tsconfig.json con "noEmit": true para turbo run typecheck. Los alias de ruta como @/* pertenecen en cada aplicación - no en la base compartida.
Configuración manual de monorrepo de Metro en SDK 57 - Copiar recetas pre-SDK-52 de watchFolders puede entrar en conflicto con la detección automática de Expo. Solución: Comienza solo con getDefaultConfig(__dirname); elimina las anulaciones de resolver heredadas y ejecuta npx expo start --clear.
Versiones duplicadas de react-native - Dos versiones en un monorrepo causan errores de compilación nativa y runtime. Solución:pnpm why react-native; agrega anulaciones raíz; nunca permitas que los paquetes fijen versiones principales de RN diferentes.
workspace:* con npm - npm no admite el protocolo de workspace. Solución: Usa pnpm (recomendación predeterminada de Turborepo), Yarn 4+, o Bun; o reemplaza con * y acepta garantías de vinculación más débiles.
Pantallas de características en packages/ui - El paquete compartido importa expo-router y hooks de características; cada aplicación hereda acoplamiento de navegación no deseado. Solución: Mantén características en apps/mobile/src/features/; los paquetes contienen solo primitivas.
Entradas de exports faltantes - Agregar ./card.tsx sin enumerarlo en exports de package.json rompe la resolución de Metro. Solución: Declara cada subruta explícitamente una vez que exports está presente.
Instalaciones aisladas de pnpm - El aislamiento estricto puede romper algunas bibliotecas de React Native. Solución: Usa nodeLinker: hoisted en pnpm-workspace.yaml si aparecen errores de resolución (Expo admite instalaciones aisladas desde SDK 54+, pero hoisted es más seguro durante la configuración).
EAS Build desde directorio incorrecto - El perfil de compilación apunta a la raíz del repositorio sin configuración de instalación de monorrepo. Solución: Establece workingDirectory de EAS a apps/mobile e instala desde la raíz según la guía de monorrepo de Expo.
Los Workspaces solos vinculan paquetes. Turborepo agrega un gráfico de tareas, caché local y caché remoto para que lint y typecheck omitan paquetes sin cambios en CI. El filtrado (--filter=mobile) se enfoca en una aplicación y sus dependencias.
¿Necesito configuración personalizada de Metro para monorrepos en SDK 57?
Generalmente no. Expo configura automáticamente Metro cuando detecta raíces de workspace y usas expo/metro-config. Si migraste desde una guía pre-SDK-52, elimina watchFolders y extraNodeModules manual, luego ejecuta npx expo start --clear.
¿Qué significa workspace:*?
Le dice a pnpm que vincula mediante symlink el workspace local packages/ui en apps/mobile/node_modules en lugar de descargar desde npm. El * significa "cualquier versión que exista en el workspace".
¿Necesitan los paquetes compartidos un paso de compilación?
Para el empaquetado de Metro, no - las aplicaciones importan .tsx raw desde @repo/ui. Para publicar en npm fuera del monorrepo, agrega una tarea build que emita dist/. Dentro del monorrepo, las importaciones de fuente son estándar.
Ejecuta pnpm install desde la raíz del monorrepo después para que se resuelvan los enlaces del workspace.
¿Puedo agregar una segunda aplicación Expo?
Sí. Andamio apps/admin con la misma plantilla, agrega "@repo/ui": "workspace:*", y ejecuta pnpm turbo run dev --filter=admin. Comparte packages/ui y packages/typescript-config entre ambos.
¿Cómo ejecuto solo una aplicación?
pnpm turbo run dev --filter=mobilepnpm turbo run typecheck --filter=mobile...
El ... final incluye dependencias de workspace de mobile.
Error común: ¿por qué Metro falla al resolver @repo/ui?
Causas comunes: entrada exports faltante para la subruta, paquete no enumerado en pnpm-workspace.yaml, o pnpm install no ejecutado desde la raíz. Verifica que node_modules/@repo/ui sea un symlink a packages/ui.
¿Cómo prevengo react-native duplicado?
pnpm why --depth=10 react-native
Alinea todos los workspaces a 0.86.0. Agrega pnpm.overrides raíz si una dependencia transitiva tira una versión principal diferente.
¿Debería packages/ui usar peerDependencies?
Sí. Declara react y react-native como peers para que la aplicación suministre una única copia. Instala versiones coincidentes en las dependencies de la aplicación, no solo en las devDependencies del paquete.
¿Dónde viven las carpetas de características en un monorrepo?
Dentro de cada aplicación: apps/mobile/src/features/. Los paquetes compartidos contienen primitivas y utilidades - no pantallas de características del producto. Ver Estructura de carpetas para características.
¿Cómo funciona EAS Build con monorrepos?
Apunta la compilación al subdirectorio de la aplicación e instala desde la raíz del monorrepo. EAS detecta pnpm-lock.yaml en la raíz. Establece el eas.json de la aplicación y el directorio de trabajo según la documentación de monorrepo de Expo.
¿Qué configuraciones de turbo.json necesita expo start?
"dev": { "cache": false, "persistent": true }
Los servidores de desarrollo son de larga duración y no deben almacenarse en caché como tareas completadas.
¿Turborepo vs Nx para React Native?
Turborepo es más ligero - caché y filtrado de tareas con configuración mínima. Nx agrega generadores, comandos afectados y plugins específicos de RN con más costo de configuración. Ver Monorrepo con Nx.
¿Cuándo es un monorrepo la opción incorrecta?
Aplicación única, equipo único, sin paquetes compartidos. Los monorrepos agregan complejidad de instalación, riesgo de dependencias duplicadas y configuración de herramientas. Comienza de forma independiente; extrae un monorrepo cuando una segunda aplicación o paquete compartido es real - no especulativa.