Saltar al contenido principal

Cómo reemplazar Differential Updater: la guía de Capacitor

Aprende a reemplazar los updaters diferenciales en apps de Capacitor con Capgo. Guía de migración paso a paso que cubre cambios en code, CI y despliegues seguros.

Cómo reemplazar Differential Updater: la guía de Capacitor

Un viernes por la tarde, un fix de producción está listo, pero el mecanismo de live update de tu app de Capacitor ha convertido el despliegue en un juego de adivinanzas. Un dispositivo reporta el nuevo bundle, otro mantiene un conjunto de assets más antiguo, y la ruta de rollback se comporta de forma distinta según qué versión llegó primero. El updater parecía una integración pequeña cuando lo instalaste. Reemplazarlo se parece más a montar un diferencial: el montaje antiguo debe retirarse limpiamente, el nuevo debe coincidir con su base, y cada medición debe ser repetible.

Esa comparación importa porque un sistema de actualización no es solo un botón de descarga. Hace seguimiento de versiones, reconstruye bundles, aplica límites nativos y de JavaScript, y decide qué pasa cuando un paquete está incompleto o incompatible. La pregunta práctica no es solo cómo reemplazar la entrega diferencial. Es cómo reemplazar el updater sin crear un segundo modo de fallo durante la migración.

Tabla de contenidos

Reconocer la necesidad de un nuevo updater

La primera advertencia suele llegar como un misterio operativo. Un release pasa las pruebas locales, el servidor muestra un upload exitoso y soporte sigue recibiendo reportes de que los usuarios ven una pantalla antigua. El equipo de ingeniería compara identificadores de bundle, versiones de Native Build, asignaciones de channel y logs del dispositivo, y descubre que el updater aceptó un paquete construido sobre una base distinta a la almacenada localmente.

Eso se parece a un diferencial con una configuración de engranajes incorrecta. Las piezas pueden parecer compatibles, pero el ensamblaje genera ruido bajo carga. En una app de Capacitor, el ruido equivalente aparece como un estado inconsistente de los assets, fallos de extracción, reintentos infinitos o un rollback que solo restaura parte del bundle esperado.

Un diagnóstico útil parte de los síntomas, no de las suposiciones:

  • Desajuste de versiones: Confirma que el native shell instalado, el bundle descargado y los metadatos del updater coincidan en su rango de compatibilidad.
  • Rollback poco claro: Prueba si un update fallido devuelve el bundle anterior completo o deja archivos obsoletos.
  • Observabilidad débil: Verifica si puedes identificar el dispositivo afectado, la versión del paquete, el channel, la etapa del fallo y el último launch exitoso.
  • Targeting descontrolado: Busca usuarios de producción que estén recibiendo artifacts destinados a streams de beta, staging o de un cliente específico.
  • Entrega ineficiente: Mide si el sistema envía un archivo completo cuando solo han cambiado unos pocos web assets. El contexto de este trade-off de diseño se explica en cómo las delta updates reducen el tamaño del payload.

Un mecánico profesional inspeccionando los bajos de un vehículo con una linterna para diagnosticar un posible fallo en la suspensión.

Diagnostica antes de elegir un reemplazo

No trates cada actualización fallida como prueba de que el updater es defectuoso. Un artifact de build defectuoso, una regla de channel incorrecta, un signing secret roto o un cambio de compatibilidad nativa pueden causar el mismo síntoma. Captura primero la ruta del fallo, incluyendo la identidad del package, la versión base, el estado del dispositivo y si la app arrancó correctamente después de aplicar la actualización.

El reemplazo se justifica cuando el mecanismo no ofrece respuestas fiables o una recuperación segura. Si tu equipo no puede demostrar qué dispositivos recibieron un bundle, no puede invalidar un release defectuoso rápidamente o no puede garantizar que una base ausente haga fallback a un package completo, parchear la configuración solo pospondrá el próximo incidente.

