Полка React Native и Expo: цена пакета — в клиенте, а не в килобайтах

пакеты≈ 14 минут

Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.

Снимок: сентябрь 2026, Expo SDK 57. Своими руками в этой части собраны окно списка, анимация на кадрах, worklet, маршруты со стеком и диск под памятью. У каждой миниатюры есть стена, и за стеной — пакет из npm. Но на телефоне цена пакета считается не в килобайтах, а в клиенте: пакет из SDK работает в Expo Go, чужой нативный — только в своей сборке. И версию нативного пакета выбираете не вы, а SDK. Версии на полке — снимок на дату проверки, а не вечная истина; как проверить строку самому, разбирает статья «Живой ли пакет».

Разделы темы:·

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

ЗадачаСначалаЕсли мало
навигацияexpo-router из SDKReact Navigation напрямую — только в проекте без Expo
ключ-значение и секретыexpo-sqlite/kv-store и expo-secure-storereact-native-mmkv ценой своей сборки
база на устройствеexpo-sqliteop-sqlite или PowerSync
серверные данныев local-first — ничего: правда в SQLiteTanStack Query и Zustand, как в вебе
анимация и жестыAnimated с useNativeDriverReanimated и gesture-handler
длинные спискиFlatList после замераFlashList или LegendList
камера и медиаexpo-image-pickerexpo-camera; VisionCamera — если нужны сами кадры
клавиатураKeyboardAvoidingViewreact-native-keyboard-controller

У полок для браузера отметка «что умеет платформа» — это Baseline, поддержка во всех основных браузерах. Здесь такого мерила нет: платформа телефона — React Native 0.86 и модули SDK 57, и столбец «Сначала» состоит из них.

В таблицах-снимках ниже столбец «Вес или цена» заполнен ценой, а не килобайтами. JavaScript пакета, конечно, едет в бандле, но раньше веса решает другое: заработает ли пакет в том клиенте, который у вас есть, — об этом следующий раздел. Столбец «Версия» — закрепление SDK 57 на сервере Expo на 14.09.2026, а не последняя версия в npm; последняя записана в цене, если отличается. У пакетов, которых SDK не знает, версия — последняя в npm.

Строка полки стареет не по календарю, а по событию: вышел новый SDK, модуль попал в Expo Go, в npm сменился мажор. Поэтому у каждого паспорта своё «Пересмотреть, если…».

Цена пакета на телефоне складывается из ответов на три вопроса, и у каждого ответа свой источник. Первый: знает ли пакет SDK — есть ли он в списке закреплений, где записано, какую версию ждёт данный SDK. Второй: есть ли у пакета нативная половина — код для iOS и Android в его архиве npm. Третий: вшит ли его модуль в Expo Go.

Третий вопрос решает бинарник, а не npm install. Модуль ищется по имени в реестре — «Модуль — это запись в реестре», — и найдётся, только если его вшили при сборке. Как это выглядит в Expo Go и в своей сборке, разобрано в «Expo Go — чужой бинарник с вашим бандлом»; там же вы запускали отказ AppMetrica.

Сведём три вопроса в одну функцию. Данные в ней записанные: выдержка из bundledNativeModules.json пакета expo 57.0.16, который стоит в проекте автора, выдержка из списка модулей Expo Go для SDK 57 и признак нативной половины по файлам архивов npm. Закрепление в таком списке — точная версия или диапазон с тильдой, тем же знаком, что в диапазонах npm. Пакетов семь: первые четыре стоят в apps/mobile, последние три читатель собирается поставить обычным npm install, то есть последних версий. Строка AppMetrica в выводе — напоминание о том запуске, новое здесь — версии. Прогноз: у каких пакетов функция найдёт расхождение с SDK и в какую сторону?

rn
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
экран примера

Расхождения бывают в обе стороны. react-native и react-native-screens в проекте старше закреплений. react-native-reanimated и @shopify/flash-list из npm, наоборот, новее — и для проверки Expo это такое же расхождение: последняя версия не значит подходящая. zustand SDK не знает, и ему не нужно: в пакете только JavaScript. А react-native-mmkv SDK не знает, нативная половина у него есть, а в Expo Go её нет — вместе с AppMetrica он и требует своей сборки.

