javascript

Capacitor: от веба к мобильным приложениям. Часть 1. Миграция проекта на Capacitor

  • среда, 28 января 2026 г. в 00:00:09
https://habr.com/ru/articles/989296/

В первой части цикла мы разобрались, зачем вообще нужен Capacitor и почему он стал адекватным выбором для кроссплатформенной разработки.

Теперь переходим к самому болезненному и интересному этапу: миграции уже существующего веб-приложения.

Оглавление

Преимущества перехода на Capacitor для существующего проекта

Повторное использование текущего кода

Главное преимущество: код не переписывается.

  • React остается React;

  • бизнес-логика, API-клиенты, сторы, формы и UI остаются прежними.

Если приложение уже адаптивное, большая часть работы выполнена заранее.

Минимальный порог входа для команды

Команда продолжает работать в привычном SPA или SSR-стеке.
Нет необходимости срочно изучать Swift, Kotlin или особенности нативных UI-фреймворков.

Контроль над нативной частью

  • Capacitor создает полноценные iOS и Android проекты;

  • не скрывает Xcode и Android Studio;

  • позволяет писать нативный код напрямую при необходимости.

Это принципиальное отличие от Cordova, где нативная часть чаще всего выглядела как «черный ящик».

Актуальность и поддержка платформ

Capacitor обновляется синхронно с:

  • iOS SDK;

  • Android SDK;

  • требованиями App Store и Google Play.

Это снижает риск внезапно оказаться с приложением, которое больше нельзя собрать или опубликовать.

Недостатки и ограничения

Если проект раньше использовал Cordova

Для таких проектов Capacitor чаще всего является логичным следующим шагом, но не без нюансов.

Что становится лучше по сравнению с Cordova

  • нет динамической загрузки плагинов;

  • нативные проекты полностью доступны для правок;

  • плагины используют современные API;

  • обновления iOS и Android переживаются заметно проще.

На что стоит обратить внимание при миграции

  • Cordova-плагины не совместимы напрямую с Capacitor;

  • часть функциональности придется заменить официальными плагинами Capacitor;

  • кастомные плагины потребуется переписать.

Зато итоговая архитектура получается более стабильной и предсказуемой.

Пример миграции старого React + Webpack проекта

Имеем:

  • старое React-приложение на Webpack;

  • Node.js версии 16;

  • проект без SSR;

  • сборка отдает статические файлы.

Выбор версии Capacitor

Важно: версия Capacitor должна быть совместима с Node.js проекта.

Для Node.js 16:

  • рекомендуется использовать Capacitor 5 или 6;

  • Capacitor 7 ориентирован на более свежие версии Node.js.

Актуальная таблица совместимости:

Версия Capacitor

Минимальная Node.js

Рекомендуемая Node.js

Комментарий

Capacitor 7

18.x

18.x / 20.x

Актуальная версия для новых проектов

Capacitor 6

16.x

18.x

Компромисс для legacy-проектов

Capacitor 5

14.x

16.x

Часто встречается в старых проектах

Capacitor 4

14.x

16.x

Постепенно устаревает

Capacitor 3

12.x

14.x

Legacy

Capacitor 2

10.x

12.x

Фактически мертв

Установка Capacitor

Для Node.js 16 выбираем Capacitor 6 и Capacitor cli 5:

npm install @capacitor/core@6 @capacitor/android@6 @capacitor/ios@6
npm install -D @capacitor/cli@5
npx cap init

В процессе инициализации:

  • указываем название приложения:

    Наименование приложения
    Наименование приложения
  • указываем appId приложения:

appId приложения
appId приложения

В конечном итоге создастся файл capacitor.config.ts со следующим содержанием:

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

const config: CapacitorConfig = {
  appId: 'ru.smartlamp',
  appName: 'smart_lamp-front',
  webDir: 'build',
  server: {
    androidScheme: 'https'
  }
};

export default config;

Убедитесь, что:

  • npm run build создает статические файлы;

  • приложение корректно открывается без сервера.

Если директория сборки у вас отличается от build то поменяйте ее.

Затем нужно создать директории самих нативных проектов:

npx cap add android
npx cap add ios

После выполнения этих команд у нас появляются 2 директории:

Директории нативных проектов
Директории нативных проектов

Что делать, если проект использует SSR (Next.js)