El principio de ingeniería es el mismo que en un conjunto de engranajes. Confirma el componente defectuoso antes de retirar la carcasa. Una migración completa del actualizador tiene un costo inicial mayor, pero te da un protocolo limpio, reglas de versión explícitas y un límite de rollback testeable, en lugar de otra capa de ajustes sobre una instalación incierta.

Retirar el mecanismo antiguo con seguridad

Trata la retirada como un procedimiento de aislamiento controlado. El objetivo no es eliminar un paquete y esperar a que el próximo build revele lo que queda. El objetivo es evitar que dos mecanismos de actualización compitan por el mismo directorio web, hook de arranque, clave de configuración o endpoint de entrega.

Comienza congelando la rama de migración y registrando el comportamiento actual. Guarda la versión activa del plugin, la configuración nativa, las variables de entorno, los comandos de CI, los nombres de canal y la ubicación donde se almacenan los bundles descargados. Necesitas este inventario para distinguir cambios intencionales de omisiones accidentales cuando se ejecute el primer build limpio.

Establecer una línea base limpia

Crea una rama descartable o copia de trabajo, e inspecciona el árbol de dependencias y la configuración de Capacitor. Identifica el paquete del actualizador legado por su nombre de paquete real, no mediante una búsqueda genérica de “update”. Revisa package.json, lockfiles, capacitor.config.ts, la configuración del proyecto iOS, los recursos de Android y el code de arranque que llama a métodos de download, sync, install o rollback.

Elimina la dependencia con el gestor de paquetes usado por el repositorio. Por ejemplo, con npm:

npm uninstall <legacy-updater-package>
npx cap sync

Usa el comando equivalente para pnpm o Yarn si eso es lo que el proyecto estandariza. El placeholder es intencional. Una guía de migración no debería inventar un nombre de paquete ni animar a ejecutar un comando destructivo contra la dependencia equivocada.

Luego busca en el repositorio el identificador del plugin antiguo, llamadas a API, nombres de endpoints, claves de configuración y event listeners. Elimina los imports obsoletos y la inicialización code de la capa de aplicación. También quita los wrappers muertos. Dejar una abstracción local que llama a un updater eliminado hace mucho más difícil el debugging posterior, ya que el build puede tener éxito mientras el comportamiento al inicio falla.

Limpiar residuos nativos

Abre los proyectos de iOS y Android tras eliminar la dependencia. Quita las referencias nativas que el gestor de paquetes no limpió, incluidos pods añadidos manualmente, dependencias de Gradle, entradas del manifiesto, valores de recursos, esquemas de URL, declaraciones de receptores y hooks de inicialización. No borres archivos solo porque sus nombres parezcan relacionados. Confirma que cada archivo pertenece exclusivamente al actualizador legacy y que ninguna configuración compartida de Capacitor depende de él.

Ejecuta una actualización de dependencias nativas y compila ambas plataformas antes de instalar el reemplazo. Esto separa los fallos de limpieza de los de integración. Un build nativo limpio no demuestra que la migración funcione, pero un build limpio fallido demuestra que el mecanismo antiguo no se ha neutralizado por completo.

La misma disciplina aplica a los scripts. Elimina los trabajos de upload antiguos, variables de endpoint, pasos de firma, comandos de copia de artefactos y notificaciones de release de CI. Revisa también los workflows de pull request, no solo los de producción. Un job de preview olvidado puede publicar un paquete incompatible en un canal que parece inofensivo hasta que un tester lo recibe.

Regla práctica: Nunca migres modificando el actualizador antiguo y añadiendo el nuevo en el mismo commit. Haz que la eliminación sea observable, compílala y solo entonces introduce el reemplazo.

Antes de continuar, instala la app limpiada en un dispositivo de prueba y verifica que ya no intente contactar el servicio anterior. Borra los datos de la app donde corresponda, inspecciona los logs de inicio y confirma que la app sigue cargando sus assets web empaquetados con normalidad. Esta línea base es tu muestra de control para la siguiente etapa. Para una comparación más amplia de enfoques, revisa Alternativas a CodePush para Capacitor, Ionic y Cordova.

