Flutter и Dart — кроссплатформенная разработка: почему ваш APK весит 80 МБ и как его уменьшить, не сломав приложение

Сборка, которая попадает в Google Play с весом 70–80 МБ, — это не редкая ошибка, а стандартный результат проекта на Flutter, который никто не измерял. Загрузка кажется нормальной на вашем офисном Wi-Fi и вашем Pixel, а потом пользователь на трёхлетнем Android-устройстве с 2 ГБ оперативной памяти ждёт, устанавливает и оставляет отзыв на одну звезду о том, что «медленно и тяжело». Исправление начинается не со списка советов. Оно начинается с цифры.

Миф первый: «Приложения на Flutter просто большие, это особенность фреймворка»

Flutter действительно поставляет среду выполнения, но фреймворк — это фиксированная стоимость, которую вы не можете убрать. Что вы можете убрать — это всё, что вы добавили сверху и никогда не проверяли. Честный первый шаг — flutter build appbundle --analyze-size (или --analyze-size для APK). Он создаёт профиль размера, который вы открываете в DevTools, и дерево разбивается по пакетам: ваш код на Dart, движок Flutter, ресурсы, нативные библиотеки, шрифты.

Большинство команд, которые запускают это впервые, находят одних и тех же трёх виновников: несжатые PNG и JPEG в папке assets/, полный шрифт иконок, подключённый ради восьми глифов, и два-три Firebase SDK, добавленных «на всякий случай» во время спринта и никогда не удалённых.

Измеряйте, прежде чем что-либо трогать Запускайте анализатор размера на той самой сборке, которую отправляете в магазин, а не на отладочной. Отладочные сборки содержат observatory и не показательны — вы будете оптимизировать не то.

Миф второй: «split-per-abi — это устаревший трюк для Android»

Это не устаревший приём, это всё ещё один из самых дешёвых способов выиграть. Универсальный APK содержит нативные библиотеки для arm64-v8a, armeabi-v7a и x86_64 в одном файле. flutter build apk --split-per-abi создаёт три APK, каждый несёт только свою архитектуру — arm64 обычно на треть меньше универсальной сборки.

Но лучший вариант по умолчанию в 2026 году — Android App Bundle. flutter build appbundle позволяет Play автоматически доставлять раздельные сборки для каждого устройства, и вы сохраняете один артефакт. Подвох, который часто упускают: если вы тестируете локально только универсальный APK, вы никогда не видите, что скачивает реальное устройство, и не замечаете, что нативная зависимость поставляет библиотеки для архитектур, которые вы не поддерживаете. Загрузите в трек внутреннего тестирования и проверьте размер загрузки, который показывает Play — именно эта цифра, а не APK на вашем диске, определяет, что платит пользователь.

Миф третий: «Ресурсы маленькие, они не важны»

Одно главное изображение, экспортированное из инструмента дизайна с весом 3 МБ, стоит больше, чем все правки кода вместе взятые. Конвертируйте в WebP, ограничьте разрешение тем, что действительно нужно макету, и проверьте с помощью анализатора размера, какие ресурсы доминируют. То же касается шрифтов: файл вариативного шрифта с полным покрытием кириллицы и латиницы может весить больше, чем ваш код на Dart. Сделайте подмножество или оставьте только используемые начертания.

Иконки — это тихий виновник. flutter build по умолчанию удаляет неиспользуемые иконки из Material и выводит, сколько глифов было удалено — прочитайте эту строку в логе сборки. Если вы подключили собственный шрифт иконок или пакет, который поставляет свой, tree-shaking его не затрагивает. Вот где шрифт на 400 КБ отправляется ради шести иконок.

Миф четвёртый: «Прореживание для iOS — проблема Apple»

App thinning на iOS реально существует, но помогает только если ваша сборка настроена для него. Опция Enable bitcode исчезла в последних версиях Xcode, и оставшийся практический рычаг — каталоги ресурсов: изображения, помещённые в Assets.xcassets с правильными вариантами масштаба, прореживаются для каждого устройства, а изображения, сброшенные в папку Flutter assets/, — нет. Если размер загрузки для iOS выглядит раздутым по сравнению с Android, сначала посмотрите туда, прежде чем винить движок.

