Перейти к содержимому

Лекция 3. Введение в Expo и React Native

Введение

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

  1. Нативная разработка — отдельный код под каждую платформу (Swift/Objective-C для iOS, Kotlin/Java для Android).
  2. Кроссплатформенная разработка — единый код, который работает на обеих платформах.

Кроссплатформенный подход экономит время и силы команды: вместо двух кодовых баз поддерживается одна. Одним из самых популярных инструментов этого направления является React Native, а на его основе построена платформа Expo, которая упрощает разработку, тестирование и публикацию приложений.

Цель лекции — разобраться, что такое React Native и Expo, из чего состоит экосистема Expo, как устроен типичный проект и как выглядит минимальное работающее приложение.

Практическая установка окружения и первый запуск проекта на вашем компьютере вынесены в практику 3 (practice_03.md). Здесь мы рассматриваем теорию и устройство проекта.


1. Что такое React Native

React Native (RN) — это фреймворк от компании Meta для создания мобильных приложений на JavaScript. Он опирается на библиотеку React, которая изначально создавалась для веба.

Ключевые идеи:

  • Один язык — JavaScript (или TypeScript). Логика приложения пишется на JS.
  • JSX — расширение синтаксиса JavaScript, позволяющее описывать интерфейс в виде «разметки» прямо в коде.
  • Компонентный подход. Интерфейс собирается из переиспользуемых компонентов (как кубики).
  • Настоящие нативные виджеты. В отличие от гибридных решений (WebView), RN не рисует интерфейс в браузере — он создаёт настоящие нативные элементы платформы.

1.1. Как RN превращает JS-компоненты в нативные виджеты

Это важный момент для понимания. Когда вы пишете <Text> или <View>, на экране появляются не HTML-теги, а реальные нативные элементы: на iOS это UIView/UILabel, на Android — android.view.View/TextView.

Связь между миром JavaScript и миром нативного кода обеспечивает специальный слой:

  • Bridge (мост) — классический механизм. JS-код и нативный код работают в разных потоках и обмениваются сообщениями в виде сериализованного JSON. Команда «создай кнопку» проходит через мост и превращается в нативный виджет.
  • JSI (JavaScript Interface) — новая архитектура RN. Она заменяет асинхронный мост на прямой синхронный вызов: JavaScript может напрямую обращаться к нативным объектам без сериализации. Это быстрее и снимает «узкое место» старого моста.
[ Ваш JS/JSX код ]
[ React (виртуальное дерево компонентов) ]
[ Bridge / JSI ] ← слой связи JS ↔ Native
[ Нативные виджеты iOS / Android ]

Для нас на этом курсе достаточно понимать: вы пишете на JavaScript, а пользователь видит настоящий нативный интерфейс.


2. Что такое Expo

Expo — это платформа и набор инструментов поверх React Native. Если RN — это «двигатель», то Expo — это «удобная машина вокруг него»: готовая сборка, набор инструментов и библиотек.

Главная ценность Expo — быстрый старт: можно начать разработку без установки Xcode и Android Studio и сразу запустить приложение на своём телефоне.

2.1. Экосистема Expo

Экосистема состоит из нескольких частей:

  • Expo CLI — инструмент командной строки для создания, запуска и управления проектом (create-expo-app, expo start).
  • Expo Go — мобильное приложение для iOS и Android. Позволяет запускать ваш проект на реальном устройстве без компиляции — достаточно отсканировать QR-код.
  • Expo SDK — большой набор готовых модулей для работы с устройством: камера (expo-camera), геолокация (expo-location), уведомления (expo-notifications), сенсоры (expo-sensors) и многое другое.
  • EAS (Expo Application Services) — облачные сервисы для сборки готовых приложений (EAS Build), отправки в App Store / Google Play (EAS Submit) и обновлений (EAS Update).
  • OTA-обновления (Over-The-Air) — возможность доставлять обновления JavaScript-части приложения пользователям без повторной публикации в магазинах.

2.2. Преимущества Expo

  • быстрый старт без нативных IDE (Xcode/Android Studio);
  • единый код для iOS и Android;
  • большой набор готовых модулей в Expo SDK;
  • удобное тестирование на устройстве через Expo Go;
  • облачные сборки и OTA-обновления;
  • большое сообщество и документация.

2.3. Ограничения Expo

  • не все нативные библиотеки совместимы из коробки — иногда нужны development builds или переход на «bare» workflow;
  • размер приложения может быть больше, чем у «чистого» нативного;
  • зависимость от экосистемы и версий Expo SDK;
  • для очень специфичных нативных задач может потребоваться писать нативный код.

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


3. Структура типичного Expo-проекта

После создания проекта командой npx create-expo-app появляется набор файлов и папок. Рассмотрим ключевые из них.

my-app/
├── app/ // экраны при использовании expo-router (file-based routing)
│ ├── _layout.tsx // корневой layout (обёртка навигации)
│ └── index.tsx // главный экран ("/")
├── assets/ // картинки, шрифты, иконки
├── components/ // переиспользуемые компоненты (опционально)
├── node_modules/ // установленные зависимости (не редактируется вручную)
├── App.js // точка входа в "классическом" шаблоне
├── app.json // конфигурация приложения (имя, иконка, версия...)
├── babel.config.js // настройка транспайлера Babel
├── package.json // зависимости и скрипты проекта
└── tsconfig.json // настройки TypeScript (если используется TS)

3.1. Ключевые файлы

package.json — «паспорт» проекта. Содержит список зависимостей и скрипты запуска:

{
"name": "my-app",
"version": "1.0.0",
"main": "expo-router/entry",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios"
},
"dependencies": {
"expo": "~51.0.0",
"react": "18.2.0",
"react-native": "0.74.0"
}
}