Две верхние строки можно сверить с настоящим CLI. Переменная CI=1 нужна, чтобы команда только читала: без неё CLI в терминале спросит, не исправить ли версии сразу. В проекте автора, без сети:

shлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.
вывод · терминал, apps/mobile, expo 57.0.16, @expo/cli 57.0.18, 14.09.2026
Dependency validation is unreliable in offline-mode
The following packages should be updated for best compatibility with the installed expo version:
react-native@0.86.0 - expected version: 0.86.2
react-native-screens@4.25.2 - expected version: ~4.26.0
Your project may not work correctly until you install the expected versions of the packages.
Found outdated dependencies

Те же два пакета и те же версии. А теперь та же команда с сетью:

shлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.
вывод · терминал, apps/mobile, expo 57.0.16, список SDK 57 с сервера Expo, 14.09.2026
The following packages should be updated for best compatibility with the installed expo version:
@expo/metro-runtime@57.0.13 - expected version: ~57.0.15
expo@57.0.16 - expected version: ~57.0.22
expo-build-properties@57.0.14 - expected version: ~57.0.17
expo-constants@57.0.14 - expected version: ~57.0.18
expo-device@57.0.1 - expected version: ~57.0.2
expo-image-picker@57.0.13 - expected version: ~57.0.17
expo-linking@57.0.7 - expected version: ~57.0.10
expo-notifications@57.0.14 - expected version: ~57.0.18
expo-router@57.0.16 - expected version: ~57.0.21
expo-secure-store@57.0.1 - expected version: ~57.0.4
expo-splash-screen@57.0.8 - expected version: ~57.0.9
expo-updates@57.0.17 - expected version: ~57.0.22
react-native@0.86.0 - expected version: 0.86.3
react-native-screens@4.25.2 - expected version: ~4.26.0
Your project may not work correctly until you install the expected versions of the packages.
Found outdated dependencies

Четырнадцать строк вместо двух, и react-native теперь ждёт не 0.86.2, а 0.86.3. Причина — в исходнике @expo/cli 57.0.18, в функции getVersionedNativeModulesAsync. Без EXPO_OFFLINE CLI берёт список SDK с сервера Expo, а с ней — или если сервер не ответил — файл bundledNativeModules.json из установленного expo. Файл — снимок того патча, что стоит в проекте: 57.0.16 от 24.08.2026. Сервер — живой список, и на 14.09.2026 он знает патчи до expo 57.0.22. Поэтому функция выше, записанная по файлу, ждёт 0.86.2, а таблицы-снимки ниже пишут закрепления сервера — у react-native это 0.86.3.

Вопроса «работает ли пакет на новой архитектуре» среди трёх нет, и это не забыто. В React Native 0.86 старую архитектуру не включить — это видно в таблице «Что осталось от моста в 0.86», — поэтому в SDK 57 выбирать не из чего. Пометка «только новая архитектура» в README FlashList 2 и в ошибке Reanimated 4 — цена переезда для проекта на SDK 54: он держит React Native 0.81.5, последнюю линию, где старая архитектура ещё собиралась.

У функции есть и стена: в её данных нет поля peerDependencies. В этом поле пакет называет соседей, с которыми работает, но которых в себе не везёт; подробнее — в статье «Живой ли пакет», в вопросе о доле в нише. У react-native-reanimated 4.6.0 там записан react-native-worklets 0.12.x, а SDK 57 держит worklets 0.10.1. Поставить из npm одну библиотеку пары — значит разбить пару, и функция этого не заметит. Научить её — первая задача в конце статьи.

npm install меняет только JavaScript-половину. Всё, что пакет ищет в бинарнике, должно было попасть туда при сборке — в Expo Go его вшила команда Expo, в свою сборку вшиваете вы.

