EAS Build та профілі збірки
EAS Build та профілі збірки
Що таке EAS і навіщо він потрібен
Коли ваш застосунок готовий до тестування або публікації — потрібно зібрати нативний бінарний файл: .ipa для iOS, .apk або .aab для Android. До появи EAS це означало:
- Налаштування Mac із Xcode (для iOS), Android Studio і Java SDK.
- Ручне управління сертифікатами підписування, provisioning profiles, keystores.
- Складна конфігурація CI/CD pipeline.
- Неможливість зібрати iOS-застосунок без Mac.
EAS Build (Expo Application Services Build) — хмарний сервіс збірки від Expo, що вирішує всі ці проблеми:
- Збірка відбувається на хмарних серверах Expo (macOS для iOS, Linux для Android).
- Автоматичне управління сертифікатами і provisioning profiles.
- Єдиний конфіг (
eas.json) для всіх типів збірки. - Інтеграція з GitHub для автоматичних збірок при push.
Але EAS — це не тільки Build. Це екосистема сервісів:
EAS Build
EAS Submit
EAS Update
EAS Workflows
Встановлення та ініціалізація
EAS CLI
npm install -g eas-cli
# Перевірити версію:
eas --version
Авторизація
eas login
# Введіть email і пароль від expo.dev
# Або:
eas whoami # перевірити поточного користувача
Підключення проєкту до EAS
# Ініціалізація EAS у проєкті (створює eas.json і прив'язує до expo.dev):
eas build:configure
Ця команда:
- Запитує платформу (iOS, Android, або обидві).
- Створює файл
eas.jsonз базовими профілями. - Прив'язує проєкт до вашого облікового запису Expo.
- Додає
extra.eas.projectIdуapp.json.
Після виконання:
{
"expo": {
"extra": {
"eas": {
"projectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
eas.json: структура і схема
Загальна схема
eas.json — центральний конфігураційний файл EAS. Він складається з трьох секцій:
{
"cli": {
"version": ">= 14.0.0",
"appVersionSource": "remote"
},
"build": {
"development": { /* ... */ },
"preview": { /* ... */ },
"production": { /* ... */ }
},
"submit": {
"production": { /* ... */ }
}
}
eas-cli, необхідна для цього конфігу. Захищає від запуску зі старою CLI.versionCode/buildNumber:'local'— уapp.json(дефолт). Ви відповідаєте за інкрементацію.'remote'— на серверах EAS. Рекомендовано. EAS автоматично інкрементує приautoIncrement: true.
development, preview, production).eas submit — публікації в App Store/Google Play.Три стандартні профілі збірки
development: для розробки
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": false
},
"env": {
"APP_ENV": "development",
"API_URL": "http://localhost:3000"
}
}
}
}
true — збірка включає expo-dev-client (Development Client). Це кастомний Expo Go, що підтримує будь-які нативні модулі вашого проєкту. Підключається до Metro Bundler для live-reload.'internal' — для внутрішнього розповсюдження (TestFlight Ad Hoc або пряме встановлення). 'store' — для публікації в магазині. Development і preview завжди 'internal'.true — збірка для iOS симулятора (.app замість .ipa). Симуляторна збірка не потребує Apple Developer Program і підписування.Constants.expoConfig.extra.Запуск development збірки:
# Android:
eas build --profile development --platform android
# iOS (на реальному пристрої):
eas build --profile development --platform ios
# iOS симулятор (локально, без хмари):
eas build --profile development --platform ios --local
preview: для тестування
Preview-профіль — для тестерів і QA. Готовий застосунок без Development Client, але без публікації в магазині:
{
"build": {
"preview": {
"extends": "production",
"distribution": "internal",
"env": {
"APP_ENV": "staging",
"API_URL": "https://staging.api.nomad.app"
},
"android": {
"buildType": "apk"
}
}
}
}
"extends": "production" означає: взяти всі налаштування production і перевизначити тільки те, що вказано.'apk' — встановлюється напряму без Google Play. 'aab' — Android App Bundle для Google Play (дефолт для production).production: для магазину
{
"build": {
"production": {
"autoIncrement": true,
"distribution": "store",
"env": {
"APP_ENV": "production",
"API_URL": "https://api.nomad.app"
},
"ios": {
"resourceClass": "m-medium"
},
"android": {
"buildType": "aab"
}
}
}
}
true— інкрементуєandroid.versionCodeіios.buildNumber'version'— інкрементуєversion(1.0.0 → 1.0.1)'buildNumber'— лише build number, не version. Потребуєcli.appVersionSource: "remote".
'm-medium' — Mac з Apple Silicon. Впливає на швидкість і вартість збірки (Free plan: лише 'ios-medium').Версіонування застосунку
Дві системи версій
Мобільний застосунок має дві незалежні системи версій, що часто плутають:
| Тип | iOS | Android | Для кого |
|---|---|---|---|
| User-facing version | version в app.json | version в app.json | Користувач (показується в магазині) |
| Build version | ios.buildNumber | android.versionCode | Магазин (технічний ідентифікатор) |
{
"expo": {
"version": "1.2.0", // ← користувач бачить "1.2.0"
"ios": {
"buildNumber": "47" // ← App Store: ця збірка #47
},
"android": {
"versionCode": 47 // ← Google Play: integer, завжди зростає
}
}
}
Правила версіонування
version (user-facing) — змінюється вручну при значущих релізах:
1.0.0→1.0.1(патч: дрібні виправлення)1.0.1→1.1.0(minor: нові функції)1.1.0→2.0.0(major: breaking changes)
buildNumber / versionCode — повинен монотонно зростати при кожному сабмішені в магазин:
- Якщо ви надіслали build #5 і він відхилений — наступний повинен бути #6, а не #5.
- Дозволено надсилати кілька build з однаковим
versionале різними build numbers (наприклад, для виправлення)
Remote versioning (рекомендовано)
{
"cli": {
"appVersionSource": "remote" // EAS зберігає лічильник на сервері
},
"build": {
"production": {
"autoIncrement": true // автоматично +1 до buildNumber/versionCode
}
}
}
appVersionSource: "remote"
EAS зберігає поточний versionCode і buildNumber на своїх серверах. Локальні значення в app.json використовуються лише як початкові.
autoIncrement: true
Перед кожною збіркою EAS автоматично збільшує лічильник. Ви більше не думаєте про versionCode вручну.
Синхронізація version (вручну)
Значення version у app.json ви змінюєте самостійно перед релізом нової версії. EAS не чіпає його при autoIncrement: true.
Перевірка поточного стану
eas build:version:get --platform android
eas build:version:get --platform ios
Ручне встановлення
eas build:version:set --platform android
# CLI запитає нове значення versionCode
Runtime Version: сумісність з OTA-оновленнями
runtimeVersion — це окрема концепція, пов'язана з EAS Update (OTA). Вона визначає сумісність JS-бандлу і нативного коду:
{
"expo": {
"runtimeVersion": {
"policy": "fingerprint" // рекомендовано: автоматичний хеш нативних залежностей
}
}
}
fingerprint — Expo автоматично обчислює хеш усіх нативних залежностей. Якщо ви додали або оновили нативний модуль — fingerprint змінюється, OTA-оновлення не встановлюється на старі збірки.
Credentials: підписування застосунку
Що таке підписування і навіщо
Перш ніж встановити або опублікувати застосунок — він повинен бути підписаний цифровим сертифікатом. Це гарантує:
- Справжність: застосунок від вказаного розробника, не підроблений.
- Цілісність: код не змінений після підписування.
На iOS і Android підписування влаштоване по-різному:
iOS підписування
Вимагає:
- Distribution Certificate (P12) — ваш особистий ключ, видає Apple
- Provisioning Profile — прив'язує додаток до сертифіката і списку дозволених пристроїв
- App Store Connect API Key — для автоматизації
Apple Developer Program: $99/рік.
Android підписування
Вимагає:
- Keystore — файл із приватним ключем (генерується раз і зберігається назавжди)
- Key Alias і паролі
- Google Play API Service Account — для автоматизації
Google Play Developer Program: $25 одноразово.
Managed Credentials (рекомендовано)
EAS може автоматично генерувати і зберігати credentials для вас:
# При першій збірці EAS запитає про credentials:
eas build --platform ios
# > No existing credentials found
# > Generate new Apple Distribution Certificate? Y
# > Generate new Provisioning Profile? Y
# Credentials збережені на серверах EAS
Або явно управляти:
# Переглянути credentials:
eas credentials
# Оновити/перегенерувати:
eas credentials --platform ios
Переваги managed credentials:
- Не потрібно передавати
.p12і.keystoreміж командою. - Автоматичне оновлення expired provisioning profiles.
- Безпечне зберігання на серверах Expo.
Local Credentials (для своїх ключів)
Якщо у вас вже є існуючий keystore або сертифікати — можна вказати їх локально:
{
"android": {
"keystore": {
"keystorePath": "./android/keystores/nomad-release.keystore",
"keystorePassword": "your-keystore-password",
"keyAlias": "nomad",
"keyPassword": "your-key-password"
}
},
"ios": {
"provisioningProfilePath": "./ios/profiles/NomadDistribution.mobileprovision",
"distributionCertificate": {
"path": "./ios/certs/distribution.p12",
"password": "your-cert-password"
}
}
}
credentials.jsonобов'язково додайте до .gitignore! Він містить приватні ключі, витік яких дозволить підробляти підписи від вашого імені. Використовуйте змінні середовища або secrets для CI/CD.Вказати credentials у eas.json
{
"build": {
"production": {
"credentialsSource": "remote", // 'remote' (EAS managed) або 'local'
"distribution": "store"
}
}
}
Internal Distribution: розповсюдження тестерам
Що таке Internal Distribution
distribution: "internal" дозволяє ділитися збіркою напряму — через QR-код або посилання — без публікації в магазині:
- iOS: Ad Hoc provisioning profile (до 100 пристроїв) або Apple Developer Enterprise.
- Android: APK-файл з прямим завантаженням або через
expo-dev-client.
# Зібрати preview і отримати QR-код для встановлення:
eas build --profile preview --platform android
Після завершення EAS надсилає email із посиланням і QR-кодом. Тестер сканує QR і встановлює застосунок.
Expo Orbit
Expo Orbit — нативний macOS застосунок для встановлення EAS Build на підключені пристрої або симулятори одним кліком:
# Встановити Orbit:
brew install --cask expo-orbit
# Або завантажити з:
# https://expo.dev/orbit
Development Client: кастомний Expo Go
Чому Development Client, а не Expo Go
Expo Go — офіційний застосунок Expo для швидкого тестування. Але він має обмеження: містить лише бібліотеки зі стандартного SDK. Якщо ваш проєкт використовує:
react-native-mapsexpo-notificationsreact-native-gesture-handler(нативна частина)stripe-react-native- Будь-який кастомний нативний модуль
...то Expo Go не підійде. Вам потрібен Development Client (також відомий як Development Build).
Expo Go
✅ Не потребує EAS або збірки
✅ Підходить для чистих Expo проєктів
❌ Лише стандартні SDK модулі
❌ Не підходить для кастомних native modules
Development Client
✅ Live reload через Metro (як Expo Go)
✅ Вбудований dev menu з інструментами
❌ Потребує однієї EAS збірки для встановлення
❌ При зміні нативних залежностей — нова збірка
Встановлення expo-dev-client
npx expo install expo-dev-client
Після встановлення — потрібна нова збірка:
eas build --profile development --platform android
# або
eas build --profile development --platform ios
Конфігурація у eas.json
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"gradleCommand": ":app:assembleDebug"
},
"ios": {
"buildConfiguration": "Debug",
"simulator": false
}
}
}
}
Робочий процес після встановлення Development Build
# 1. Встановили Development Build на пристрій (через QR або Orbit)
# 2. Запускаємо Metro Bundler:
npx expo start
# 3. На пристрої відкриваємо Development Build
# 4. Відскануємо QR-код з Metro
# 5. Застосунок запустився з live reload!
# При зміні JS-коду — auto-reload
# При зміні нативних залежностей — нова збірка через EAS
Dev Menu
Development Client включає вбудований dev menu (потряси телефон або Cmd+D у симуляторі):
- Reload JS — примусово перезавантажити бандл.
- Open Debugger — відкрити Chrome DevTools для відлагодження.
- Toggle Element Inspector — виділяти компоненти і бачити props.
- Toggle Performance Monitor — FPS і памʼять у реальному часі.
- Disconnect — відключитись від Metro.
Змінні середовища в EAS
Середовища і конфіги
Реальний застосунок має кілька середовищ: development, staging, production. Для кожного — різні API endpoint-и, ключі аналітики, налаштування.
Підхід 1: env у eas.json (build-time)
{
"build": {
"development": {
"env": { "APP_ENV": "development", "API_URL": "http://localhost:3000" }
},
"preview": {
"env": { "APP_ENV": "staging", "API_URL": "https://staging.api.nomad.app" }
},
"production": {
"env": { "APP_ENV": "production", "API_URL": "https://api.nomad.app" }
}
}
}
Ці змінні доступні під час компіляції (для Babel plugins, Metro), але не в рантаймі JS напряму.
Підхід 2: app.config.js з process.env (runtime)
export default ({ config }) => ({
...config,
extra: {
apiUrl: process.env.API_URL ?? 'http://localhost:3000',
environment: process.env.APP_ENV ?? 'development',
sentryDsn: process.env.SENTRY_DSN,
},
});
Доступ у коді:
import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig?.extra?.apiUrl;
const env = Constants.expoConfig?.extra?.environment;
Підхід 3: EAS Secrets (sensitive values)
# Додати секрет (тільки для даного проєкту):
eas secret:create --scope project --name SENTRY_DSN --value "https://xxx@sentry.io/..."
# Переглянути всі секрети:
eas secret:list
# Секрети автоматично доступні як process.env.SENTRY_DSN під час збірки
eas.json — цей файл зазвичай у git. Використовуйте eas secret:create для секретних значень.EAS Build Hooks: скрипти до і після збірки
EAS підтримує npm-скрипти, що запускаються на серверах збірки:
{
"scripts": {
"eas-build-pre-install": "echo 'Перед встановленням залежностей'",
"eas-build-post-install": "echo 'Після npm install'",
"eas-build-on-success": "echo 'Збірка успішна!'",
"eas-build-on-error": "echo 'Збірка провалена'"
}
}
Типові використання:
eas-build-pre-install— перевірка змінних середовища, завантаження конфігів.eas-build-post-install— генерація файлів (наприклад,src/config.tsз ENV vars).eas-build-on-success— відправка Slack-повідомлення, оновлення версії в JIRA.
Міні-проєкт: preview profile + internal build для Nomad
Завдання
- Налаштувати
eas.jsonз трьома профілями для Nomad. - Зібрати preview збірку для Android (APK).
- Переконатись що credentials налаштовані.
- Опціонально: зібрати iOS збірку для внутрішнього тестування.
Крок 1: фінальний eas.json для Nomad
{
"cli": {
"version": ">= 14.0.0",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": {
"APP_ENV": "development"
},
"android": {
"gradleCommand": ":app:assembleDebug"
},
"ios": {
"buildConfiguration": "Debug"
}
},
"preview": {
"extends": "production",
"distribution": "internal",
"env": {
"APP_ENV": "staging"
},
"android": {
"buildType": "apk"
}
},
"production": {
"autoIncrement": true,
"distribution": "store",
"env": {
"APP_ENV": "production"
},
"android": {
"buildType": "aab"
},
"ios": {
"resourceClass": "m-medium"
}
}
},
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "internal"
},
"ios": {
"appleId": "your@email.com",
"ascAppId": "1234567890"
}
}
}
}
Крок 2: app.config.js для Nomad
const IS_DEV = process.env.APP_ENV === 'development';
const IS_STAGING = process.env.APP_ENV === 'staging';
export default ({ config }) => ({
...config,
name: IS_DEV ? 'Nomad (Dev)' : IS_STAGING ? 'Nomad (Staging)' : 'Nomad',
slug: 'nomad',
version: '1.0.0',
icon: IS_DEV ? './assets/icon-dev.png' : './assets/icon.png',
extra: {
apiUrl: IS_DEV
? 'http://localhost:3000'
: IS_STAGING
? 'https://staging.api.nomad.app'
: 'https://api.nomad.app',
environment: process.env.APP_ENV ?? 'development',
eas: { projectId: 'your-project-id-here' },
},
});
name і icon також змінюються залежно від середовища. Це дозволяє мати одночасно встановлені Dev, Staging і Production версії застосунку — вони виглядають по-різному і не конфліктують.Крок 3: збірка preview для Android
# Запустити preview збірку:
eas build --profile preview --platform android
# Якщо credentials не налаштовані — EAS запросить:
# > No Android credentials found. Create a new keystore? (Y)
# Після завершення (~5-10 хв) отримаєте:
# ✓ Build finished. APK available at: https://expo.dev/artifacts/...
# ✓ QR code for download (scan with Android camera)
Крок 4: перевірка версіонування
# Переглянути поточний versionCode:
eas build:version:get --platform android
# Встановити початкове значення:
eas build:version:set --platform android
# > Enter versionCode: 1
Структура команд EAS Build
# Основні команди:
eas build --profile <name> --platform <android|ios|all>
eas build:list # список всіх збірок проєкту
eas build:view <id> # деталі конкретної збірки
eas build:cancel <id> # скасувати збірку
# Версіонування:
eas build:version:get --platform <android|ios>
eas build:version:set --platform <android|ios>
# Credentials:
eas credentials
eas credentials --platform ios
eas credentials --platform android
# Secrets:
eas secret:create --scope project --name KEY --value value
eas secret:list
eas secret:delete --name KEY
Підключення до Nomad: chore: eas build profiles
Для Nomad рекомендований workflow:
- development — для щоденної розробки з Development Client.
- preview — кожного тижня або перед feature release для QA.
- production — при релізі нової версії.
Поширені помилки
npm install -g eas-cli. Якщо встановлено через npx — використовуйте npx eas ....eas credentials --platform ios і виберіть варіант генерації. Для simulator-збірки (ios.simulator: true) credentials не потрібні.autoIncrement: true без cli.appVersionSource: "remote" не працює. Обидва поля обов'язкові. Перевірте що вони разом у eas.json.eas build:view <id> або перейдіть на expo.dev → Projects → Builds → виберіть збірку → Logs.app.config.js правильно читає APP_ENV і повертає відповідний URL.expo-dev-client і зберіть development build через EAS.Підсумок
eas.json профілі
development—developmentClient: true,distribution: internalpreview—extends: production,internal, APK для Androidproduction—autoIncrement: true,store, AAB для Androidextendsдля уникнення дублювання
Versioning
version— user-facing (semantic, вручну)buildNumber/versionCode— технічний, зростаєappVersionSource: "remote"+autoIncrement: trueruntimeVersion: fingerprintдля OTA-сумісності
Credentials
- Managed (EAS) — рекомендовано, автоматично
- Local (
credentials.json) — для існуючих ключів eas credentialsдля перегляду і управління- Secrets для чутливих ENV-значень
Development Client
expo-dev-client= кастомний Expo Go- Підтримує будь-які нативні модулі
- Dev Menu (потряс або Cmd+D)
- Expo Orbit для швидкого встановлення
eas submit.Доступність та інтернаціоналізація
VoiceOver, TalkBack, accessibilityLabel, ролі, touch targets, dynamic type та рядки UA з expo-localization у React Native
Вступ до штучного інтелекту та машинного навчання
Що таке AI, ML та Data Science, чим вони відрізняються, як комп'ютер навчається на даних — без формул, але з ясними аналогіями та хронологією розвитку від 1950 до ChatGPT