Saltar al contenido principal

Cómo actualizar tu app de Capacitor a Capacitor 8

Actualiza una app de Capacitor a Capacitor 8: Node 22, Xcode 26, iOS 15, Android SDK 36, AGP 8.13, System Bars, SPM por defecto y fixes para errores comunes.

logo de Capacitor sobre un fondo azul oscuro para la guía de actualización a Capacitor 8

Para actualizar una app de Capacitor a Capacitor 8, instala Node.js 22+, Xcode 26+ y Android Studio Otter, actualiza @capacitor/cli a la última versión 8.x y ejecuta bunx cap migrate, luego corrige lo que reporte el migrador. Los principales breaking changes son iOS 15 como target de despliegue mínimo, Android SDK 36 con minSdk 24, AGP 8.13 con Gradle 8.14.3, y la eliminación de adjustMarginsForEdgeToEdge en favor del nuevo plugin System Bars.

Esta guía recorre el camino automatizado, cada paso manual necesario y los errores más comunes tras la actualización. Si mantienes un plugin en lugar de una app, lee Cómo actualizar tu plugin de Capacitor a Capacitor 8 en su lugar.

Requisitos de Capacitor 8 de un vistazo

Revisa tu toolchain antes de tocar el proyecto. La mayoría de las actualizaciones fallidas se deben a un JDK, Xcode o Node antiguos en CI, no al code.

Área Capacitor 7 LTS Capacitor 8 LTS
Node.js 20+ 22+ (el CLI declara engines.node >= 22.0.0)
Xcode 16+ 26+
Target de despliegue de iOS 14.0 15.0
Android Studio Ladybug Otter 2025.2.1+
minSdkVersion 23 24
compileSdkVersion / targetSdkVersion 35 36
Android Gradle Plugin 8.7.2 8.13.0
Gradle wrapper 8.11.1 8.14.3
Kotlin (si se usa) 1.9.25 2.2.20
JDK para builds de Android 21 21 (@capacitor/android compila con Java 21)
Nuevo default de la plataforma iOS CocoaPods Swift Package Manager

Xcode 26 no es solo un requisito de Capacitor. Desde el 28 de abril de 2026, App Store Connect rechaza los uploads hechos con un Xcode antiguo, así que lo necesitarás de todos modos. Mira el requisito de Xcode 26 de Apple para apps Capacitor para más detalles.

Antes de empezar

  1. Haz commit de todo o crea una rama. El migrador edita los archivos nativos in situ.
  2. Asegúrate de que la app compile con Capacitor 7 hoy. Actualizar un proyecto roto solo genera ruido.
  3. Si usas Capacitor 6 o inferior, actualiza primero a la versión anterior. Cada versión mayor tiene su propia lógica de migración en el CLI.
  4. Lista tus plugins con bunx cap ls y comprueba que cada uno tenga una release compatible con Capacitor 8. Revisa el peerDependencies de la última versión:
bun pm view @capgo/capacitor-updater peerDependencies

