Add-to-app — официальный механизм Flutter для встраивания Flutter-модуля в существующее нативное приложение для iOS или Android. Приложение-хост остаётся ровно тем, чем было: ваша кодовая база на Swift или Kotlin, ваш релизный процесс, ваши пользователи, — а Flutter появляется внутри него одним скомпилированным модулем и рисует те экраны, которые вы решите ему отдать. Каждый из этих экранов пишется один раз и работает на обеих платформах.

Эта страница — для команд, которые хотят Flutter внутри приложения, которое у них уже есть: нативный продукт, который никто не собирается переписывать, но каждая следующая фича обходится вдвое дороже, потому что её приходится строить отдельно для iOS и Android. Если ваша настоящая цель — со временем оказаться целиком на Flutter, это другой проект с той же механикой: читайте миграцию с React Native и натива — та страница честно называет её переписыванием. Здесь не переписывается ничего: нативное приложение остаётся продуктом, а Flutter зарабатывает своё место фича за фичей.

Какие проекты мы берём

  • Пилотная фича — одна ограниченная по объёму фича, построенная на Flutter и выпущенная внутри обоих ваших нативных приложений, где стоимость интеграции и отдача измеряются, а не обсуждаются на словах
  • Выравнивание функциональности — экран, который есть в вашем iOS-приложении и которого нет в Android-версии (или наоборот), построенный один раз для обеих платформ вместо второго раза для одной
  • Новая поверхность — программа лояльности, флоу бронирования, чат: самостоятельное дополнение к зрелому нативному продукту, выходящее на обе платформы за один бюджет
  • Фундамент для внедрения — каркас модуля, интеграция роутера, обвязка CI и контракты platform channels, настроенные как следует, чтобы фичи дальше выпускали ваши собственные инженеры

Кому это подходит — а кому лучше мигрировать

Add-to-app окупается при конкретных условиях, и мы предпочитаем назвать их прямо, а не продавать интеграцию команде, которой нужно другое.

Признаки того, что add-to-app подходит

  • Каждая фича роадмапа строится дважды, а iOS- и Android-версии приложения начали расходиться по возможностям
  • Приложение слишком большое или слишком проверенное, чтобы его переписывать, поэтому «просто возьмите Flutter» никогда не было реальным вариантом
  • Вы хотите оценить Flutter на настоящей продакшен-работе — одна фича, реальные пользователи, замеры — прежде чем брать на себя что-то большее
  • Две платформенные команды трудно укомплектовать поровну, и новые поверхности буксуют на той платформе, где в этом квартале не хватает рук

Когда это НЕ правильный выбор

  • Приложение настолько маленькое, что свежая сборка на Flutter или поэкранная миграция обойдётся дешевле, чем поддержка шва между нативом и Flutter, — у интеграции есть накладные расходы, и маленький хост их не амортизирует
  • Решение прийти к 100% Flutter уже принято — тогда ведите проект как миграцию с первого дня, с картой миграции, а не сползайте в неё незаметно
  • Приложение уже на React Native — встраивание второго кроссплатформенного рантайма рядом с первым усугубляет проблему; реалистичные варианты для такой команды — остаться как есть или мигрировать
  • Нужная вам фича — глубоко платформенная: интерфейс, построенный на виджетах, или функциональность прежде всего для Watch, — здесь Flutter не тот инструмент, и мы так и скажем

Честный вывод: гибридное приложение — это постоянный шов: два тулчейна, два набора идиом и граница, которую обязан понимать каждый инженер команды. Add-to-app стоит этой цены, когда хост слишком большой, чтобы его переписывать, а роадмап продолжает платить налог на две платформы. Если ни то ни другое не про ваше приложение, лучшим ответом будет одна из соседних страниц — и на первом созвоне мы скажем, какая именно.

Как проходит поэтапное внедрение

Как устроен путь add-to-app

Шаг 1

Нативное приложение остаётся продуктом

Ваши iOS- и Android-приложения продолжают выходить без изменений — без заморозки, без параллельного переписывания, без перехода на горизонте

Шаг 2

Встраивается модуль Flutter

Один модуль Flutter подключается к обеим оболочкам и использует их навигацию, аутентификацию и аналитику через зафиксированные контракты

Шаг 3

Выходит пилотная фича

Ограниченная фича строится один раз на Flutter и выпускается внутри обоих приложений — с замерами размера и времени старта до и после

Шаг 4

Внедрение растёт фича за фичей

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

Шаг 5

