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

Вот и я решил создать приложение для уже существующего образовательного портала RushENGL, ведь сайт то безусловно хорош, но не всем пользователям с телефона удобно им пользоваться, да и хотелось бы видеть его в списке приложений для быстрого доступа.

Когда я только брался за разработку, я не знал особо какие есть методы и на какой язык выбрать. Но в итоге мой первый выбор пал на React Native.

Нативные приложения

Когда я только начинал, я не знал, какие технологии лучше использовать. Я понимал, что не хочу разрабатывать два отдельных приложения — одно на Kotlin для Android, и второе на Swift для iOS. Это было бы слишком тяжело для одного человека, да и яблочных устройств для разработки на Swift у меня под рукой не было.

Мой выбор пал на React Native — JavaScript-фреймворк от Meta* (*организация, признанная экстремистской на территории РФ). Он позволяет писать один код для Android и iOS одновременно.

Звучит идеально, правда? На React Native работают такие крупные приложения, как Discord, Uber Eats, и даже различные приложения от Microsoft.

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

  • Тяжеловесность среды

    Даже банальные команды сборки могли сильно грузить систему. Часто приходилось ждать по несколько минут, пока приложение пересоберётся. Для мощных машин это не критично, но мой ноут явно не радовался. И ведь это я сделал только базовые функции по типу навигации.

  • Сложная отладка и документация

    Простой пример: я хотел настроить базу данных. Простая задача, казалось бы. Но оказалось, что прямое подключение серверной базы к приложению без промежуточного API не имеет смысла. Надо было использовать локальную базу данных (например, SQLite, потому что она легковесная и может работать офлайн) и синхронизировать ее с сервером, если есть интернет. Но понять, как это все работает в React Native, оказалось сложно. Мало актуальных гайдов, много недосказанностей, и куча багов при сборке.

  • Фронтенд заново

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

    В итоге, я провёл почти полмесяца, пытаясь довести до ума базовую рабочую версию. И понял одну простую вещь:

    Для одного разработчика с ограниченным временем — нативная разработка на React Native не лучший путь.

Так или иначе а у React Native есть свои плюсы:

  • Кроссплатформенность - разработка под Android и iOS как и говорилось ранее.

  • Хорошая поддержка сообществом. Для React Native есть много разных библиотек которые упрощают работу и дают вам интересные функции в приложения.

  • Использование JavaScript. Этот язык является очень популярным на рынке, что снижает порог входа для веб-разработчиков и увеличивает востребованность специалистов.

    Я отложил проект на некоторое время.

Webview спешит на помощь

Я решил рассмотреть более простые реализации, которые мне бы позволили использовать уже готовый сайт для реализации. И такое решение нашлось - Webview.

WebView — это компонент, который позволяет отображать веб-контент (например, сайт) прямо внутри мобильного приложения. Такой подход часто используют новостные агрегаторы, интернет-магазины и даже крупные соцсети — там, где основной функционал уже реализован на вебе, и нет смысла дублировать всё нативно.

Разумеется, просто завернуть сайт в обёртку и выкатить в Google Play — плохая идея. Во-первых, модерация может не пропустить такое приложение. Во-вторых, нужно обеспечить минимальный уровень нативного UX: навигация, загрузочные экраны, работа оффлайн и т.п.

Для реализации WebView-приложения я выбрал Flutter — фреймворк от Google, построенный на языке Dart. Flutter оказался гораздо быстрее и стабильнее, чем React Native, особенно в плане сборки, зависимостей и документации.

Конкретно для WebView я использовал библиотеку flutter_inappwebview — она показалась мне самой гибкой и удобной.

Как всё устроено внутри

Приложение по сути отображает разные страницы сайта, но с нативной нижней навигацией, которая реагирует на текущий URL. Это позволяет пользователю ощущать себя внутри полноценного мобильного приложения, а не просто браузера.

Пример инициализации ссылок

В начале я определяю список URL-ов, каждый из которых соответствует определённой вкладке (здесь ссылки анонимизированы для примера):

final List<String> _urls = [
  'https://example.com/app/main',      // Главная
  'https://example.com/app/vocab',     // Словарь
  'https://example.com/app/grammar',   // Грамматика
  'https://example.com/app/practice',  // Практика
  'https://example.com/app/other',     // Прочее
];

Слежение за URL и смена вкладки

Когда пользователь переходит по ссылкам внутри WebView, приложение отслеживает текущий URL и меняет активную иконку в навигации. Для этого реализована простая функция:

void _updateCurrentIndex(String url) {
  final newIndex = () {
   if (url.contains('index.php')) return 0;
   if (url.contains('practice') || url.contains('prgrammar') || url.contains('prvocab')) return 3;
   if (url.contains('vocab')) return 1;
   if (url.contains('grammar')) return 2;
   return 4; // Прочее
  }();

  if (newIndex != _currentIndex) {
    setState(() {
      _currentIndex = newIndex;
    });
  }
}

Важно:
Используйте уникальные части URL для каждого раздела, чтобы не было пересечений между вкладками. А если пересечения и есть как у меня (prvocab и prgrammar), то стоит поднять такое условие выше чтобы у него был приоритет.

Открытие внешних ссылок

Чтобы внешние сайты и приложения открывались не внутри WebView, а во внешнем браузере или нужном приложении, я использовал пакет url_launcher:

shouldOverrideUrlLoading: (controller, navigationAction) async {
  final uri = navigationAction.request.url;

  if (uri == null) return NavigationActionPolicy.CANCEL;

  _updateCurrentIndex(uri.toString());

  // Открываем только свой сайт внутри приложения
  if (uri.host.contains('rushengl.com')) {
    return NavigationActionPolicy.ALLOW;
  }

  // Внешние ссылки — через браузер или другое приложение
  if (await canLaunchUrl(uri)) {
    await launchUrl(uri, mode: LaunchMode.externalApplication);
  }

  return NavigationActionPolicy.CANCEL;
}

canLaunchUrl и launchUrl — это асинхронные функции из пакета url_launcher. Они позволяют безопасно открывать внешние ссылки через браузер или другие приложения.

Важные настройки для Android

Чтобы приложение могло работать с интернетом, обязательно нужно добавить разрешения в файл AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Без разрешения на интернет (INTERNET) WebView просто не сможет загрузить сайт.

Подведение итогов

Создать мобильное приложение в одиночку — вполне реально, особенно если у вас уже есть готовый сайт. Главное — выбрать правильный подход.

Если бы я пошёл по пути полной нативной разработки, даже с React Native, мне бы потребовалось, скорее всего, пару месяцев минимум. А с WebView и Flutter я уложился в две недели, и получил рабочее, стабильное приложение, которое уже доступно в Google Play, RuStore и Huawei Market.

Разумеется, путь не был безболезненным. Я не знал Dart и активно использовал ИИ-помощников в разработке. Но это не значит, что я просто копировал чужой код. Я разбирался, читал, тестировал, исправлял баги. Иногда уходил целый день на то, чтобы понять, почему не работает банальная вещь — но оно того стоило.

Такой подход — не панацея. WebView не подойдёт, если вам нужно сложное, интерактивное приложение с кастомными анимациями, offline-хранилищем, или глубоким доступом к железу. Но если у вас уже есть сайт, и вы хотите завернуть его в мобильную упаковку — WebView может сэкономить вам месяцы работы.

Советы начинающим

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

  • Не бойтесь использовать ИИ, но не полагайтесь на него вслепую. Часто он может усложнять простые вещи или выдавать устаревшие решения. Лучше прочитайте документацию и разберитесь сами в проблеме — может оказаться, что решение проще, чем казалось.

  • Сохраняйте разные версии проекта. Особенно важно разделять версию с ключом подписи (для публикации) и debug-версию (для разработки). Я однажды подписал основную сборку, и потом пришлось откатываться назад и переорганизовывать проект, чтобы снова собирать без подписи.

  • Не беритесь за тяжёлую артиллерию без надобности. Если вам не нужно сложное кастомное поведение — не усложняйте себе жизнь. Простые задачи требуют простых решений. Иногда WebView — это именно то, что нужно.

  • Добавьте нативный UX — навигацию, анимации, разрешения на использование чего-либо (если оно требуется), Splash Screen и прочее чтобы приложение точно прошло и выглядело как нативное для пользователя.

Flutter vs React Native — что выбрать?

Оба инструмента по-своему хороши, и каждый подходит под свои задачи:

Flutter

React Native

Язык

Dart

JavaScript

Скорость сборки

Быстрее

Могут быть долгие билды

Поддержка

Отличная от Google

Широкая, от Meta и сообщества

Документация

Современная и подробная

Иногда устаревшая или неполная

UI

Отрисовка с нуля (canvas)

Обёртка над нативными компонентами

Кроссплатформенность

Да

Да

Порог входа

Средний (нужно знать Dart)

Ниже (если знаете JS)