Instalación y configuración de la nueva plataforma

Un updater de reemplazo debe integrarse en el proyecto como un protocolo explícito, no como una biblioteca opaca. Define qué contiene un bundle, qué versiones nativas pueden aplicarlo, cómo se mapean los canales a audiencias y qué hace el cliente cuando su base almacenada no está disponible. Si esas reglas no están claras antes de la instalación, la migración pasará una prueba de happy-path pero seguirá siendo insegura en producción.

Añade el cliente a propósito

Instala el nuevo paquete de updater con el gestor de paquetes del repositorio y sincroniza los proyectos nativos:

npm install <new-updater-package>
npx cap sync

Usa el nombre del paquete y las claves de configuración documentados por el proveedor en el proyecto actual. Mantén el cambio de dependencia separado de las actualizaciones no relacionadas de Capacitor para que un fallo en la compilación nativa tenga una causa acotada.

Inicializa el actualizador en un punto predecible del arranque de la aplicación. Debe conocer la compilación nativa actual, el canal activo, la versión del bundle web local y la política del servidor para comprobar actualizaciones. Evita repartir las llamadas de actualización entre varias pantallas. Un único servicio debe encargarse de las comprobaciones, descargas, verificación, decisiones de instalación y reporte de errores.

El cliente debe distinguir entre una actualización del bundle de JavaScript y una actualización de la aplicación nativa. Un bundle web no puede añadir un plugin nativo, alterar permisos de plataforma ni asumir con seguridad que existe un nuevo puente nativo. Codifica la compatibilidad en los metadatos de la versión y haz que el actualizador rechace paquetes fuera del rango nativo soportado.

Crea canales antes de publicar

Configura flujos separados para pruebas internas, staging y producción. Un canal es más que una etiqueta. Es una salvaguarda que determina qué audiencia puede recibir un paquete y te da un entorno controlado para validar el arranque, la navegación, la autenticación, el comportamiento offline y las llamadas al puente nativo.

Define la ruta de promoción por escrito:

  1. Desarrollo compila localmente sin publicar.
  2. Interno recibe artefactos firmados para dispositivos de ingeniería y QA.
  3. Escenografía ejercita servicios y configuración de release similares a producción.
  4. Producción acepta solo un artefacto que haya superado las comprobaciones previas.

Mantén la asignación de canales fuera del bundle de la aplicación siempre que sea posible, usando configuración de entorno gestionada en lugar de valores de prueba codificados. Un build de producción que apunte accidentalmente a un stream beta es un fallo del proceso de release, no un error del usuario.

Protege el límite del bundle

El servicio debe publicar un bundle web completo y determinista, incluso si la optimización de transporte envía solo los archivos modificados más tarde. Genera el artefacto desde un workspace limpio, excluye source maps o archivos de desarrollo a menos que tengas una razón deliberada para incluirlos, y registra una identidad de contenido para el paquete resultante.

Exige verificación de integridad antes de la instalación. El cliente debe validar los datos descargados, reconstruir el directorio esperado y cambiar a él de forma atómica. Si la verificación falla, conserva el bundle que está funcionando actualmente e informa del fallo con suficiente contexto para diagnosticarlo.

El modelo OTA más amplio, incluido el momento seguro de las actualizaciones y las limitaciones nativas, se describe en cómo realizar actualizaciones OTA.

Captura de pantalla de https://capgo.app

Almacena la configuración en el secret manager de la plataforma o en variables de CI protegidas, no en el repositorio. Separa el acceso de lectura para los jobs de build de los permisos administrativos que pueden eliminar releases o cambiar el targeting de producción. El updater también debe exponer un fallback de paquete completo. Si el dispositivo no tiene la versión base requerida, el sistema no debe intentar aplicar un parche sin anclaje.