Поле main указывает точку входа приложения. В классическом шаблоне это App.js, а при использовании expo-router — специальный модуль expo-router/entry.

app.json (или app.config.js) — конфигурация самого приложения: имя, slug, версия, иконка, splash-экран, ориентация экрана, настройки платформ.

{
"expo": {
"name": "My App",
"slug": "my-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"backgroundColor": "#ffffff"
}
}
}

Вариант app.config.js нужен, когда конфигурацию надо строить динамически (например, читать значения из переменных окружения).

App.js / app/_layout — главный компонент приложения.

  • В классическом шаблоне корневой компонент описывается в App.js.
  • В шаблоне с expo-router используется папка app/, где каждый файл — это экран, а _layout задаёт общую обёртку (навигацию). Маршруты строятся по структуре файлов (file-based routing), как в Next.js.

assets/ — статические ресурсы: изображения, иконки, шрифты. На них ссылаются из app.json и из кода.

babel.config.js — настройка Babel, инструмента, который преобразует современный JS/JSX в код, понятный движку. Для Expo обычно содержит пресет babel-preset-expo:

module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};

node_modules/ — папка с установленными библиотеками. Её не редактируют руками и не добавляют в систему контроля версий.


4. Запуск проекта (кратко)

Полный разбор установки и запуска — в практике 3. Здесь — общая последовательность, чтобы видеть картину целиком.

  1. Создание проекта:
Окно терминала
npx create-expo-app my-app
cd my-app
  1. Запуск сервера разработки:
Окно терминала
npx expo start

После запуска в терминале появляется QR-код и адрес локального сервера (Metro bundler).

  1. Открытие на устройстве:
  • установите приложение Expo Go на телефон;
  • отсканируйте QR-код камерой (iOS) или внутри Expo Go (Android);
  • приложение откроется и будет обновляться вживую при изменении кода (Fast Refresh).

Альтернативно можно запустить на эмуляторе Android или симуляторе iOS клавишами a / i в терминале.


5. Разбор простого приложения

Рассмотрим минимальное работающее приложение — счётчик. Это пример классического шаблона с корневым компонентом App.

// App.js — точка входа приложения
import { useState } from 'react';
import { Text, View, Button, StyleSheet } from 'react-native';
// Корневой компонент. export default делает его точкой входа.
export default function App() {
// useState создаёт состояние count с начальным значением 0
const [count, setCount] = useState(0);
// Компонент возвращает дерево JSX, которое будет отрендерено
return (
<View style={styles.container}>
<Text style={styles.title}>Привет, Expo!</Text>
<Text>Счётчик: {count}</Text>
<Button title="Увеличить" onPress={() => setCount(count + 1)} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
});

5.1. Что здесь происходит

  • Точка входа. Expo загружает модуль, указанный в package.json (main). В классическом шаблоне это App.js, который экспортирует по умолчанию (export default) корневой компонент App.
  • Корневой компонент. Функция App — это функциональный компонент. Она возвращает JSX — описание интерфейса.
  • Рендер. RN берёт это описание, строит виртуальное дерево компонентов и превращает его в нативные виджеты на экране.
  • View — базовый контейнер (аналог div в вебе), организует расположение элементов.
  • Text — элемент для отображения текста. В RN любой текст должен находиться внутри <Text>.
  • Button — кнопка с обработчиком события onPress.
  • useState — хук, который хранит состояние. При вызове setCount компонент перерисовывается с новым значением.
  • StyleSheet — способ описывать стили. Используется Flexbox и свойства, похожие на CSS (flex, justifyContent, alignItems, fontSize).

5.2. То же приложение в стиле expo-router

Если проект создан с expo-router, главный экран лежит в app/index.js, а корневая обёртка — в app/_layout.js:

// app/_layout.js — корневой layout, описывает навигацию
import { Stack } from 'expo-router';
export default function Layout() {
return <Stack />;
}
// app/index.js — главный экран по маршруту "/"
import { useState } from 'react';
import { Text, View, Button } from 'react-native';
export default function Home() {
const [count, setCount] = useState(0);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Счётчик: {count}</Text>
<Button title="Увеличить" onPress={() => setCount(count + 1)} />
</View>
);
}

Разница только в организации файлов: при file-based routing каждый файл в app/ автоматически становится экраном, а точкой входа служит expo-router/entry.


Краткие итоги

  • React Native — фреймворк для создания мобильных приложений на JavaScript; интерфейс собирается из компонентов и превращается в настоящие нативные виджеты iOS/Android.
  • Связь между JS и нативным кодом обеспечивает мост (bridge), а в новой архитектуре — JSI (прямой синхронный доступ без сериализации).
  • Expo — платформа поверх RN для быстрого старта. Экосистема: CLI, Expo Go, Expo SDK, EAS, OTA-обновления.
  • Плюсы Expo — быстрый старт, единый код, готовые модули; минусы — ограничения с некоторыми нативными библиотеками и зависимость от экосистемы.
  • Ключевые файлы проекта: package.json (зависимости и точка входа), app.json/app.config (конфигурация), App.js или app/_layout (корневой компонент), assets/, babel.config.js.
  • Запуск: create-expo-appexpo start → Expo Go по QR-коду (подробности в практике 3).
  • Минимальное приложение состоит из точки входа, корневого компонента и возвращаемого им JSX, который рендерится в нативный интерфейс.

Вопросы для самопроверки

  1. Что такое React Native и как он связан с библиотекой React? Чем нативные виджеты отличаются от гибридного (WebView) подхода?
  2. Для чего нужен мост (bridge) в React Native и в чём преимущество архитектуры JSI?
  3. Из каких частей состоит экосистема Expo (CLI, Expo Go, SDK, EAS, OTA) и какие задачи решает каждая из них? Назовите ключевые файлы проекта Expo и их назначение.