React Native отлично подойдёт, если вы уже знакомы с JavaScript или делаете сложное приложение с большим количеством нативных модулей и кастомной логикой. Его используют крупные компании (Discord, Microsoft, Uber и др.), и для сложных проектов с большим бюджетом и командой это оправдано.

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

Заключение

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

Да, WebView — это не rocket science. Но если работает, выглядит достойно и даёт пользователю нормальный UX — почему бы и нет?

Комментарии (4)


  1. Evgen175
    17.07.2025 15:18

    Даже банальные команды сборки могли сильно грузить систему. Часто приходилось ждать по несколько минут, пока приложение пересоберётся

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

    Простая задача, казалось бы. Но оказалось, что прямое подключение серверной базы к приложению без промежуточного API не имеет смысла

    Не до конца понял что вы имеете ввиду. Обычно у сервера есть апи, вы можете к нему обращаться и получать данные в рамках контрактов. Если надо вы можете эти данные сохранить в тот же SQLite или любую другую БД на девайсе. Какой документации вам не тут хватило или какой вы ожидали?

    Для одного разработчика с ограниченным временем — нативная разработка на React Native не лучший путь.

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

    Для реализации WebView-приложения я выбрал Flutter — фреймворк от Google, построенный на языке Dart

    А зачем вообще вы брали Flutter для этого? Почему не нативку учитывая что вы с ИИ прогали, ну или ionic или cardova, на крайняк? Просто взять здоровенный фраемворк исключительно для показа вебвью и навбара звучит как оверхед и такое советовать я бы не стал.

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

    Не понял что такое "основная сборка" и зачем потом надо было переорганизовывать проект и что значит "переорганизовывать проект". Предполагаю что речь про андроид. Для него обычно создается дебаг и прод ключи (использование можно посмотреть в файле android/app/build.gradle) и приложение подписывается в зависимости от build variant, который вы используете при сборке. При этом откатываться или что-то переорганизовывать не надо

    Flutter — лучшее решение для быстрого и стабильного вывода веб-сайта в формате приложения, особенно если нужен WebView или кастомный UI

    А вы пробовали на RN сделать тоже самое с WebView, как пришли к выводу что на Flutter это сделать быстрее?


    1. codeNvectors Автор
      17.07.2025 15:18

      Здравствуйте, спасибо за критику.

      Хочу уточнить, что моя статья — это субъективный опыт человека, который до этого не имел опыта в мобильной разработке. Главная задача стояла — создать работающее мобильное приложение в кратчайшие сроки, а не изучить всё досконально. И именно с этой задачей я успешно справился.

      Сначала я выбрал React Native, поскольку это один из самых популярных инструментов для кроссплатформенной разработки. Однако по ходу работы столкнулся с рядом сложностей: нехваткой понятной информации для новичка (например, по работе с серверными базами), необходимостью постоянной установки дополнительных библиотек и довольно тяжёлой сборкой, особенно на слабом ноутбуке. Это замедляло процесс, вызывало раздражение и съедало время.

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

      Я рассматривал возможность использовать WebView как на React Native, так и на Flutter. На основе своего опыта и проведённого сравнения (в том числе с помощью AI и обзоров в сети), я выбрал Flutter. Он показался мне более простым в освоении, имел всё нужное "из коробки", быстрее собирал проект и потреблял меньше ресурсов. В итоге за 2 недели я сделал кроссплатформенное приложение, которое стабильно работает и весит всего 18 МБ после установки.

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


  1. Mizantrop777
    17.07.2025 15:18

    На c# вполне пишется кросплатформено. Раньше ксамарин был, но его Майкрософт купил вроде. Давно не занимался мобильной разработкой. Но для вебвью и навигации использовать какие то сторонние библиотеки с кучей лишнего - такое себе. Стандартные средства уже не работают что ли?


    1. codeNvectors Автор
      17.07.2025 15:18

      Спасибо за комментарий! Моя статья — это субъективный опыт новичка, который успешно справился с задачей: быстро создать производительное кроссплатформенное приложение с WebView и нативной навигацией для уже существующего веб-сайта. Выбор Flutter был обусловлен не только его популярностью, но и тем, что он позволил достичь поставленных целей в сжатые сроки, сэкономить на оборудовании (не нужен Mac для iOS-разработки) и получить легкое приложение (18 МБ). Альтернативы вроде Xamarin (сегодня известный как .NET MAUI) или Ionic/Cordova не попали в моё поле зрения при поиске наиболее эффективных инструментов для быстрого старта новичка, а уж тем более не решали бы мою задачу кроссплатформенности без глубокого погружения в две нативные экосистемы. Результат налицо: приложение есть и работает, а это главное.