Оптимизация производительности Mini App для мобильных устройств в Telegram

Вы открыли Mini App в Telegram, а она тормозит. Кнопки откликаются с задержкой, анимации лагают, и через пару минут приложение вообще перестает реагировать. Это не ваш телефон - это проблема самой Mini App. Миллионы пользователей сталкиваются с этим каждый день, и большинство разработчиков даже не подозревают, что исправить это можно за пару часов. Оптимизация производительности Mini App для мобильных устройств - не про сложные алгоритмы. Это про то, чтобы убрать то, что мешает. Просто и эффективно.

Почему Mini App в Telegram тормозит на телефоне

Mini App в Telegram - это веб-приложение, запущенное внутри мобильного браузера. Он не имеет доступа к нативным API, как обычное приложение из App Store или Google Play. Всё, что вы видите, рисуется через WebView - слабое звено в цепочке. На старых телефонах, даже с 4 ГБ ОЗУ, WebView может работать в режиме экономии ресурсов. И если ваша Mini App загружает 5 МБ JavaScript-файлов, 100 изображений по 200 КБ и 15 библиотек, которые вы не используете - она упадёт. Даже на iPhone 13.

Вот реальный кейс: приложение для управления задачами в Telegram загружало 12 МБ данных при старте. Пользователи жаловались, что приложение «не запускается». На самом деле, оно запускалось - но 8 секунд висело на белом экране. После оптимизации - 1,2 секунды. Разница в 6,5 раза. И это не магия - это устранение лишнего.

Уберите всё, что не нужно

Самая простая и самая недооценённая оптимизация - удалить ненужный код. Вы используете React? Проверьте, сколько библиотек вы подключили. Vue? Тоже. Сколько из них реально нужны для вашего Mini App? В 80% случаев разработчики подключают целые фреймворки, чтобы сделать одну кнопку с анимацией. Это как завести танк, чтобы поехать за хлебом.

Используйте Tree Shaking - это технология, которая автоматически удаляет неиспользуемый код при сборке. В Webpack, Vite или Rollup она включена по умолчанию, но только если вы пишете код правильно. Не импортируйте целый пакет, если вам нужна одна функция:

  • Плохо: import { debounce } from 'lodash'
  • Хорошо: import debounce from 'lodash/debounce'

Удалите все библиотеки для работы с DOM, если вы не работаете с ним напрямую. Telegram Mini App уже предоставляет API для взаимодействия с интерфейсом - вам не нужен jQuery, не нужен Axios, если вы используете fetch(). Не нужен Lodash вообще, если вы пишете 3 строки кода на чистом JavaScript.

Оптимизируйте изображения и медиа

Изображения - главный виновник тормозов. Вы загружаете PNG-файлы размером 1500×1500 пикселей для кнопки 48×48 пикселей? Это как везти грузовик с бензином, чтобы заправить мопед.

Превратите все изображения в WebP. Это формат, который сжимает картинки на 30-50% без потери качества. Используйте инструменты вроде Squoosh.app или ImageOptim. Не забудьте про размеры: если кнопка в интерфейсе 48×48 - сохраняйте изображение именно в этом размере. Не загружайте 200×200 и не уменьшайте через CSS - браузер всё равно скачает полный файл.

Для иконок используйте SVG. Они масштабируются без потери качества, и их размер - обычно 1-3 КБ. Не используйте PNG для иконок. Даже если вы думаете, что PNG «лучше», это не так. SVG - стандарт для мини-приложений.

Загружайте изображения лениво (lazy loading). Не грузите все картинки при старте. Используйте атрибут loading="lazy" для тегов <img>. Telegram Mini App API поддерживает это. Если у вас список сообщений с аватарками - грузите их только тогда, когда пользователь прокручивает до них.

Баланс между тяжелым ненужным кодом и оптимизированным Mini App с SVG, WebP и чистым JavaScript.

Сократите время загрузки JavaScript

JavaScript - это самый тяжёлый ресурс для мобильных устройств. Каждая строка кода требует времени на парсинг, компиляцию и выполнение. На старом Android-телефоне это может занять 2-3 секунды только на загрузку одного файла.

Разбейте ваш код на чанки. Используйте динамический импорт (dynamic imports). Загружайте только то, что нужно на старте. Остальное - по мере необходимости. Например, если у вас есть экран настроек, который открывается редко - загружайте его только при открытии этого экрана.

Пример:

const openSettings = async () => {
  const settingsModule = await import('./settings.js');
  settingsModule.showSettings();
};

Так вы сократите начальную загрузку на 60-70%. Это работает, потому что Telegram Mini App не требует, чтобы всё было загружено сразу. Он работает как веб-сайт - загружайте только то, что нужно прямо сейчас.

Используйте кэширование и локальное хранилище

Каждый раз, когда пользователь открывает Mini App, он загружает всё заново. Это ужасно неэффективно. Вы можете кэшировать статические ресурсы: CSS, JS, изображения, шрифты. Используйте Service Workers - они работают в Telegram Mini App. Они позволяют сохранять ресурсы на устройстве и загружать их из кэша, даже если интернета нет.

Для данных используйте localStorage или IndexedDB. Не делайте запросы к серверу за одним и тем же списком задач каждый раз. Сохраняйте их локально. Обновляйте только при изменении. Это уменьшает количество HTTP-запросов и ускоряет работу в 3-5 раз.

