← Вернуться в блог

Что делать, если главный пакет WeChat Mini Program превысил 2 МБ: чек-лист по оптимизации с учетом выгоды

Нажмите «Загрузить», и в инструментах разработчика появится красная надпись: размер главного пакета превышает ограничение в 2 МБ. Публиковать версию нельзя, задачи висят в очереди. В этой статье не будет теоретического обзора, только список способов вернуть размер главного пакета в пределы 2 МБ, отсортированный по принципу «много сэкономить, мало изменить». Сначала разберемся: что именно ограничивает 2 МБ. WeChat устанавливает для кода Mini Program два жёстких лимита: | Ограничение | Верхняя граница | | Главный пакет (включая app.js, страницы tabBar, общие ресурсы и т.д.) | **2 МБ** | | Один подпакет | 2 МБ | | Общий размер всех пакетов | 20 МБ | Обратите внимание: здесь «размер» — это объем уже загруженного кода, а не только JS. В проекте учитываются все файлы, которые попадут в сборку: .js, .wxml, .wxss, ., шрифты, аудио, а также — обычно занимающие львиную долю — **изображения**. Это жёсткое ограничение «не укладываешься — не выйдет релиз», а не просто «лучше оптимизировать». Поэтому первым делом не нужно хвататься за инструмент, а нужно понять, где деньги ушли.

Поделиться

Нажмите «Загрузить», и в инструментах разработчика появится красная надпись: размер главного пакета превышает ограничение в 2 МБ. Публиковать версию нельзя, задачи висят в очереди.
В этой статье не будет теоретического обзора, только список способов вернуть размер главного пакета в пределы 2 МБ, отсортированный по принципу «много сэкономить, мало изменить».


Сначала разберемся: что именно ограничивает 2 МБ

WeChat устанавливает для кода Mini Program два жёстких лимита:

Ограничение Верхняя граница
Главный пакет (включая app.js, страницы tabBar, общие ресурсы и т.д.) 2 МБ
Один подпа́кет 2 МБ
Общий размер всех пакетов 20 МБ

Обратите внимание: здесь «размер» — это объем уже загруженного кода, а не только JS. В проекте учитываются все файлы, которые попадут в сборку: .js、.wxml、.wxss、.、шрифты、аудио, а также — обычно занимающие львиную долю — изображения.

Это жёсткое ограничение «не укладываешься — не выйдет релиз», а не просто «лучше оптимизировать». Поэтому первым делом не нужно хвататься за инструмент, а нужно понять, где деньги ушли.

Шаг 0: Посмотреть, что именно занимает место в главном пакете

В правом верхнем углу инструментов разработчика WeChat можно посмотреть общий размер локального пакета в разделе «Подробнее → Основная информация»; подробнее — в панели инструментов «Анализ зависимостей кода» (Code Dependency Analysis), где можно увидеть объем по файлам и отметить неиспользуемые.

У большинства проектов после просмотра этой таблицы выясняется одна и та же вещь: статические ресурсы, такие как изображения и шрифты, значительно больше бизнес-кода. JS объемом в десятки тысяч строк — это всего несколько сотен КБ, а необработанный баннерный снимок может занимать сотни КБ, а каталог images/ легко съедает половину главного пакета.

Ниже — список мер, отсортированный по выгоде от наибольшей к наименьшей.


Способ 1: Удалить абсолютно бесполезные файлы

Самый простой и часто игнорируемый способ.

  • Файлы, помеченные как неиспользуемые в «Анализе зависимостей»: старые иконки, оставшиеся от прошлых версий,废弃ные страницы, тестовые изображения — удаляем.
  • Файлы, которые не должны попадать в пакет: макеты, README, .psd, исходные материалы, Mock-данные. Если можно вынести их из каталога проекта — выносите; если нет — в project.config. используйте packOptions.ignore для исключения:

{
"packOptions": {
"ignore": [
{ "type": "folder", "value": "design" },
{ "type": "suffix", "value": ".psd" }
]
}
}

  • Полная имплементация библиотеки компонентов: если используется всего три компонента, а в главный пакет попадает вся библиотека UI — это частый «скрытый жирный». Измените на имплементацию по требованию (on-demand), оставив только нужные каталоги компонентов.