Что версии библиотек сообщества под SDK подбирает npx expo install, говорилось ещё в «Трёх этажах». Подбирать есть что: последняя версия в npm и версия, которую ждёт SDK, — разные числа. Вот как далеко на 14.09.2026 они разошлись у пакетов этой полки:

ПакетПоследняя в npmSDK 57 держит
react-native0.87.10.86.3
react-native-reanimated4.7.14.5.1
react-native-worklets0.13.0; ветка 0.10 — под тегом legacy, 0.10.40.10.1
react-native-gesture-handler3.3.0; ветка 2 — под тегом legacy, 2.33.0~2.32.0
react-native-keyboard-controller1.22.51.21.9
@react-native-async-storage/async-storage3.1.12.2.0
@shopify/flash-list2.3.22.0.2 — как и в SDK 54, 55, 56 и 58

Отсюда три команды. Нативный пакет ставят npx expo install <пакет>: CLI допишет к имени версию из списка SDK. Расхождения в уже поставленном ищут npx expo install --check, как в прошлом разделе, а правят npx expo install --fix — оба флага есть в справке @expo/cli 57.0.18.

Две оговорки из исходника той же команды, функции getVersionedPackagesAsync. Версию, указанную руками, — npx expo install react-native-reanimated@4.7.1 — CLI не подменяет: верит вам. А пакет, которого в списке SDK нет, уходит менеджеру пакетов как есть, то есть последней версией из npm. Для такого пакета диапазон — ваш: проверять его на устройстве, помня, что старой архитектуры в SDK 57 нет, и держать запасной выход на случай, если пакет перестанет обновляться.

Закрепление меняется и внутри одного SDK. В файле expo 57.0.16 у react-native записано 0.86.2, а сервер для SDK 57 на 14.09.2026 отдаёт 0.86.3: номер SDK прежний, закрепление новое.

npm install ставит последнюю версию, npx expo install — ту, с которой собран ваш SDK. Для нативного пакета права вторая.

Начнём с темпа. В таблице — даты выпуска expo x.0.0 по реестру и версия React Native в списке каждого SDK на сервере Expo.

SDKВыпускReact Native
5328.04.20250.79.6
5410.09.20250.81.5
5525.02.20260.83.10
5620.05.20260.85.3
5730.06.20260.86.3
58preview: 58.0.0-preview.0 — 10.09.2026, 58.0.0-preview.1 — 14.09.2026, под тегом next0.88.0-rc.0

За год до снимка вышли три SDK, и каждый принёс новую линию React Native. Новый react-native — это новый бинарник: в таблице «Долетит или нужна сборка» правка «поднять react-native» меняет отпечаток. По воздуху такое обновление к установленным приложениям пускать нельзя — от этого их и бережёт замок из статьи «runtimeVersion: замок, который бережёт установленные приложения». А Expo Go из магазина собран под одну версию SDK («Свой проект»); на 14.09.2026 сервер Expo называет для него SDK 57.

SDK 58 уже виден: он в preview, и сервер Expo отдаёт его список. Что в нём ждёт пакеты этой полки:

shлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.
вывод · терминал, api.expo.dev после выхода expo 58.0.0-preview.1, Node 26.5.0, 14.09.2026
react-native 0.88.0-rc.0
react-native-gesture-handler ~3.2.1
react-native-reanimated 4.6.0
react-native-keyboard-controller 1.22.4
@shopify/flash-list 2.0.2

Список preview меняется на глазах: в тот же день, до выхода 58.0.0-preview.1, сервер отдавал для SDK 58 react-native 0.87.1, а теперь — кандидат в релиз 0.88.0-rc.0. Главная перемена для полки — react-native-gesture-handler ~3.2.1, новый мажор: по типам пакета 3.3.0 жесты в нём объявляются хуками вроде usePanGesture, а прежние объекты получили приставку Legacy — LegacyPanGesture, LegacyScrollView. Остальное — шаги внутри мажора: reanimated 4.6.0, keyboard-controller 1.22.4, а flash-list остаётся на 2.0.2.