Ещё два рычага, о которых стоит знать:

  • --split-debug-info и --obfuscate удаляют таблицы символов из релизного бинарника. Вы сохраняете файл символов для деобфускации стектрейсов при сбоях — потеряйте его, и ваши стектрейсы станут шумом, поэтому архивируйте его в CI.
  • Отложенные компоненты позволяют поставлять функцию как отдельную загрузку на Android. Мощно, но добавляет состояние загрузки и путь отказа, который теперь нужно тестировать. Не прибегайте к этому, пока не сделаны простые улучшения.

Как выглядит реалистичное «до/после»

Цифры ниже приведены для иллюстрации для приложения среднего размера с Firebase Auth, Firestore, экраном карт и лентой с обилием медиа — ваше дерево будет отличаться, но пропорции обычно сохраняются.

Рычаг До После
Универсальный APK, устройство arm64 ~78 МБ —
App Bundle, загрузка на устройство — ~34 МБ
Ресурсы (PNG → WebP, изменённый размер) ~14 МБ ~4 МБ
Удалены неиспользуемые Firebase SDK ~6 МБ 0
Шрифт иконок → tree-shaken Material ~0,5 МБ ~0,05 МБ

Часть, которая действительно кусается: проверка, что ничего не сломалось

Каждый выигрыш в размере — это изменение поведения, пока не доказано обратное. То, что ловит команды, — офлайн: вы сжали ресурсы, сменили форматы, переместили шрифт — и приложение, которое работало онлайн, теперь показывает серые квадраты в режиме полёта. Тестируйте релизную сборку, а не отладочную, с отключённой сетью, на реальном маломощном устройстве. Проверьте, что изображения отображаются, иконки появляются, а экраны, работающие из кеша, по-прежнему заполняются.

60-секундная проверка перед релизом Установите подписанную для магазина сборку на бюджетный Android-телефон, включите режим полёта, откройте каждую вкладку по одному разу. Если что-то пусто, вы оптимизировали файл, который приложению был нужен во время работы.

Где структурированное обучение действительно помогает

Вы можете найти каждую команду выше в документации Flutter — барьер не в информации, а в знании, какой рычаг применим к вашему дереву и в каком порядке, и в том, чтобы кто-то проверил компромисс перед выпуском. Самостоятельное изучение даёт вам команды; оно редко даёт обратную связь по такому решению, как «стоят ли отложенные компоненты состояния загрузки здесь?»

Курс Flutter и Dart — кроссплатформенная разработка охватывает конвейер сборки, интеграцию с Firebase, работу с ресурсами и публикацию в магазинах в том же порядке, в котором вы с ними сталкиваетесь в реальном проекте, с уроками, адаптированными под ваш уровень — полезно, если вы хотите охватить сторону релиза, а не открывать её для себя в день запуска.

Размер — это бюджет, а не разовая уборка. Установите потолок, проверяйте цифру загрузки, которую сообщают Play и App Store Connect при каждом релизе, и воспринимайте скачок как сигнал снова открыть анализатор.

← Все статьи

Спросить AI по этой статье

Задайте вопрос по этой статье — ASI Biont ответит, опираясь на её текст.

Читайте также

ИИ для повседневной жизни: как построить реальный семейный бюджет с ChatGPT и Claude (без кода, 2026)

27 октября 2026

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

27 октября 2026

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

27 октября 2026

QA Automation Engineer: 5 мифов, которые стоят новичкам месяцев (и как их избежать)

11 ноября 2026

Вайб кодинг: как создавать код с помощью AI без навыков программирования — обзор курса и практические грабли

27 октября 2026

Excel и Google Таблицы: освойте работу с электронными таблицами — от формул до сводных и макросов

29 октября 2026

Деловая переписка на английском: шаблоны, которые работают, и ошибки, которые дорого стоят

29 октября 2026

Запуск бизнеса с нуля: от идеи до первых продаж — комплексная программа для старта собственного дела

29 октября 2026

Linux для начинающих: освойте командную строку с нуля и станьте уверенным администратором

30 октября 2026