Способ 2: Подпакеты — вынести страницы, не являющиеся стартовыми, из главного пакета

Это официальный правильный путь. В главный пакет оставляем только стартовую страницу, страницы tabBar и необходимые общие для них ресурсы. Остальные страницы по бизнес-логике разбиваем на подпакеты:

{
"pages": ["pages/index/index", "pages/mine/mine"],
"subPackages": [
{ "root": "packageOrder", "pages": ["list/list", "detail/detail"] },
{ "root": "packageActivity", "pages": ["index/index"] }
],
"preloadRule": {
"pages/index/index": { "network": "all", "packages": ["packageOrder"] }
}
}

Несколько важных моментов:

  • Ресурсы следуют за страницей. Для картинок и компонентов, используемых в подпакете, их нужно поместить в каталог подпакета. Если они лежат в общем images/ главного пакета, то независимо от того, как вы разбили подпакеты, их объем всё равно будет засчитан в главном пакете.
  • preloadRule — предварительная загрузка. При входе на главную страницу можно «по дороге» скачать тот подпакет, который с высокой вероятностью понадобится дальше. Пользователь почти не почувствует задержки.
  • Независимый подпакет ("independent": true): подходит для страниц мероприятий, лендингов и т.п., которые могут открываться отдельно от главного пакета, без зависимости от него при запуске.
  • Асинхронность подпакетов. При использовании компонентов или JS из других подпакетов можно использовать заглушки и require.async, чтобы не подтягивать код обратно в главный пакет ради «общего» использования.

Цена такого подхода — необходимо менять структуру каталогов и пути переходов. Для старых проектов разборка может занять много времени, именно поэтому сначала имеет смысл выполнить следующий шаг — часто после него главный пакет возвращается в пределы 2 МБ.

Способ 3: Сжать изображения (изменений минимум, выгода максимальная)

Изображения — самая простая часть для «лишнего веса» в главном пакете. PNG из экспорта дизайнера могут содержать лишние блоки данных, качество JPG может быть завышенным. Эти байты пользователю невидимы, но каждый из них учитывается в 2 МБ.

Какие изображения обязаны остаться в пакете

Не все изображения можно перенести в CDN:

  • Иконки tabBar: iconPath / selectedIconPath поддерживают только локальные пути, сетевые изображения не работают.
  • Стартовый экран, логотип главного экрана, резервные изображения. Их нужно показывать и при слабом интернете или офлайне.
  • Маленькие иконки, которые встречаются часто. Загрузка каждого раза по сети невыгодна.

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

Обходная трюк: фоновые изображения в wxss

Использование background-image для локальных изображений в .wxss на реальном устройстве не работает. Частый обходной путь — преобразовать в base64 и встроить. Но кодировка base64 увеличивает объем примерно на треть, и она скрыта в файле стилей, так что в анализе зависимостей заметна не сразу. Если можно использовать компонент <image> или сетевой адрес — не используйте встроенные стили; если встроить обязательно — сначала сожмите исходник, а потом конвертируйте.

Используйте ImgZilla для on-site сжатия целого каталога ресурсов

Самое страшное для разработки Mini Program — после сжатия картинок возвращаться и менять пути — в wxml、в wxss、в конфигурации JS、в конфигурации tabBar. Там повсюду /images/xxx.png. Многие утилиты сохраняют как xxx-min.png или требуют экспортировать в другую папку, и после сжатия нужно вручную заменять и перепроверять, не пропустили ли что-то.

ImgZilla — это инструмент для сжатия изображений для macOS, который работает on-site (без смены имен и путей):

  • Имя файла、путь、формат не меняются. После сжатия icon-home.png по-прежнему icon-home.png, в коде ничего менять не нужно.
  • Просто перетащите целый каталог. Он рекурсивно сканирует все подкаталоги, автоматически пропуская скрытые файлы и node_modules. Перетащите images/、static/ или даже весь каталог проекта — и сразу в инструментах разработчика увидите изменение объема пакета.
  • Исходники по умолчанию перемещаются в корзину. Если что-то не понравится — правый клик «Вернуть на место» — и файл возвращается. Если проект в Git, это дополнительная страховка.
  • Работает локально, без отправки в сеть. Материалы корпоративного проекта не покидают ваш компьютер, и нет ограничений онлайн-сервисов по количеству файлов или размеру.