Порядок обновления из этого и следует. Прочитать журнал изменений нового SDK — его адрес сервер Expo отдаёт сам, в поле releaseNoteUrl: у SDK 57 это expo.dev/changelog/sdk-57, а у SDK 58 в preview такого поля ещё нет. Поднять expo и выровнять остальное npx expo install --fix. Проверить проект целиком — для этого у Expo есть отдельный пакет expo-doctor: по описанию в реестре он ищет в проекте известные проблемы, запускается npx expo-doctor. Собрать новый dev client, проверить на устройстве — и только потом выпускать сборку и обновления к ней.

Пересмотреть, когда SDK 58 выйдет из preview: сверить закрепления всей полки.

Отдельная не нужна в проекте на Expo: expo-router уже в SDK. Он закреплён в SDK 57 и вшит в Expo Go, а React Navigation, на котором стоит, везёт внутри себя: в expo-router 57.0.21 это папка build/react-navigation. Пакетов @react-navigation/* в зависимостях у версий для SDK 56 и 57 нет, у версии для SDK 55 они были. Поэтому @react-navigation/native напрямую берут в React Native без Expo.

Своя сборка — глава 5: адрес из пути файла в «Собираем маршруты», история и системная «назад» в «Собираем стек экранов с историей» и сверка миниатюры с настоящим маршрутизатором — «Миниатюра остаётся в песочнице».

БиблиотекаВерсияВес или ценаПроверено
expo-router~57.0.24в SDK 57; есть в Expo Go05.10.2026

Тильда в версии — часть закрепления: SDK 57 принимает любой патч 57.0.x не ниже 24-го.

Пересмотреть с выходом SDK 58: сверить закрепление expo-router.

Не нужна для пары настроек: kv-store и SecureStore из SDK. Своя сборка: ящик строк по ключу, где каждый вызов — промис, в «Асинхронном ящике», а в разделе «Данные — в базе, токен — в SecureStore» — expo-sqlite/kv-store, замена AsyncStorage один в один, и expo-secure-store для токена.

БиблиотекаВерсияВес или ценаПроверено
expo-secure-store~57.0.4в SDK 57; есть в Expo Go14.09.2026
expo-sqlite~57.0.3в SDK 57; есть в Expo Go; kv-store внутри14.09.2026
react-native-mmkv4.3.2нет в SDK; нативный (Nitro); нужен dev client14.09.2026
@react-native-async-storage/async-storage2.2.0в SDK 57 и в Expo Go; в npm уже 3.1.114.09.2026

На полке — kv-store и SecureStore. AsyncStorage остаётся там, где он уже стоит: SDK 57 и Expo Go держат 2.2.0 при 3.1.1 в npm, поэтому ставят его только через npx expo install.

react-native-mmkv — запас на случай, когда ящика строк мало. Синхронность сама по себе не довод: у kv-store тоже есть getItemSync. Довод — то, чего у kv-store нет: хук useMMKVString(key) перерисовывает компонент, когда значение по ключу меняется, а режим multi-process в спецификации пускает к тому же хранилищу расширения приложения и фоновые службы. Четвёртая версия построена на Nitro Modules — это отдельный нативный пакет react-native-nitro-modules того же автора, и mmkv 4.3.2 требует его в peerDependencies. Ни mmkv, ни nitro-modules нет ни в списке SDK 57, ни в Expo Go (проверено 14.09.2026), поэтому цена — своя сборка, а версия — ваша.

Пересмотреть, если SDK перейдёт на async-storage 3 или mmkv попадёт в Expo Go.

Не нужна, если данные живут на сервере: хватит кеша запросов. Если же главная копия в телефоне, своя сборка — главы 6 и 7: от «Главная копия — в телефоне» до настоящей базы в «expo-sqlite: настоящая база в телефоне», а сравнение готовых движков — в таблице «Что брать и чем платить».

БиблиотекаВерсияВес или ценаПроверено
@op-engineering/op-sqlite18.2.1нет в SDK; нативный; dev client14.09.2026
@powersync/react-native2.2.1нет в SDK; нативная половина через op-sqlite; dev client14.09.2026

Первый выбор — expo-sqlite из раздела выше: он в SDK и в Expo Go. @op-engineering/op-sqlite — запас на случай, когда упираетесь в скорость: в реестре он описывает себя как самый быстрый SQLite для React Native. Цена у него видна там же: распакованный пакет весит 351,7 миллиона байт. В архиве лежат исходники SQLite и SQLCipher, а для libsql и Turso — готовые библиотеки под каждую архитектуру Android и iOS.

PowerSync — запас для синхронизации с сервером. Нативная часть самого @powersync/react-native 2.2.1 маленькая — модуль PowerSyncOpSqlite для iOS и Android, — а база под ним — op-sqlite: в peerDependencies стоит @op-engineering/op-sqlite от 17.1.0 до 19. Та же строка «нативный код» есть в таблице движков.

Пересмотреть, если PowerSync сменит нативный драйвер или expo-sqlite получит синхронизацию.

Не нужны в local-first, где правда хранится в SQLite. Своя сборка — врезка «Кеш запросов — не движок синхронизации»: там TanStack Query из проекта автора настроен правильно, и там же видно, что его clear() в local-first стирает оригинал.

Если данные всё-таки живут на сервере — общий справочник упражнений, чужие программы тренировок, — полка та же, что в вебе. TanStack Query и Zustand — чистый JavaScript: в архивах @tanstack/react-query 5.102.8 и zustand 5.0.15 нет кода для iOS и Android, поэтому Expo Go им не помеха, а SDK их не закрепляет. Где у них стены и почему на полке именно они, разобрано на полке React и Next. В проекте автора стоят оба: @tanstack/react-query 5.102.3 и zustand 5.0.15.

БиблиотекаВерсияВес или ценаПроверено
@tanstack/react-query5.102.8только JS; SDK не закрепляет14.09.2026
zustand5.0.15только JS; SDK не закрепляет14.09.2026

Пересмотреть, если TanStack Query или Zustand выпустят v6.

Не нужна для простых переходов: Animated с useNativeDriver. Своя сборка — глава 8: значение, подписка и кадр в «Собираем анимацию», описание анимации во втором потоке в «useNativeDriver: два потока», функция в другом потоке в «Worklet: функция, уехавшая в другой поток» и то, почему сам Reanimated не запускается в предпросмотре, — «Почему Reanimated нет в предпросмотре».

БиблиотекаВерсияВес или ценаПроверено
react-native-reanimated4.5.1в SDK 57 и в Expo Go; в npm 4.7.105.10.2026
react-native-worklets0.10.1в SDK 57 и в Expo Go; в npm 0.12.214.09.2026
react-native-gesture-handler~2.32.0в SDK 57 и в Expo Go; в npm 3.3.014.09.2026

Reanimated и worklets ставятся парой, и пару держит SDK. react-native-reanimated 4.5.1 просит в peerDependencies react-native-worklets 0.10.x, а 4.7.1 — уже 0.13.x (по реестру на 05.10.2026). npm install react-native-reanimated принесёт 4.7.1 к worklets 0.10.1 из SDK, и пара разбита. У gesture-handler в npm уже мажор 3, а ветка 2 живёт под тегом legacy: SDK 57 держит ~2.32.0, и хуков вроде usePanGesture в этой версии ещё нет.

Пересмотреть с выходом SDK 58: gesture-handler переходит на 3.

Не нужна, пока замер не показал проблем FlatList. Своя сборка: деление, распорки и запас в «Собираем окно», а счёт строк и вызовов — в таблице «Что на телефоне иначе», где песочница сверена с React Native 0.86.

БиблиотекаВерсияВес или ценаПроверено
@shopify/flash-list2.0.2в SDK 57; только JS; в npm 2.3.214.09.2026
@legendapp/list3.3.11нет в SDK; только JS14.09.2026

FlashList 2 и LegendList 3 — чистый JavaScript: в архивах npm @shopify/flash-list 2.0.2 и 2.3.2 и @legendapp/list 3.3.11 нет ни ios/, ни android/, ни podspec (проверено 14.09.2026). Поэтому то, что FlashList нет в списке Expo Go, ему не мешает: вшивать нечего. Версию FlashList всё равно выбирает SDK, а LegendList SDK не знает, и его версия — ваша.

Пересмотреть, если SDK поднимет закрепление flash-list выше 2.0.2.

Не нужна камера, чтобы выбрать фото: хватит пикера. Своя сборка — «Настоящий Expo: пикер, файл и отправка»: пикер отвечает адресом файла, а в SDK 57 глобальный fetch — это expo/fetch, и часть формы { uri, name, type } он отклоняет.

БиблиотекаВерсияВес или ценаПроверено
expo-image-picker~57.0.20в SDK 57; есть в Expo Go05.10.2026
expo-camera~57.0.6в SDK 57; есть в Expo Go; тег latest в npm — 57.0.605.10.2026
expo-image~57.0.5в SDK 57; есть в Expo Go14.09.2026
expo-audio~57.0.5в SDK 57; есть в Expo Go14.09.2026
expo-video~57.0.5в SDK 57; есть в Expo Go05.10.2026
react-native-vision-camera5.2.3нет в SDK; нативный; dev client14.09.2026

Всё, кроме последней строки, — модули SDK, и в Expo Go они уже есть. Но и им нужен npx expo install: тег latest в npm живёт своей жизнью, а закрепление SDK — своей (на 14.09.2026 latest у expo-camera стоял на 57.0.4, ниже закрепления, к 05.10.2026 догнал его). expo-av в этом списке больше нет: его убрали из SDK 55, и звук с видео теперь у expo-audio и expo-video — подробнее в разделе «Сошли с полки».

VisionCamera — запас для случая, когда нужны сами кадры: у react-native-vision-camera 5.2.3 есть useFrameOutput и тип Frame. Как и mmkv, пятая версия стоит на Nitro Modules — в её peerDependencies react-native-nitro-modules и react-native-nitro-image, — а в SDK её нет, так что и цена та же: своя сборка.

Пересмотреть с выходом SDK 58: сверить закрепления expo-image-picker, expo-camera, expo-image, expo-audio и expo-video.

Не нужна для одного поля: KeyboardAvoidingView. Своя сборка — «Клавиатура — ещё один нижний край»: события Keyboard, расчёт сдвига по исходнику KeyboardAvoidingView и правило, что отступ клавиатуры и отступ безопасной зоны не складывают.

БиблиотекаВерсияВес или ценаПроверено
react-native-keyboard-controller1.21.9в SDK 57 и в Expo Go; в npm 1.22.514.09.2026

react-native-keyboard-controller есть и в SDK 57, и в Expo Go, так что цена у него только в соседях: в peerDependencies стоит react-native-reanimated не ниже 3.0.0. Reanimated в SDK тоже есть, и npx expo install поставит обоих в версиях одного SDK.

Пересмотреть с выходом SDK 58: его список уже держит 1.22.4.

Эти пакеты ещё встречаются в старых проектах и ответах на форумах. У каждого — дата последнего выпуска, номер вопроса из «Живой ли пакет», на котором он отсеялся, и что брать вместо. Номера те же: 0 — не умеет ли этого платформа, 1 — жив ли пакет. На телефоне платформа — это и SDK Expo.

ПакетПоследний выпускВопросЧто вместо
expo-av16.0.8 от 05.12.20250: удалён из SDK 55; в списке SDK 54 он ещё есть, с закреплением ~16.0.8expo-audio и expo-video — раздел «Камера, медиа, файлы»
react-native-fast-image8.31.1 от 04.10.2026; до того молчал с 31.10.20220 и 1: кешировать картинки на диске умеет expo-image из SDK — у него cachePolicy по умолчанию "disk"; всплеск выпусков пакета в октябре 2026 после четырёх лет молчания — смена рук, а не повод вернутьсяexpo-image
Moti, moti0.30.0 от 29.01.20251: последний коммит в репозитории — 11.03.2025Reanimated напрямую — раздел «Анимация и жесты»
WatermelonDB, @nozbe/watermelondb0.28.0 от 07.04.20251: ни одного коммита после 11.08.2025expo-sqlite или PowerSync — раздел «База на устройстве»

WatermelonDB сошёл с полки, но не из учебника: его разбор в статье «Готовые движки: WatermelonDB и PowerSync» остаётся, и читать его стоит как устройство движка синхронизации, а не как совет, что ставить.

Сошедший пакет не обязательно выкорчёвывать завтра. Но новый код на нём не пишут, а при переходе на новый SDK его меняют первым.

Пакеты ниже живы и не помечены устаревшими. Отказ — не оценка качества. У двух первых это вопрос 4 из «Живой ли пакет»: навязывает ли пакет устройство проекта. Оговорка та же, что на полке React и Next: вопрос 4 совпадает с укладом автора — стили здесь пишутся через StyleSheet.create, — поэтому у каждой строки названа причина, которую можно проверить.

ПакетЧто провереноПочему не на полке
NativeWindnativewind 4.2.6 от 22.06.2026; в peerDependencies — tailwindcssвопрос 4: стили переезжают в разметку классами Tailwind, а учебник пишет StyleSheet.create
Tamaguitamagui 2.7.7 от 15.08.2026; описание в реестре обещает стили, компоненты и оптимизирующий компиляторвопрос 4: своя система стилей и свой компилятор — экраны проекта пишутся уже на них
Аналитика и крэши@react-native-firebase/app 26.4.0 и @appmetrica/react-native-analytics 4.2.0; в проекте автора стоят Firebase 26.3.2 и AppMetrica 4.2.0не паспорт полки: метка события, очередь, стек из прода и группы отчётов разобраны в «После релиза», а цена нативного SDK видна в функции из раздела о цене. Где сервис хранит данные пользователей — ещё и юридический вопрос; с 01.07.2025 действует Федеральный закон от 28.02.2025 № 23-ФЗ, учебник его не решает

Строка аналитики отличается от остальных: отказ здесь не пакету, а паспорту. Ставить ли SDK аналитики, решает продукт, а полка может только назвать цену: нативная половина вне Expo Go и данные пользователей на чужом сервере.

Вопрос 4 не запрещает пакет. Он предупреждает, что уйти с него — значит переписать экраны, а не поменять строку в package.json.

  • На телефоне цена пакета — клиент: знает ли пакет SDK, есть ли у него нативная половина и вшит ли модуль в Expo Go. Пакет из SDK работает в Expo Go, чужой нативный — только в своей сборке, чистый JavaScript — везде.
  • Версию нативного пакета выбирает SDK: npx expo install ставит закрепление, --check ищет расхождения, --fix их правит. Последняя в npm бывает новее закрепления — reanimated 4.6.0 при 4.5.1 в SDK 57, — и это тоже расхождение.
  • У закреплений два источника: файл bundledNativeModules.json установленного expo — снимок патча — и живой список SDK на сервере Expo. С EXPO_OFFLINE CLI сверяет с файлом, без неё — с сервером; в проекте автора это 2 расхождения против 14.
  • Соседей пакета называет поле peerDependencies: reanimated 4.6.0 просит worklets 0.12.x, а SDK 57 держит 0.10.1. Поставить из npm одну библиотеку пары — значит разбить пару.
  • За год до снимка вышло три SDK, и каждый принёс новую линию React Native, то есть новый бинарник: обновление SDK — новая сборка и проверка на устройстве, а не обновление по воздуху. SDK 58 уже в preview, и gesture-handler там переходит на мажор 3.
  • Каждая таблица полки — снимок на 14.09.2026 с ценой и условием «Пересмотреть, если…»; сошедшие пакеты названы с датой и вопросом, на котором отсеялись, отвергнутые — с причиной, которую можно проверить.

1/4В проект на SDK 57 добавили react-native-mmkv и открыли его в Expo Go из магазина. Что будет?

2/4CI=1 EXPO_OFFLINE=1 npx expo install --check нашёл в проекте два расхождения, а та же команда без EXPO_OFFLINE — четырнадцать. Почему?

3/4@shopify/flash-list нет в списке модулей Expo Go. Нужна ли ради него своя сборка?

4/4Проект на SDK 57, npm install react-native-reanimated поставил 4.6.0. Что сломалось?

Разбитая пара

Функция из раздела о цене не видит peerDependencies. Здесь у неё есть это поле, но только для соседства reanimated и worklets. Допишите peerProblems: для каждого поставленного пакета найти в peers его соседей, отыскать соседа среди поставленных и, если его версия не попадает в диапазон вида 0.12.x, вернуть строку «пакет, версия, просит такого-то соседа такого-то диапазона, а стоит такая-то версия». Прогноз до правки: что напечатает пример как есть?

ts
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера

Диапазон вида 0.12.x сверяется по частям: x подходит к чему угодно, остальные части должны совпасть.

tsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Теперь вторая строка другая: npm install: react-native-reanimated 4.6.0 просит react-native-worklets 0.12.x, стоит 0.10.1, а первая по-прежнему «соседи сходятся». Настоящие диапазоны разнообразнее: у того же reanimated 4.6.0 рядом записан react-native 0.83 - 0.87, у keyboard-controller — >=3.0.0, и разбирает их npm по правилам semver. Своя функция на один вид диапазона — только модель. В проекте разбитую пару покажет уже npx expo install --check: reanimated 4.6.0 не совпадёт с закреплением 4.5.1.

Крышка вместо тильды

В списке закреплений SDK 57 почти все записи — точная версия или тильда, но две — с крышкой ^: @expo/vector-icons и react-native-bootsplash. Функция fits из раздела о цене крышку не понимает и сравнивает такую запись с версией как строку. Научите её: ^15.0.2 принимает тот же мажор и версию не ниже. Прогноз: сколько из трёх строк скажут «версию держит SDK» до правки и сколько — после?

ts
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера

Мажор сравнивается при любом знаке, дальше тильда требует тот же минор, а крышка — версию не ниже:

tsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

До правки «держит» не сказала ни одна строка, после — одна: @expo/vector-icons: версию держит SDK, потому что 15.1.1 попадает в ^15.0.2. Screens 4.25.2 ниже закрепления ~4.26.0, а bootsplash 7.3.3 — последний в npm на 14.09.2026 — ушёл в новый мажор, и крышка его не пропускает. Одна оговорка: у версий с мажором 0 крышка по semver строже — ^0.10.1 держит и минор, — но в списке SDK 57 таких записей нет.

Какой клиент нужен

Проект на SDK 57 открывают в Expo Go. Для каждой команды решите: хватит ли Expo Go после неё и кто выбрал версию — SDK или вы. В одной из команд есть ловушка.

№Команда
1npx expo install @shopify/flash-list
2npm install react-native-mmkv react-native-nitro-modules
3npx expo install expo-camera
4npm install @legendapp/list
5npm install react-native-gesture-handler

1. Expo Go хватит: у FlashList нет нативной половины. Версию выбрал SDK — 2.0.2, хотя в npm 2.3.2.

2. Нужна своя сборка: оба пакета нативные, и ни в списке SDK, ни в Expo Go их нет. Версии ваши — CLI Expo их бы и не подобрал.

3. Expo Go хватит: модуль из SDK, вшит в Expo Go. Версию выбрал SDK — закрепление ~57.0.5.

4. Expo Go хватит: в архиве @legendapp/list 3.3.11 нет кода для iOS и Android. SDK пакета не знает, поэтому npm install здесь не ошибка — версия ваша при любой команде.

5. Ловушка. npm install принесёт 3.3.0 — новый мажор, — а в Expo Go для SDK 57 вшит gesture-handler ~2.32.0. JavaScript-половина пакета и нативная половина в бинарнике окажутся из разных мажоров. Правильная команда — npx expo install react-native-gesture-handler: она поставит ~2.32.0.

Общее правило: клиент решает нативная половина, а версию — есть ли пакет в списке SDK. Команда npx expo install ничем не хуже npm install: пакет из SDK она закрепит, а чужой пропустит к npm как есть.