Un monolito modular lanza un binario instalable con módulos de características habilitados por flags y configuración. Multi-app repositorios construyen listados de tienda separados - diferentes bundle IDs, iconos y a menudo trenes de lanzamiento independientes. Elige basándote en independencia de lanzamiento, no en preferencia del equipo.
# Mismo repositorio - diferentes apps instalables via perfiles EASAPP_VARIANT=consumer eas build --profile production-consumer --platform iosAPP_VARIANT=business eas build --profile production-business --platform ios
Cuándo usar esto:
El producto pide una "app empresarial" junto al consumidor - decide si es un flag o un listado de tienda.
Inquilinos white-label necesitan bundle IDs personalizados pero comparten el 90% del código.
El cumplimiento requiere aislar herramientas de administración de binarios orientados al consumidor.
Los gerentes de lanzamiento quieren uno vs dos registros App Store Connect.
// Fallar cerrado cuando módulo requerido está deshabilitadoimport { getFeatureFlags } from "@/shared/config/featureFlags";export function B2BPortalScreen() { if (!getFeatureFlags().b2bPortal) { return null; // o redirigir - la ruta también debe estar sin registrar } // ...}
Prefiere excluir rutas del navegador sobre renderizar pantallas vacías.
Feature flags sin límites de módulos - B2B deshabilitado aún se vincula si importaciones de features/b2b se filtran. Solución: Aísla features/b2b; lint-import apps solo consumidor lejos de ella.
Un slug, dos bundle IDs - El dashboard Expo y canales OTA se confunden. Solución: Canales EAS Update separados por APP_VARIANT.
Flags en tiempo de ejecución para cumplimiento - Código de administración aún en el bundle JS. Solución: Multi-app o exclusión en tiempo de compilación para SKUs reguladas.
División multi-app prematura - Dos apps, 99% código compartido, costo CI duplicado. Solución: Inicia monolito + variantes; extrae apps/ cuando configuración nativa diverge.
URLs de API codificadas por app - Lógica env duplicada. Solución: Central getAppConfig() indexado por appVariant.
Expo Go no puede probar variantes realistamente - Bundle IDs e iconos necesitan dev builds. Solución: Perfil de desarrollo EAS por variante.
if (flags.x) divino en cada pantalla - Ramificación inmantenible. Solución: Registra rutas y navegadores desde un único useAppRoutes() / manifiesto de módulo.
Un binario de app instalable que contiene múltiples módulos de características. Los módulos están limitados en código (features/b2b) y habilitados via configuración o flags - no microservicios separados.
¿Cuándo es suficiente un binario con flags?
Cuando productos comparten navegación, plugins nativos, y cadencia de lanzamiento - solo algunos tabs o flujos difieren (portal B2B, características beta, branding de inquilino).
¿Cuándo necesito apps separadas en el repositorio?
Cuando bundle IDs, cuentas de tienda, entitlements nativos, o cronogramas de lanzamiento son genuinamente independientes - no meramente temas diferentes.
¿Los feature flags eliminan código del bundle?
Los flags en tiempo de ejecución ocultan UI; no hacen tree-shake de módulos nativos. Usa variantes en tiempo de compilación o apps separadas para excluir SDKs regulados.
¿Cómo funciona Expo Updates con variantes?
Asigna un canal por variante (production-consumer, production-business). Publicar en el canal incorrecto actualiza el listado incorrecto.
¿Puede el monolito modular soportar white-label?
Sí - env TENANT en app.config.ts por perfil EAS. packages/features compartido mantiene código; activos de inquilino viven en env específico de perfil o assets/tenants/<name>/.
¿APP_VARIANT vs EXPO_PUBLIC feature flags?
APP_VARIANT típicamente impulsa identidad (nombre, bundle ID) en tiempo de compilación. Los flags EXPO_PUBLIC_* se adaptan a experimentos en tiempo de ejecución incrustados en JS - ambos pueden coexistir.
¿Cómo oculto rutas Expo Router cuando un flag está desactivado?
Registra condicionalmente entradas Tabs.Screen / Stack.Screen desde un manifiesto de rutas - no dependas de que los usuarios nunca hagan deep-link a rutas deshabilitadas.
¿Es multi-app lo mismo que monorepo?
No. Monorepo es diseño de repositorio. Multi-app significa múltiples apps Expo (apps/a, apps/b). Un monorepo puede alojar una app (monolito modular) o muchas.
¿Qué pasa con applicationId de Android vs bundleIdentifier de iOS?
Ambos se ramifican desde app.config.ts por variante. Mantén sincronizados con APP_VARIANT - IDs desajustadas rompen deep links y credenciales push.
¿Puedo fusionar apps consumidor y empresarial después?
Más fácil que dividir. Migra módulos solo empresariales detrás de flags, unifica estrategia bundle ID deliberadamente - listados de tienda pueden requerir reinstalación del usuario.
¿Cómo se relaciona esto con perfiles de compilación EAS?
Cada perfil establece env (APP_VARIANT, TENANT, flags). Los perfiles son el mecanismo de entrega para variantes de monolito y objetivos multi-app.
¿Deberían B2B y consumidor compartir analítica?
Arquitectónicamente namespaces de eventos separados por appVariant. Multi-app puede usar proyectos de analítica diferentes - planifica antes de fusionar dashboards.
¿Monolito modular vs servicio de feature flags?
Los flags locales controlan módulos en tiempo de compilación y navegación. Los servicios de flags remotos controlan experimentos - usa ambos: límites de módulos localmente, remoto para A/B.