Un plugin con @capacitor/core: ^7.0.0 como peer se instalará con warnings y podría fallar al compilar. Los plugins de Capgo siguen la versión mayor de Capacitor en su propio número de versión, así que @capgo/* las releases 8.x apuntan a Capacitor 8.

  1. Actualiza el toolchain local y de CI: Node 22, Xcode 26, JDK 21, Android Studio Otter. En GitHub Actions, fija una imagen de macOS que incluya Xcode 26 y usa actions/setup-java con java-version: '21'.

Opción 1: actualizar con cap migrate

CLI incluye un comando de migración que hace casi todo el trabajo. Instala la última versión de CLI y ejecútalo:

bun add -D @capacitor/cli@latest
bunx cap migrate

El migrador te preguntará si debe instalar los nuevos paquetes de Capacitor y te permitirá elegir entre npm, Yarn, pnpm o Bun. Elige Bun si tu proyecto usa bun.lock. Puedes saltarte el prompt con bunx cap migrate --noprompt.

Cambios realizados:

  • Actualiza @capacitor/core, @capacitor/ios, @capacitor/android y plugins oficiales @capacitor/* a la versión 8.x.
  • Configura IPHONEOS_DEPLOYMENT_TARGET = 15.0 en el proyecto de Xcode y platform :ios, '15.0' en el Podfile.
  • Actualizaciones variables.gradle, el classpath de AGP, el Gradle wrapper y kotlin_version.
  • Añade density a android:configChanges en AndroidManifest.xml.

Lee el output completo. Cuando un paso no se puede aplicar, por ejemplo porque un archivo se personalizó, CLI imprime un error con el nombre del archivo y continúa. Esas líneas son tu lista de tareas manuales.

Al finalizar:

bun run build
bunx cap sync

Luego abre cada plataforma y haz un build desde el IDE para ver todos los errores nativos.

Opción 2: actualizar manualmente

Si tus proyectos nativos están muy personalizados o el migrador saltó pasos, aplica los cambios a mano. Estos coinciden con la guía oficial de actualización a Capacitor 8.

Actualiza los paquetes de npm

bun add @capacitor/core@latest @capacitor/ios@latest @capacitor/android@latest
bun add -D @capacitor/cli@latest

Luego actualiza cada plugin oficial, por ejemplo:

bun add @capacitor/app@latest @capacitor/splash-screen@latest @capacitor/status-bar@latest

iOS: sube el deployment target a 15.0

En Xcode, selecciona el proyecto y abre Build Settings del proyecto, busca Objetivo de despliegue de iOS en Despliegue y ajústalo a 15.0. Repite esto para cada target de la app, incluyendo las extensiones.

Si la app aún usa CocoaPods, actualízalo ios/App/Podfile:

platform :ios, '15.0'

Luego ejecuta bunx cap sync ios, que ejecuta pod install por ti.

Si la app usa SPM, el CLI se regenera ios/App/CapApp-SPM/Package.swift en cada sync con la versión de plataforma correcta y una capacitor-swift-pm versión que coincida con la que tienes instalada @capacitor/ios. No edites ese archivo a mano.

iOS: elimina las notificaciones de view controller personalizadas

Capacitor 8 ahora emite CAPBridgeViewController notificaciones para viewDidAppear y viewWillTransition en sí. Si añadiste una extensión o subclase para publicar .capacitorViewDidAppear o .capacitorViewWillTransition, elimínala, o los listeners se dispararán dos veces.

Android: actualiza Android Studio y AGP

Instala Android Studio Otter o superior, abre el android carpeta y ejecuta Herramientas > Asistente de actualización de AGP. Elige 8.13.0 y ejecuta los pasos. O edita android/build.gradle directamente:

buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:8.13.0'
        classpath 'com.google.gms:google-services:4.4.4'
    }
}

Y android/gradle/wrapper/gradle-wrapper.properties:

distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip

Android: actualiza variables.gradle

ext {
    minSdkVersion = 24
    compileSdkVersion = 36
    targetSdkVersion = 36
    androidxActivityVersion = '1.11.0'
    androidxAppCompatVersion = '1.7.1'
    androidxCoordinatorLayoutVersion = '1.3.0'
    androidxCoreVersion = '1.17.0'
    androidxFragmentVersion = '1.8.9'
    coreSplashScreenVersion = '1.2.0'
    androidxWebkitVersion = '1.14.0'
    junitVersion = '4.13.2'
    androidxJunitVersion = '1.3.0'
    androidxEspressoCoreVersion = '3.7.0'
    cordovaAndroidVersion = '14.0.1'
}

Mantén las variables extra que lean tus plugins (por ejemplo firebaseMessagingVersion). Las actualizaciones de plugins oficiales para Capacitor 8 incluyen firebaseMessagingVersion = '25.0.1', androidxBrowserVersion = '1.9.0', androidxMaterialVersion = '1.13.0' y androidxExifInterfaceVersion = '1.4.1'.

Android: cambia a = asignación en archivos Gradle

Gradle marcó como deprecated la sintaxis de asignación con espacio. Hoy solo lanza un warning, pero fallará en una futura versión de Gradle, así que arréglalo ya en android/app/build.gradle:

android {
-    namespace "com.example.app"
-    compileSdk rootProject.ext.compileSdkVersion
+    namespace = "com.example.app"
+    compileSdk = rootProject.ext.compileSdkVersion
     defaultConfig {
         aaptOptions {
-            ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
+            ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
         }
     }
}

Las llamadas a métodos como google() o mavenCentral() se mantienen igual.

Android: Kotlin y configChanges

Si tu módulo de app usa Kotlin, establece kotlin_version = '2.2.20'. Kotlin 2.x convierte el antiguo kotlinOptions {} bloque en un error, así que mueve jvmTarget en kotlin { compilerOptions { ... } }.

Luego añade density a la actividad principal para que el WebView no se recree al cambiar la densidad de pantalla (plegables, redimensionamiento de ventana, ajustes de tamaño):

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"

Android: el layout del bridge se renombró

bridge_layout_main.xml ya no existe. Si tu MainActivity o un fragment personalizado referenciaba R.layout.bridge_layout_main, usa R.layout.capacitor_bridge_layout_main.

Edge-to-edge y el nuevo plugin System Bars

Este es el cambio con más impacto visual. Capacitor 8 eliminó android.adjustMarginsForEdgeToEdge y añadió un plugin core de System Bars. No necesitas instalarlo, viene con @capacitor/core.

Android 15 obliga al modo edge-to-edge para apps con SDK 35, y Android 16 elimina la opción de desactivarlo para apps con SDK 36. Capacitor 8 apunta a 36, por lo que tu contenido web ahora se dibuja detrás de las barras de estado y navegación a menos que gestiones los insets.

La configuración del plugin se encuentra en plugins.SystemBars:

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  webDir: 'dist',
  plugins: {
    SystemBars: {
      // 'css' (default) injects --safe-area-inset-* variables on Android
      // 'native' relies on env() and viewport-fit
      // 'disable' leaves inset handling entirely to you
      insetsHandling: 'css',
      initialViewportFitValueHint: 'cover',
    },
  },
};

export default config;

Con css o native, las nuevas Android WebViews (Chromium 140+) respetan viewport-fit=cover y reportan los valores env(safe-area-inset-*) reales. En WebViews antiguas, Capacitor añade padding a la WebView y establece los valores de env en 0px. Así que configura la meta tag y usa las variables:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
body {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

At runtime you can change bar style or visibility:

import { SystemBars, SystemBarsStyle, SystemBarType } from '@capacitor/core';

await SystemBars.setStyle({ style: SystemBarsStyle.Dark });
await SystemBars.hide({ bar: SystemBarType.NavigationBar });

Las apps de Ionic Framework ya usan las variables de safe-area, así que normalmente solo necesitan la meta tag. Nuestro post anterior sobre edge-to-edge sin plugins describe la opción Capacitor 7, que ya no existe en la 8.

Otros cambios de comportamiento a revisar

  • appendUserAgent en iOS: Capacitor 7 añadió dos espacios antes de tu string, Capacitor 8 añade uno. Si tu servidor parsea el user agent de forma estricta, añade un espacio al inicio de ios.appendUserAgent (no en la opción root, que también afecta a Android).
  • Screen Orientation y Barcode Scanner: en pantallas grandes de Android 16+, los bloqueos de orientación se ignoran. Hay un opt-out temporal disponible mediante la propiedad android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY del manifest, pero Android 17 la elimina.
  • Geolocalización: timeout ahora se aplica a todas las peticiones en Android e iOS. Si ves nuevos timeouts, aumenta el valor. watchPosition en Android obtuvo un interval opción.
  • Barra de estado: el plugin ya no incluye sus propios CAPBridgeViewController archivos de notificación, ya que el core ahora emite esos eventos.
  • Las nuevas plataformas de iOS usan SPM por defecto: bunx cap add ios ahora crea un proyecto SPM. Usa --packagemanager CocoaPods si necesitas la plantilla antigua. Consulta cómo usar CocoaPods con Capacitor 8.

Verifica la actualización

Revisa esta lista en ambas plataformas antes de publicar:

bunx cap doctor
bunx cap sync
bunx cap run ios
bunx cap run android
  • cap doctor muestra las versiones 8.x compatibles para el core, CLI, iOS y Android.
  • La app arranca, el splash screen se oculta y los deep links abren la pantalla correcta.
  • Las áreas de la barra de estado y de navegación se ven correctamente en dispositivos Android 15/16 y en iPhones con notch.
  • Las push notifications, la cámara, el acceso a archivos y cualquier plugin con permisos nativos siguen funcionando.
  • Una build de release (Archive en Xcode, ./gradlew bundleRelease) funciona, no solo la de debug.

Si no quieres mantener Xcode 26 y JDK 21 en cada máquina, Build de Capgo ejecuta las builds de iOS y Android en la nube con toolchains actuales.

Lanza la actualización de forma segura con Live Updates

Una actualización mayor de Capacitor cambia el code nativo, por lo que debe pasar por la App Store y Google Play. Los web bundles creados tras la actualización podrían llamar a APIs de plugins que los binarios antiguos no tienen.

Si usas actualizaciones Live Update de Capgo, mantén separados a los usuarios de Capacitor 7 y a los de Capacitor 8 hasta que la adopción se nivele: incrementa tu versión nativa, sube nuevos bundles a un canal usado por el nuevo binario y ejecuta la comprobación de compatibilidad antes de subir:

bunx @capgo/cli@latest bundle compatibility

Compara las versiones de los plugins nativos en tu bundle con lo que se ejecuta en el canal y detecta discrepancias antes de que los usuarios reciban una actualización rota.

Solución de errores comunes al actualizar a Capacitor 8

The engine "node" is incompatible o si CLI no arranca. Estás usando Node 20 o inferior. Instala Node 22 LTS y actualiza también tu imagen de CI.

error: invalid source release: 21 en Android. Gradle se está ejecutando con JDK 17. Configura Android Studio para que use su JDK 21 integrado (Configuración &gt; Build, Execution, Deployment &gt; Build Tools &gt; Gradle &gt; Gradle JDK) y establece JAVA_HOME a un JDK 21 para builds por CLI y CI.

Minimum supported Gradle version is 8.13. Actualizaste AGP pero no el wrapper. Establece el wrapper en 8.14.3.

Dependency ... requires libraries and applications that depend on it to compile against version 36. compileSdkVersion sigue siendo 35 en algún lugar. Revisa variables.gradle y cualquier plugin que lo tenga hardcodeado.

Using 'kotlinOptions' ... is an error o errores similares de Kotlin DSL. Un plugin o tu módulo de la app aún usa kotlinOptions. Actualiza el plugin o aplícale un patch hasta que salga una versión (mira cómo aplicar un patch a un plugin de Capacitor).

Xcode: No such module 'Capacitor' después de la actualización. Para CocoaPods, abre App.xcworkspace, no App.xcodeproj, and rerun bunx cap sync ios. Para SPM, usa Archivo &gt; Paquetes &gt; Restablecer caché de paquetes.

"X" plugin is not implemented on ios/android. El plugin no se sincronizó o no tiene una versión Capacitor 8 / compatible con SPM. Ejecuta bunx cap sync y lee las advertencias.

Para una lista más completa, consulta la Guía de troubleshooting de iOS de Capacitor y la Guía de troubleshooting de Android. Las versiones incompatibles de core y plugins se tratan en solucionar errores de desajuste de versión de Capacitor.

Deja que un agente de IA haga lo aburrido

Si usas Claude Code, Cursor o un agente similar, las Capgo Skills abiertas incluyen capacitor-app-upgrade-v7-to-v8 y capacitor-app-upgrades para saltos entre versiones mayores. Instálalas con bunx skills add Cap-go/capgo-skills y pídele al agente que actualice la app. Ejecuta el migrador y luego revisa los pasos que CLI suele omitir, como la sintaxis de Gradle, las opciones de Kotlin y las imágenes de CI.

Qué viene después

Capacitor 9 ya está en prerelease. Una vez que estés estable en la 8, lee Preparándote para Capacitor 9 para que la próxima actualización sea más ligera.

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.