Проверьте, сколько запросов делает ваша Mini App при старте. Если их больше 10 - вы делаете что-то не так. Оптимально - 2-3 запроса: один за базовыми настройками, один за пользовательскими данными. Всё остальное - локально.

Тестируйте на реальных устройствах

Вы разрабатываете на MacBook Pro с 32 ГБ ОЗУ и SSD. Но ваш пользователь - это человек с Android-телефоном 2020 года, 3 ГБ ОЗУ, и медленным интернетом в деревне. Если вы не тестируете на таких устройствах - вы не знаете, как работает ваше приложение.

Используйте Chrome DevTools - включите режим «Throttling» (замедление сети) и выберите «Slow 3G». Включите «CPU throttling» - поставьте 4x slowdown. Теперь откройте вашу Mini App. Видите, как она тормозит? Это то, что видят ваши пользователи.

Не полагайтесь на скорость в эмуляторе. Эмуляторы не показывают реальную производительность WebView. Тестируйте на реальных телефонах. Возьмите у друга старый Xiaomi, Huawei или Samsung - и проверьте. Если приложение работает плавно на нём - значит, оно будет работать для 90% пользователей.

Сравнение загруженного и оптимизированного интерфейса Mini App: слева — тормоза, справа — плавная анимация.

Оптимизируйте рендеринг и анимации

Анимации - это красиво. Но если вы используете transform: translate или opacity - это нормально. Если вы меняете width, height, margin или padding - это убийца производительности. Каждое изменение этих свойств заставляет браузер пересчитывать расположение всех элементов на странице. Это называется reflow. И он дорогой.

Используйте только CSS-свойства, которые не вызывают reflow: transform, opacity, filter. Для анимаций используйте requestAnimationFrame. Не используйте setInterval или setTimeout для анимаций - они не синхронизированы с частотой обновления экрана.

Если у вас есть список с 50 элементами, которые меняются при прокрутке - не рендерите всё заново. Используйте виртуализацию. Отображайте только те элементы, которые видны на экране. Остальные - скрыты. Это сократит количество DOM-узлов с 50 до 5-10. Это разница между 60 FPS и 10 FPS.

Что ещё можно сделать

Отключите ненужные функции Telegram API. Например, если вы не используете уведомления, не инициализируйте Telegram.WebApp.openTelegramLink() или Telegram.WebApp.showAlert() в начале. Инициализируйте их только тогда, когда пользователь нажимает на кнопку.

Используйте preload и preconnect для критически важных ресурсов. Например, если ваша Mini App загружает шрифт с Google Fonts - добавьте в <head>:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preload" as="font" href="..." type="font/woff2">

Это ускорит загрузку шрифтов на 300-500 мс.

Не используйте CSS-фреймворки вроде Bootstrap. Они добавляют 100+ КБ кода, который вы не используете. Напишите 20 строк стилей на чистом CSS - и вы получите тот же результат, но в 10 раз быстрее.

Итог: 5 шагов к быстрой Mini App

  1. Удалите все ненужные библиотеки. Оставьте только то, что используется.
  2. Сожмите изображения в WebP, используйте SVG для иконок, включите lazy loading.
  3. Разделите JavaScript на чанки и загружайте только необходимое при старте.
  4. Кэшируйте статические ресурсы через Service Workers, сохраняйте данные в localStorage.
  5. Тестируйте на реальном старом телефоне с медленным интернетом.

Если вы сделаете эти 5 вещей - ваша Mini App станет быстрее в 3-8 раз. Пользователи будут открывать её чаще, дольше оставаться в ней и меньше жаловаться. Это не про «лучшие практики». Это про то, чтобы приложение работало. Без сбоев. Без задержек. Без раздражения.

Как проверить, сколько весит моя Mini App?

Откройте Telegram Mini App в браузере на компьютере, нажмите F12, перейдите во вкладку Network. Перезагрузите страницу. Внизу вы увидите общий размер всех загруженных файлов. Если это больше 3 МБ - нужно оптимизировать. Идеально - меньше 1,5 МБ.

Можно ли использовать React или Vue в Mini App?

Можно, но с осторожностью. Эти фреймворки добавляют вес. Если вы используете React, выбирайте React 18+ с Concurrent Mode и минимизируйте количество компонентов. Для простых задач лучше использовать чистый JavaScript и библиотеки вроде Preact (всего 3 КБ). Vue 3 тоже легче, чем Vue 2, но всё равно тяжелее, чем чистый HTML + JS.

Почему Mini App работает медленнее на Android, чем на iPhone?

На Android WebView часто работает с ограничениями, особенно на устройствах с низким уровнем памяти. Apple оптимизирует WebView глубже и дает ему больше ресурсов. Android-устройства могут выделять всего 128 МБ памяти на WebView. Если ваша Mini App использует больше - она будет убиваться системой. Это не ошибка - это особенность платформы.

Нужно ли использовать TypeScript?

Нет, не нужно. TypeScript добавляет слой компиляции, который увеличивает время сборки и размер итогового JavaScript-файла. Для Mini App, где важна скорость загрузки, чистый JavaScript предпочтительнее. TypeScript полезен для больших команд и сложных проектов - но не для мини-приложений с 5 страницами.

Как часто нужно обновлять Mini App?

Обновляйте только при появлении критических багов или изменений в API Telegram. Каждое обновление требует, чтобы пользователь заново загрузил приложение. Частые обновления снижают доверие. Лучше сделать один качественный релиз, чем пять быстрых. Если вы добавляете новую функцию - сделайте её опциональной и включайте по запросу пользователя.