Capacitor загружает статические файлы в WebView.
Классический SSR:

  • требует Node.js сервера;

  • рендерит HTML на лету.

Основные стратегии

Static export

Если SEO внутри мобильного приложения не критичен:

next build
next export

На выходе получаем статический билд, полностью совместимый с Capacitor.

Разделение веб и мобильной сборки

  • веб-версия остается с SSR;

  • мобильная версия работает как SPA или SSG.

Перед тем как рассказать про минимальную настройку Android studio и Xcode считаю необходимым показать сводные таблицы совместимости OC и IDE с версией Capacitor:

Capacitor совместимость версий IDE
Capacitor совместимость версий IDE

И Версий iOS и Android:

Capacitor совместимость версий OS
Capacitor совместимость версий OS

Это нам понадобится при выполнении дальнейших шагов. Далее я коротко опишу минимальную настройку под разные системы.

Для разработки и сборки iOS приложения Вам в любом случае понадобится устройство на macOS (нет, через эмулятор или виртуалку не получится).

Настройка Android Studio

Capacitor требует:

  • Android Studio;

  • Android SDK;

  • Android Emulator.

Установка

  1. Скачать Android Studio с официального сайта.

  2. Установить Android SDK через SDK Manager.

  3. Создать виртуальное устройство (AVD).

После скачивания и установки Android Studio Вам нужно открыть директорию android вашего приложения

IDE с открытой директорией проекта
IDE с открытой директорией проекта

Дальше как правило происходят вещи от которых никуда не деться, а именно всевозможные ошибки совместимости версий Java, Gradle (сборщик) и т.д.

Это не означает что вы обязательно сталкнетесь с проблемами, но в нашем случае основная проблема:

  • Несовместимая версия Gradle

В таком случае Android studio сам предлагает повысит версию до совместимой. Из предложенных на скриншоте вариантов Я бы посоветовал выбрать самую последнюю версию, а именно 8.10. Сам выбрал что-то посредине, а именно 8.7.

После того как Вы, если это конечно будет необходимо, установите нужную версию Gradle должна произойти синхронизация проекта.

Синхронизация
Синхронизация

После успешной синхронизации IDE выведет что-то подобное:

Успешная сборка
Успешная сборка

Если в процессе у Вас что-то пошло не так, спросите у chatGPT или Google. Как правило ошибки распространенные. Возможно что-то связанное с ОС или с версией Java (если она у Вас есть, если нет поставьте).

Далее есть два варианта:

  • Установить эмулятор устройства

  • Подключить по USB к ПК физическое устройство

В первом случае вам нужно зайти в меню устройств в IDE, нажать добавить устройство и выбрать любое понравившееся вам устройство. В нашем случае я выбрал Pixel 9. И установить эмулятор:

Pixel 9 emulator
Pixel 9 emulator

Во втором случае подключайте Android устройство по USB, но перед этим устройство нужно подготовить к отладке.

Перед запуском мобильного приложение нужно запустить dev сервер. В моем случае это делается через react-scripts в Вашем может быть что угодно, но главное тут соблюсти несколько вещей:

  • Общий порт

  • Общий ip адресс

На Windows узнать свой IP можно выполнив команду:

ipconfig

На MacOS/Linux выполнив:

ifconfig | grep inet

После чего запускаете свой dev сервер на этом IP и на любом порте.

Теперь можно запускать мобильной приложение выполнив:

npx cap run android --host 'ваш ip' --port 'такой же как запущенного dev сервера'

И вы должны увидеть работающее приложение в эмуляторе:

Pixel 9 emulator app
Pixel 9 emulator app

Настройка Xcode

Требования

  • macOS;

  • установленный Xcode совместимой версии;

  • Xcode Command Line Tools;

  • Возможно понадобится установка CocoaPods;

После того как мы выполнили npx cap add ios в прошлых шагах, мы можем открыть открыть наш проект в xcode, но перед этим мы дожны убедиться в совместимости версий.

Далее выполняем команду:

npx cap open ios

Откроется проект в Xcode. Если все хорошо то далее можем выполнить команду:

npx cap run ios --host 'ваш ip' --port 'такой же как запущенного dev сервера'

Dev сервер при этом должен быть запущен. После запуска этой команды мы получаем долгожданный результат:

Iphone 16 pro app
Iphone 16 pro app

Минимальная сборка под Android

Для сборки apk файла нашего приложения нам понадобится файл подписи приложения.