Ajuste de pipelines de build y CI

Publicar manualmente es aceptable para un experimento y peligroso como sistema de release. Un pipeline fiable convierte una revisión del código fuente en un artefacto conocido, ejecuta checks sobre ese artefacto, lo firma, lo publica en el canal previsto y registra el resultado. La misma entrada debe producir la misma decisión de release, tanto si el job se ejecuta en la estación de trabajo de un desarrollador como en un runner alojado.

Construye el artefacto en un entorno limpio

Empieza con una secuencia reproducible. Instala las dependencias con lockfile, ejecuta linting y tests, construye la capa web y genera el output de Capacitor a partir de los archivos resultantes. No calcules un diferencial contra el directorio de trabajo de un desarrollador. Compara dos bundles inmutables y versionados producidos por CI.

Un pipeline práctico separa las responsabilidades:

  • Validación: Ejecuta tests unitarios, type checks, linting y un build web de producción antes de cualquier upload.
  • Compatibilidad: Confirma que las capacidades nativas requeridas del bundle coincidan con los builds de la app de destino.
  • Empaquetado: Crea un archivo determinista o un manifiesto de archivos y excluye los archivos temporales.
  • Firma: Firma el release con credenciales protegidas en el entorno de CI.
  • Publicación: Envía el artefacto al canal seleccionado por la rama, el tag o la aprobación del release.
  • Verificación: Consulta el servicio de entrega y confirma que la versión, el checksum y el canal coinciden.

Una infografía de seis pasos que ilustra el proceso de mejora continua para optimizar el build de software y los pipelines de CI.

Identidad de versión inequívoca

Usa un identificador de release que conecte la revisión de origen, la compatibilidad nativa y el bundle publicado. No confíes en etiquetas mutables como “latest” al hacer troubleshooting. El updater debe reportar la versión instalada exacta y la versión candidata exacta, mientras que el sistema de release debe conservar suficiente historial para hacer rollback o republicar intencionadamente.

Un manifest útil registra:

Campo Por qué es importante
Versión del bundle Identifica los web assets instalados y candidatos
Compatibilidad nativa Evita que un web bundle asuma un code de bridge no disponible
Canal Define el público objetivo
Versión base Ancla la reconstrucción diferencial
Valor de integridad Detecta corrupción o manipulación
Estado de la release Permite decisiones de promoción, pausa y rollback

La versión base es especialmente importante para la entrega diferencial. RFC 3229 describe el modelo general: un cliente identifica su representación almacenada, solicita un algoritmo de diferencias y recibe una respuesta que representa el cambio en lugar del recurso completo. El equivalente a nivel de aplicación debe calcular un patch solo cuando la base conocida del dispositivo sea válida, y enviar el bundle completo cuando no lo sea.

Protege la ruta de publicación

Trata el runner de CI como una máquina de publicación privilegiada. Restringe quién puede lanzar publicaciones en producción, mantén el material de firma fuera de los logs, rota las credenciales mediante los controles de secretos de la plataforma y evita que pull requests no confiables accedan a los secretos de publicación. Las prácticas de seguridad de CI/CD de DevArmor aportan contexto útil para reforzar permisos, secretos y límites del pipeline.

Añade un paso de publicación en staging o un dry-run antes de producción. Prueba el artifact descargado en un simulador o dispositivo limpio; luego verifica el primer inicio, el relanzamiento, la descarga interrumpida, la firma rechazada y el comportamiento de rollback. Mantén el job de release idempotente siempre que sea posible. Volver a ejecutar un job fallido no debería crear una colección ambigua de paquetes con identificadores superpuestos.

Para un patrón de implementación concreto, usa la guía de configuración del pipeline CI/CD de CapacitorEl objetivo no es solo automatizar los uploads. Es lograr que cada release sea auditable, desde el commit de origen hasta el estado del dispositivo.

Despliegue gradual y monitoreo del éxito