Финал решаете вы

Оставайтесь гибридом сколько угодно, передайте модуль своей команде или превратите набранный темп в полную миграцию: каждая граница фичи — точка остановки

Этот процесс сознательно использует ту же машинерию, что и наша услуга миграции: модуль Flutter за общим роутером, экраны переносятся по одному. Разница — в пункте назначения: миграция в конце выводит нативный хост из эксплуатации, а внедрению это не обязательно. А значит, позже внедрение без потерь превращается в миграцию, если модуль её заслужит, — и ничего не выбрасывается.

Чего add-to-app требует на самом деле

Один движок с управляемым жизненным циклом

Модуль Flutter приносит с собой движок Flutter, а движок — ресурс, которым хост обязан управлять осознанно: прогретый заранее, чтобы первый Flutter-экран открывался без видимой паузы на запуск; общий для всех точек входа, а не создаваемый на каждый экран; освобождаемый, когда платформа просит память назад. Ошибка здесь невидима в демо и очевидна в продакшене. Это первое, что мы строим, а не последнее, что тюним.

Навигация через границу

Пользователям всё равно, какой фреймворк отрисовал экран, на котором они находятся, и навигация обязана это учитывать: жесты «назад» ведут себя так, как принято на платформе, диплинки приземляются на Flutter-экраны так же надёжно, как на нативные, а состояние переживает переход в обе стороны. Контракт роутера между хостом и модулем — та часть архитектуры add-to-app, которая решает, будет шов невидимым или станет постоянным источником багов.

Общие сервисы: заимствовать, а не дублировать

В вашем приложении уже есть аутентификация, аналитика, сеть и фиче-флаги. Модуль Flutter должен заимствовать их через , а не отращивать собственные копии — именно так у гибридного приложения появляются две сессии, две схемы событий и метрики, которым никто не доверяет. Точное определение этих канальных контрактов — большая часть работы над фундаментом, и она окупается на каждой следующей фиче.

Два тулчейна в одном пайплайне

После интеграции ваш собирает модуль Flutter и обе нативные оболочки, а версии модуля приходится согласовывать с двумя релизными циклами, которые не всегда движутся синхронно. Мы встраиваем сборку модуля в ваш существующий пайплайн — кэшируемую, воспроизводимую и живущую в вашем репозитории, а не на чьём-то ноутбуке, — потому что интеграция, которую не может собрать ваш CI, — не интеграция.

Шов, с которым смогут жить ваши дизайнеры

Flutter рисует свои пиксели сам, и это работает в обе стороны: он не унаследует ваши нативные компоненты, но точно воспроизведёт вашу дизайн-систему — как только токены, типографика и отступы перенесены в тему модуля. Мы делаем этот перенос в рамках фундамента, чтобы пользователь, скроллящий с нативного экрана на Flutter-экран, не мог понять, где проходила граница.

Издержки: измеренные, а не заявленные

Встраивание Flutter добавляет реальный вес: порядка нескольких мегабайт к Android-релизу и несколько больше на iOS, плюс запуск движка при первом открытии Flutter-экрана. Точные цифры зависят от вашего приложения — поэтому в поставку пилота входят замеры размера бинарника и времени старта до и после: решение идти дальше вы принимаете по данным собственного продукта, а не по бенчмарку из чьего-то блога.

Прецеденты в продакшене

Flutter поддерживает модель интеграции add-to-app уже много лет, и её самый известный пользователь — Google Pay, внедривший Flutter внутрь существующего нативного приложения с сотнями миллионов пользователей, прежде чем идти дальше. Паттерн — ровно тот, что описывает эта страница: встроить, выпустить одну поверхность, замерить, затем решить. Наш собственный опыт с этой машинерией пришёл из миграционных проектов, где та же связка «модуль за роутером» переносит целые приложения; внедрение использует её же, но с куда меньшими обязательствами.

Как мы работаем

Фундамент и пилот с фиксированным объёмом. Мы интегрируем модуль в обе оболочки, переносим дизайн-токены, определяем канальные контракты и выпускаем первую фичу — ограниченный проект, где замеры входят в поставку. Наш процесс разработки описывает, как мы ведём такую работу неделя за неделей.

Встроенные инженеры. Наши Flutter-инженеры входят в вашу нативную команду — в ваш репозиторий и ваши спринты — и развивают модуль рядом с людьми, которые владеют хостом, — см. расширение команды. Это естественный формат, когда пилот себя доказал и модуль стал местом, где регулярно оказываются задачи вашего роадмапа.