Создать его можно 2 способами:

Самый простой способ через терминал

keytool -genkeypair -v \
  -keystore habr-capacitor.jks \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -alias habr-capacitor

Нужно будет указать:

  • Пароль keystore;

  • Имя, организация и т.д. — можно писать что угодно;

  • Пароль ключа — можно такой же, можно другой;

На выходе нужный нам файл habr-capacitor.jks.

Как подключить к проекту

Обычно кладут в android/app/.

Обновляем android/app/build.gradle:

apply plugin: 'com.android.application'

def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {
    namespace "ru.bast.smartlamp"
    compileSdkVersion rootProject.ext.compileSdkVersion
    defaultConfig {
        applicationId "ru.bast.smartlamp"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        aaptOptions {
             // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
             // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
            ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
        }
    }
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}

repositories {
    flatDir{
        dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
    implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
    implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
    implementation project(':capacitor-android')
    testImplementation "junit:junit:$junitVersion"
    androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
    androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
    implementation project(':capacitor-cordova-android-plugins')
}

apply from: 'capacitor.build.gradle'

try {
    def servicesJSON = file('google-services.json')
    if (servicesJSON.text) {
        apply plugin: 'com.google.gms.google-services'
    }
} catch(Exception e) {
    logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
}

Также обновляем keystore.properties в корне директории android. Я указал:

storePassword=habrcapacitor
keyPassword=habrcapacitor
keyAlias=habrcapacitor
storeFile=habr-capacitor.jks

Разумеется keystore.properties нужно добавить в .gitignore.

Важные замечания

  • Один keystore = одно приложение.

  • Потерял keystore ключ → потерял обновления в Google Play.

  • Именно поэтому имеет смысл генерировать подписи через Android Studio и хранить их на серверах Google.

После всех манипуляций мы наконец-то можем выполнить команду сборки:

cd android && ./gradlew assembleRelease

После чего наш apk файл будет лежать по пути android/app/build/outputs/apk/release.

Минимальная сборка под iOS

Сборка под iOS заключается в том чтобы создать архив и отправить его на сервера Apple для дальнейшего распространения среди различных групп пользователей, будь то тестировщики или релизный билд. Чтобы выполнить сборку и следующие шаги Вам необходимы:

  • Аккаунт Apple который будет выступать в качестве разработчика;

  • Оплаченная подписка на год в размере $100;

  • Signin сертификат который так же требует подписки;

Можно конечно сделать это и бесплатно для запуска приложения на своем смартфоне, но это как по мне сомнительная возможность.

Именно поэтому в этой статье не считаю нужным касаться дальнейшей сборки под iOS, так как рассказ выйдет довольно долгим. Более подробно про сборку готового приложения Я распишу в другой статье.

Кстати для того чтобы выложить Android приложение в Google Play тоже нужно покупать подписку, но это не запрещает создать apk файл и выложить его скажем в RuStore бесплатно или распространять его как Вам угодно.

Миграция Cordova приложения

Миграция приложения с cordova принципиально отличается от вышеприведенной инструкции лишь тем, что cordova использует специфические и зачастую старые версии Android/iOS плагинов. В общих чертах миграция такого проекта будет заключаться в следующем:

  • Установка Capacitor и т.д по инструкции

  • Аудит используемых плагинов и установка аналогов как официальных так и плагинов сообщества

  • Удаление Cordova и установка памятника

Поэтому в этой статье касаться миграции такого проекта я не буду, потому что она касается в основном работы с плагинами.

Итоги

Миграция существующего веб приложения на Capacitor — это:

  • быстрый способ выйти в мобильные сторы;

  • минимальные изменения в кодовой базе;

  • разумный компромисс между вебом и нативом.

Capacitor не идеален и не заменяет нативную разработку, но для большинства бизнес-приложений он закрывает задачу быстрее и дешевле, чем альтернативы.

В следующей статье мы разберем:

  • Установка официальных плагинов Capacitor

  • Установка community плагинов

  • Миграция с Cordova плагинов на Capacitor

  • Разработка собственного плагина

На этом у меня все. Пишите любые интересующие вас вопросы в комментарии и в личку.

Ссылки:

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Узнали ли Вы что-то новое из статьи?
33.33%Да1
66.67%Нет2
0%Не читал0
Проголосовали 3 пользователя. Воздержавшихся нет.