El rollout es donde el diseño del updater se pone a prueba bajo carga. El primer día, un paquete que parecía limpio en staging llega a dispositivos con bases más antiguas, descargas interrumpidas, poco almacenamiento y versiones de la app que tu matriz de QA no cubría. Trata el targeting por porcentaje como un dial, pero el mecanismo de seguridad real es poder detener la promoción y devolver a los usuarios a un bundle que se sabe que funciona. Haz el rollout como configurarías un nuevo engranaje diferencial. Empieza con una comprobación de ajuste controlada, vigila si hay problemas y ábrelo solo cuando el engrane esté probado y estable.

Observa toda la ruta de actualización

Vigila todo el recorrido, no solo la transferencia. Los dispositivos pueden descargar cada byte y aun así fallar en la verificación de firma, extracción, activación o en el primer lanzamiento después del cambio. Registra cada etapa con la versión del bundle, la versión nativa de la app, el canal, la plataforma, un identificador de dispositivo respetuoso con la privacidad y una categoría de error sobre la que el equipo pueda actuar.

Las señales mínimas deberían responder a algunas preguntas operativas:

  • ¿El dispositivo descubrió el candidato?
  • ¿Recibió el bundle completo o un patch diferencial?
  • ¿Pasó la validación de integridad?
  • ¿Se completó la activación?
  • ¿La app se inició correctamente después?
  • ¿El cliente se mantuvo saludable en su siguiente sesión normal?

Ese rastro de eventos da a distintos equipos lo que necesitan. Soporte necesita una línea de tiempo por dispositivo para explicar qué pasó en un teléfono. Los responsables de release necesitan tendencias de adopción, fallos y rollback en toda la flota. Un modelo práctico para seguimiento del éxito de actualizaciones OTA en apps de Capacitor se mapea claramente a esas etapas y facilita mucho el diseño del dashboard.

Un infográfico profesional que detalla un proceso de dos pasos para lanzar nuevos proyectos y monitorear su rendimiento posterior.

Usa el rollback como una funcionalidad de release

Define condiciones de rollback antes de publicar. Buenos disparadores incluyen un aumento en fallos de lanzamiento, errores de integridad repetidos, un conjunto creciente de dispositivos atascados en la versión candidata o un patrón de crashes aislado a una plataforma. Mantén el último bundle conocido como estable en el dispositivo y haz que el cambio sea reversible sin esperar a una publicación en la app store.

El rollback también requiere retención de evidencia. Conserva los metadatos del paquete fallido y los logs para que el equipo pueda reproducir el problema, identificar el rango de compatibilidad afectado y decidir si restaurar la asignación anterior o publicar un artefacto corregido. Un rollback que elimina el síntoma para los usuarios pero borra la pista suele provocar que el mismo fallo reaparezca en la siguiente versión.

El modelo de transporte detrás de la entrega diferencial lleva mucho tiempo en uso. La codificación delta HTTP se convirtió en un estándar web formal a través del RFC 3229, publicado por la Internet Engineering Task Force en enero de 2002, y la Especificación RFC 3229 sigue siendo útil por una razón práctica. Un delta solo ayuda cuando el cliente tiene una versión base válida y reconstruir el resultado cuesta menos que enviar el recurso completo.

Por eso, los updaters que entienden la aplicación suelen funcionar mejor que depender del comportamiento delta genérico de HTTP. El servicio conoce el bundle base, el cliente puede verificar el resultado reconstruido y el updater puede recurrir a un paquete completo si algo no encaja. La decisión de ingeniería es si el protocolo de entrega explicita la compatibilidad, la integridad, el rollback y la observabilidad, y la respuesta determina si la entrega diferencial sirve de algo.

Live updates para apps Capacitor

Cuando un bug de la capa web está en producción, publica el fix a través de Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el flujo de revisión habitual.

Lo último de nuestro blog

Capgo te da la información clave que necesitas para crear una app móvil realmente profesional.