Conceptos básicos de actualizaciones OTA
10 ejemplos para que comiences con actualizaciones Over-The-Air (OTA) en Expo SDK 57 - qué puede cambiar EAS Update en minutos versus qué aún requiere un envío de App Store o Play Store.
Busca en todas las páginas de la documentación
10 ejemplos para que comiences con actualizaciones Over-The-Air (OTA) en Expo SDK 57 - qué puede cambiar EAS Update en minutos versus qué aún requiere un envío de App Store o Play Store.
Las actualizaciones OTA requieren expo-updates en un binario de release o preview - no en Expo Go.
npx create-expo-app@latest MyOtaApp --template blank-typescript
cd MyOtaApp
npx expo install expo-updates
npx eas init
npx eas update:configureHerramientas: Estos ejemplos tienen como objetivo Expo SDK 57 (
expo~57.0.4), React Native 0.86.0 y React 19.2.3.
Cada decisión de lanzamiento móvil comienza con una pregunta: ¿este cambio toca código nativo?
Cambio solo en JavaScript / assets -> eas update (minutos)
Shell nativo / permisos / SDK -> eas build + envío a tienda (días)Relacionado: expo-updates (Client API) - comprobación y aplicación de actualizaciones desde código de la app
Los errores de lógica pura en JavaScript son el caso de uso clásico de OTA - sin cruzar el límite nativo.
// src/screens/CheckoutScreen.tsx - corrección de typo se envía por OTA
export function CheckoutScreen() {
const total = useCartTotal();
return (
<View>
<Text>Total: {formatCurrency(total)}</Text>
{/* Corregido: se estaba dividiendo por 100 dos veces */}
<PrimaryButton label="Pagar ahora" onPress={submitPayment} />
</View>
);
}# Después del soak de preview
eas update --channel production --environment production --message "Corregir display del total de checkout"preview primero; soak antes de production en rutas de ingresosRelacionado: Release Channels & Branches - promoción de staging a production
Las imágenes agrupadas, las fuentes referenciadas desde JS y JSON de Lottie se envían con el manifest de actualización.
// src/components/HeroBanner.tsx
import heroImage from "@/assets/hero-summer.png";
export function HeroBanner() {
return <Image source={heroImage} style={{ width: "100%", height: 200 }} />;
}Instalar un paquete con código nativo cambia la salida en ios/ y android/ - OTA no puede hacerlo.
# Esta secuencia requiere eas build + envío a tienda, NO eas update solo
npx expo install react-native-vision-camera// app.config.ts - nuevo plugin = reconstrucción nativa
export default {
expo: {
plugins: [
[
"react-native-vision-camera",
{ cameraPermissionText: "Necesitamos acceso a la cámara para escanear códigos." },
],
],
},
};npx expo prebuild es la señal - si hay cambios en el proyecto nativo, planea una compilación de tiendaRelacionado: EAS Build Basics - binarios en la nube que reciben actualizaciones
El texto de permiso vive en manifests nativos - los usuarios ven texto antiguo si haces OTA sin reconstruir.
{
"expo": {
"ios": {
"infoPlist": {
"NSCameraUsageDescription": "Escanea códigos de barras para agregar artículos a tu carrito."
}
},
"android": {
"permissions": ["android.permission.CAMERA"]
}
}
}infoPlist, permissions o entitlements necesita eas buildLas actualizaciones de SDK cambian el runtime nativo, la versión de Hermes y las dependencias nativas por defecto.
{
"dependencies": {
"expo": "~57.0.4",
"react": "19.2.3",
"react-native": "0.86.0"
}
}eas build para todos los perfiles, luego resume eas update en la nueva línea de runtimeRelacionado: Runtime Version Policy - estrategias de
appVersion,nativeVersiony fingerprint
runtimeVersion le dice a EAS Update qué bundles de JS puede descargar un binario. Desajuste = omisión silenciosa.
// app.config.ts
export default {
expo: {
version: "2.4.0",
runtimeVersion: {
policy: "appVersion",
},
updates: {
url: "https://u.expo.dev/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
},
},
};# Build integra runtime 2.4.0
eas build --profile production --platform all
# Update debe apuntar al mismo runtime
eas update --channel production --environment productioneas build y los bundles de eas update deben compartir el mismo runtimeVersion resueltonpx expo config --type public | jq '.runtimeVersion'Relacionado: expo-updates Configuration -
app.configcookbook completo
Copia esta tabla en tu runbook de lanzamiento y requiere una casilla de verificación por cambio.
| Cambio | ¿OTA? | ¿Tienda? | Notas |
|---|---|---|---|
| Corrección de bug de JS | ✅ | - | Soak de preview primero |
| Nueva pantalla React (sin nativo nuevo) | ✅ | - | Monitorea tamaño de bundle |
Nuevo módulo nativo de expo install | - | ✅ | Bump de runtime; cierra JS |
| Plugin de configuración agregado/cambiado | - | ✅ | Diff de prebuild requerido |
| Icono de app / icono adaptativo | - | ✅ | Pipeline de assets nativo |
| Icono de notificación push (Android) | - | ✅ | Recurso nativo |
| Copia remota / tokens de tema en JS | ✅ | - | Sin toque nativo |
| Migración de esquema SQLite en JS | ✅ | ⚠️ | Prueba la ruta de actualización; migración mala daña |
| Cambio que rompe la API | ✅ | ⚠️ | JS antiguo debe tolerar API antigua |
| Bytecode de Hermes / tamaño de bundle | ✅ | - | Trata como evento de lanzamiento |
OTA te deja enviar JS rápido; los flags de características te dejan controlar quién lo ejecuta.
// src/features/barcode/useBarcodeScanner.ts
import * as Application from "expo-application";
const MIN_NATIVE_FOR_SCANNER = "2.4.0";
export function useBarcodeScannerEnabled(remoteFlag: boolean) {
const nativeVersion = Application.nativeApplicationVersion ?? "0.0.0";
const nativeReady = compareSemver(nativeVersion, MIN_NATIVE_FOR_SCANNER) >= 0;
return remoteFlag && nativeReady;
}Application.nativeApplicationVersion refleja el binario de tienda, no el ID del bundle de OTARelacionado: Feature Flags for Safe Rollout - kill switches junto con OTA
El soporte y la respuesta a incidentes necesitan el ID de actualización - no solo la versión de marketing.
// app/_layout.tsx (solo diagnósticos de dev/preview)
import * as Updates from "expo-updates";
import { useEffect } from "react";
export default function RootLayout() {
useEffect(() => {
if (__DEV__) return;
console.info("[updates]", {
updateId: Updates.updateId,
runtimeVersion: Updates.runtimeVersion,
channel: Updates.channel,
isEmbeddedLaunch: Updates.isEmbeddedLaunch,
});
}, []);
return <Stack />;
}Updates.updateId identifica el bundle de OTA; Updates.isEmbeddedLaunch verdadero significa que aún no se ha aplicado OTANo. OTA reemplaza bundles de JavaScript y assets descargables. Los módulos nativos, permisos, entitlements, versión de SDK e iconos de app requieren eas build y envío a tienda.
No. Expo Go usa un shell nativo genérico sin tu configuración de canal expo-updates. Prueba OTA en compilaciones de preview o production profile de EAS.
Después de publicar, los dispositivos verifican en el lanzamiento (según tu política checkAutomatically). Los usuarios pueden necesitar un reinicio. Las correcciones críticas pueden provocar recarga a través de expo-updates (Client API).
La app se bloquea en import o en la primera llamada nativa - a menudo inmediatamente en el lanzamiento. Revierte el canal y envía una compilación de tienda. Prevención: soak de preview + guards de runtime + Release & OTA Rules.
Reciben OTAs para su línea de runtimeVersion solamente. Monitorea distribución de runtime semanalmente; refuerza versión nativa mínima cuando la seguridad lo requiere.
runtimeVersion, URL, check-on-launchVersiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0 y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 16 jul 2026