В плане качества подход отличается для разных форматов:

  • PNG: используется oxipng для без потери качества (lossless). Пиксели не меняются. В Mini Program много иконок и сплайнов — их можно сжимать смело.
  • SVG: удаление избыточных тегов — тоже без потерь.
  • JPG / WebP / GIF и т.д.: сжатие с потерями. Параметры уже настроены на диапазон визуально без потерь — человеческим глазом разницу заметить сложно. Не обязательно слепо доверять; встроенное окно сравнения (⌘D) позволяет сравнивать в реальном времени и детально рассматривать пиксели.

Еще два момента:

  • Он не «жмет» сильно уже оптимизированные изображения. Если степень сжатия менее 0,4%, файл помечается как «уже минимальный» и остается без изменений. Не ради красивой цифры картинка не размывается. Если ваши изображения уже были тщательно оптимизированы, этот шаг может не дать большого эффекта — это нормально и указывает, что пора переходить к подпакетам.
  • Не меняет формат и разрешение. После сжатия PNG остается PNG, размер не меняется. Если вы хотите конвертировать в WebP или уменьшить размер 3x-изображения до 2x — это отдельная задача.

Сколько можно сэкономить зависит от того, как изначально были экспортированы изображения, поэтому конкретный процент не приводится. В качестве ориентира: для тестов мы опубликовали результаты — для уже сжатых JPG сайтов экономия составила 46,8%; для JPG с камер — 76,8% (подробнее в серии «ImgZilla Test»). В Mini Program изображения часто экспортируются прямо из дизайн-софта, обычно не были оптимизированы, поэтому стоит попробовать.

ImgZilla на данный момент только для macOS (macOS 12.3 и выше), доступна в Mac App Store, до 10 изображений бесплатно в день. Для пользователей Windows логика этого раздела применима, нужно просто найти аналогичный инструмент, сохраняющий имена файлов.

Способ 4: Переместить большие изображения в CDN

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

Но это не бесплатно:

  • Первая загрузка идет по сети, при слабом интернете возможны пустые экраны. Лучше использовать заглушки или скелетоны.
  • Нужно поддерживать процесс загрузки、кэширования и обновления.
  • Оплата по трафику CDN. Каждый раз, когда изображение загружается, вы платите. Стоимость примерно равна объему изображения × количеству просмотров. Поэтому, прежде чем переносить в CDN, также имеет смысл сначала сжать изображения — один раз сжатие сэкономит трафик при каждом последующем просмотре.

Способ 5: Финальные штрихи на уровне кода

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

  • В инструментах разработчика в разделе «Подробнее → Локальные настройки» включите сжатие скриптов, стилей и WXML при загрузке.
  • В app. включите "lazyCodeLoading": "requiredComponents" (по требованию). Это в основном влияет на скорость запуска, а не на объем пакета, но если вы занимаетесь оптимизацией — включите и это.
  • Проверьте miniprogram_npm: не имплементируется ли весь пакет npm, когда используются только несколько функций.
  • Длинные статические данные (списки городов, таблицы конфигурации), записанные прямо в JS, лучше передавать через API.

Таблица-резюме

Мера Экономия Изменения Рекомендуемый порядок
Удаление бесполезных файлов Зависит от истории проекта Очень мало 1
On-site сжатие изображений Чем больше изображений и хуже экспорт, тем больше Почти ноль, пути не меняются 2
Подпакеты Может быть много Необходимо менять структуру каталогов и маршрутизацию 3
Перенос больших изображений в CDN Много Нужно менять ссылки, поддерживать процесс загрузки 4
Сжатие кода и имплементация по требованию Мало В зависимости от ситуации 5

Логика проста: сначала мелкие изменения, потом крупные. Удаление файлов и сжатие изображений почти не затрагивают бизнес-код. После этого посмотрите, сколько еще не хватает до 2 МБ — если главный пакет уже в норме, релиз можно публиковать; если нет — переходите к подпакетам и CDN.

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

Нужны изображения легче и быстрее?

Скачайте ImgZilla и сжимайте локально — изображения не покидают ваш Mac.