Pasar la app a producción
Publicar una app de Expo no se parece a desplegar un backend: no hay servidor al que subir nada, hay dos tiendas con sus propios requisitos y un build que se compila fuera de tu máquina.
No, no necesitas Android Studio ni Xcode
Es la primera duda y la respuesta es que EAS Build compila en la nube. Lanzas
eas build, se construye en los servidores de Expo y te devuelve un artefacto —un .aab para Play,
un .ipa para App Store—.
Consecuencias prácticas: puedes publicar en iOS desde Linux o Windows, y no tienes que mantener SDKs nativos al día en tu equipo.
Solo necesitas el toolchain local en dos casos: si compilas con eas build --local, o si tienes que
depurar código nativo. Ninguno es el caso normal.
Lo que sí hace falta para iOS es una cuenta de Apple Developer (de pago, anual). Sin ella no se puede ni firmar un build para dispositivo real. Android es un pago único en Play Console.
Los tres perfiles de eas.json
Ya están definidos y cada uno existe para algo distinto:
| Perfil | Para qué | Detalle |
|---|---|---|
development |
Build con dev-client, para desarrollar contra tu máquina | developmentClient: true, APK |
preview |
Compartir con alguien sin pasar por la tienda | distribution: internal → enlace instalable |
production |
Lo que va a la tienda | autoIncrement: true, y Android sale como .aab |
distribution: internal es la vía para que alguien pruebe la app sin tienda: EAS da un enlace y se
instala directamente. En iOS eso exige que el dispositivo esté registrado en tu cuenta de Apple.
Y "simulator": false en preview significa build para dispositivo real, no para el simulador.
Las versiones las gestiona EAS
"cli": { "appVersionSource": "remote" }
Con eso, el número de build lo lleva EAS, no el repositorio, y autoIncrement: true lo sube
solo en cada build de producción. Tú solo tocas version en app.json, que es la versión que ve el
usuario (1.0.0, 1.1.0…).
No edites números de build a mano: con remote los ignora y te confundirás.
Orden de trabajo
1 · Vincular el proyecto
npx eas-cli@latest login
npx eas-cli@latest init
eas init crea el proyecto en tu cuenta y añade extra.eas.projectId a app.json. Sin ese id,
eas build no sabe contra qué proyecto construir. Es el primer paso y solo se hace una vez.
2 · Dominios reales en eas.json
Los perfiles vienen con dominios de ejemplo (api.template.example). Cada perfil apunta la app a un
backend distinto vía EXPO_PUBLIC_API_URL, así que antes del primer build de producción hay que
poner el dominio real. Un build con el placeholder compila perfectamente y la app no conecta con
nada.
Ojo con el prefijo: EXPO_PUBLIC_ significa que el valor queda incrustado en el bundle y es
legible por cualquiera que descargue la app. Ahí van URLs, nunca secretos.
3 · Identificadores y metadatos en app.json
Lo que hay que revisar antes de publicar, porque algunos no se pueden cambiar después:
ios.bundleIdentifieryandroid.package— son la identidad de la app en cada tienda. Cambiarlos tras publicar significa publicar una app distinta, no actualizar la existente.nameyslug— el nombre visible. Conviene que no siga siendo el del repo.- Iconos y splash — cada tienda valida tamaños y formatos.
- Textos de permisos — iOS rechaza builds que piden un permiso sin explicar para qué. Aquí ya
está
NSFaceIDUsageDescription; cualquier permiso nuevo necesita el suyo.
4 · Credenciales de firma
EAS puede generarlas y guardarlas por ti, que es lo recomendado:
npx eas-cli@latest credentials
- Android: un keystore. Guárdalo o delega en Play App Signing. Si pierdes el keystore y no
usas firma gestionada por Google, no puedes volver a actualizar la app publicada — hay que
publicar otra con otro
package. Es el error irreversible más caro de este proceso. - iOS: certificado de distribución y perfil de aprovisionamiento. EAS los crea y renueva contra tu cuenta de Apple.
5 · Push, si la app lo usa
El backend envía por FCM y APNs directamente, no por el servicio de Expo — ver push. Así que:
- Android: hace falta
google-services.jsondel proyecto de Firebase, referenciado desdeapp.jsonconandroid.googleServicesFile. - iOS: una clave de APNs subida al almacén de credenciales de EAS.
El push no se puede probar en Expo Go ni en un emulador Android sin Play Store: necesitas una build de desarrollo en un dispositivo real.
6 · Build y envío
npx eas-cli@latest build --platform android --profile production
npx eas-cli@latest submit --platform android --profile production
submit sube el artefacto a la tienda. Lo que no hace es rellenar la ficha: eso se hace a mano
en Play Console y App Store Connect la primera vez.
Lo que pide cada tienda, y suele frenar
Esto es lo que más retrasa una primera publicación, y nada de ello es código:
| Requisito | Play | App Store |
|---|---|---|
| Política de privacidad en una URL pública | obligatoria | obligatoria |
| Capturas de pantalla por tamaño de dispositivo | sí | sí |
| Clasificación por edad / cuestionario de contenido | sí | sí |
| Declaración de datos recogidos | Data safety | preguntas de privacidad |
| Revisión humana antes de publicar | revisión | App Review |
La política de privacidad es bloqueante en las dos. Si la app maneja datos personales, necesita una URL accesible antes de poder enviar nada.
Y un detalle de calendario que sorprende: Play exige a las cuentas de desarrollador personales nuevas un periodo de pruebas cerradas con un mínimo de testers durante varios días antes de poder pasar a producción. Conviene comprobar la política vigente al empezar, porque cambia y puede añadir semanas al plan.
Después del primer envío
No hay actualizaciones por aire. El proyecto no incluye expo-updates, así que cada cambio
—aunque sea una cadena de texto— exige un build nuevo y pasar otra vez por la tienda. Si eso se
vuelve un problema, añadir expo-updates permite publicar cambios solo de JavaScript sin revisión;
lo que nunca se puede actualizar así es un cambio de configuración nativa: permisos, plugins,
iconos, identificadores.
Sabiendo eso, la regla práctica: agrupa los cambios nativos. Cada uno cuesta un ciclo de revisión completo.
Checklist antes del primer build de producción
-
eas initcorrido yextra.eas.projectIdenapp.json -
EXPO_PUBLIC_API_URLcon el dominio real en el perfilproduction -
eas.jsoncommiteado -
name,slug,bundleIdentifierypackagedecididos — no se cambian después - Iconos, splash y textos de permisos revisados
- Keystore guardado, o Play App Signing activado
- Credenciales de push por plataforma, si hay push
- Política de privacidad publicada en una URL
- Capturas y ficha preparadas en cada consola