В обоих случаях смету под задачу мы присылаем в течение двух рабочих дней после того, как разберёмся в требованиях.

Сколько стоит интеграция add-to-app

Проект «фундамент плюс пилот» оценивается после того, как мы увидим приложение: стоимость интеграции определяет хост — его навигационная архитектура, его система сборки, то, как устроен доступ к его общим сервисам, — куда сильнее, чем сама пилотная фича, поэтому цифра, названная до взгляда на кодовую базу, была бы фикцией. Как ориентир: ограниченный пилот стоит заметно меньше самостоятельного приложения — опубликованные тарифы на странице разработки на Flutter начинаются с 1,4–2,7 млн ₽ за полноценный MVP, а пилотная фича внутри существующего хоста — лишь доля этого объёма.

Для модели со встроенными инженерами действует опубликованная ставка расширения команды: 900 тыс. ₽ – 1,3 млн ₽ за senior-инженера в месяц. А если честный финал роадмапа — приложение целиком на Flutter, называйте проект своим именем и оценивайте его как миграцию, которую та страница сравнивает с полной пересборкой, — а не как внедрение, переросшее своё название.

Частые вопросы

Что чаще всего спрашивают команды, которые думают о Flutter внутри существующего нативного приложения.

Да — ровно для этого и существует модель интеграции add-to-app у Flutter. Модуль Flutter встраивается в ваше существующее приложение на Swift или Kotlin, подключается к его навигации, аутентификации и аналитике через platform channels и рисует те экраны, которые вы решите в нём построить. Ваше приложение всё это время продолжает выходить без изменений; модуль добавляется рядом с существующим кодом, а не вместо него. Каждый Flutter-экран пишется один раз и работает внутри обоих ваших приложений — и iOS, и Android.
Нет. Внедрение и миграция используют одну механику — модуль Flutter за общим роутером, — но миграция обязуется в конце вывести нативное приложение из эксплуатации, а внедрению это не обязательно. Каждая граница фичи — полноправная точка остановки: одни продукты остаются гибридом неограниченно долго, отдав Flutter несколько поверхностей, другие передают модуль собственной команде, третьи превращают набранный темп в полную миграцию, когда модуль её заслужил. Ничего построенного во время внедрения не выбрасывается, если позже вы решите пойти дальше.
Движок и модуль Flutter добавляют реальный вес — порядка нескольких мегабайт к релизной сборке Android и несколько больше на iOS. Точная цифра зависит от вашего приложения и содержимого модуля — поэтому наш пилотный проект включает замеры размера бинарника и времени старта до и после на вашем реальном продукте. Решение о внедрении вы принимаете по собственным цифрам, а не по обобщённому бенчмарку.
Механически это работает: Flutter встраивается в хост на React Native так же, как в полностью нативный. Стратегически это редко имеет смысл: вы получите два кроссплатформенных рантайма, два моста и три UI-идиомы в одном бинарнике — что усугубляет проблему сопровождения, а не решает её. Для команды на React Native, недовольной положением дел, реалистичные варианты — остаться как есть или мигрировать на Flutter экран за экраном; наша страница миграции начинается с того, кому не стоит делать ни того ни другого.
Да. Add-to-app — модель интеграции, которую Flutter поддерживает уже много лет, и её самый известный пользователь — Google Pay, встроивший Flutter в нативное приложение с сотнями миллионов пользователей, прежде чем ставить на него больше. Паттерн «встроить модуль, выпустить одну поверхность, замерить, затем решить» давно отработан. Оставшиеся инженерные риски — детали интеграции: жизненный цикл движка, навигация через границу, продублированные сервисы, — и именно их работа над фундаментом закрывает в первую очередь.
Для пилота — нет: его строим мы, а ваша команда ревьюит границу модуля, а не Dart внутри него. Если внедрение Flutter растёт, часть ваших инженеров захочет работать в модуле, а Dart — небольшой шаг от Swift или Kotlin: строгая типизация, сборка мусора — и он куда ближе к тому, что они уже пишут, чем JavaScript. Модель со встроенными инженерами существует ровно для этого перехода: наши люди строят рядом с вашими, пока модуль не станет кодовой базой, которой ваша команда владеет, а не просто хостит.

Прочитайте страницу миграции, если пункт назначения — целиком Flutter; посмотрите расширение команды — про модель со встроенными инженерами; или начните с пилларной страницы разработки на Flutter.