Перейти к содержанию
Innovialabs

Как проанализировать и уменьшить размер JavaScript-бандла

Продвинутое4 мин

Коротко

Сначала посмотрите на бандл через analyzer и найдите самые крупные модули, затем по очереди включите tree shaking, замените тяжёлые зависимости, сузьте полифиллы и перенесите лишнюю работу на сервер, каждый раз фиксируя размер до и после.

Короткий ответ

Размер бандла уменьшают не догадками, а по данным. Рабочий цикл:

  1. Снять базу — сколько JS (сжатого и несжатого) грузится на ключевых страницах.
  2. Найти крупнейшие модули через bundle analyzer.
  3. Убрать или заменить их одним из приёмов ниже.
  4. Перемерить и записать результат.

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

Шаг 1. Анализ бандла

Инструменты строят карту (treemap): каждый прямоугольник — модуль, площадь — его размер.

СтекИнструмент
webpackwebpack-bundle-analyzer
Next.js@next/bundle-analyzer
Vite / Rolluprollup-plugin-visualizer
Любой с source mapssource-map-explorer

Пример для Next.js:

// next.config.js
const withBundleAnalyzer = require("@next/bundle-analyzer")({
  enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({});

Запуск: ANALYZE=true npm run build. Что искать в отчёте:

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

Шаг 2. Tree shaking

Tree shaking — удаление неиспользуемых экспортов при сборке. Работает, когда:

  • код и зависимости используют ES-модули (import/export), а не CommonJS;
  • импорты именованные: import { debounce } from "lodash-es", а не весь пакет;
  • в package.json библиотеки корректно указан sideEffects.

Проверка простая: импортируйте одну функцию и посмотрите в analyzer, сколько кода библиотеки попало в бандл. Если вся — tree shaking не работает.

Шаг 3. Замена тяжёлых библиотек

Частые кандидаты и типовые альтернативы:

  • Даты: крупные библиотеки с локалями → date-fns (модульный импорт), dayjs или встроенный Intl.DateTimeFormat.
  • Утилиты: полный lodash → отдельные функции из lodash-es или нативные методы массивов и объектов.
  • Иконки: импорт всего набора → импорт отдельных иконок или SVG-спрайт.
  • HTTP-клиент: если нужны простые запросы, часто хватает встроенного fetch.
  • Графики и редакторы: не заменять, а загружать лениво через dynamic import.

Перед добавлением новой зависимости проверяйте её размер (например, на bundlephobia) и поддержку tree shaking.

Шаг 4. Лишние полифиллы и транспиляция

Если сборка ориентирована на старые браузеры, в бандл попадают полифиллы и громоздко транспилированный код.

  • Уточните целевые браузеры в browserslist по реальной аудитории из аналитики.
  • Не подключайте полифиллы целиком «на всякий случай» — только для фич, которые реально используются и не поддерживаются вашими целями.
  • Проверьте, не тянет ли какая-то зависимость собственные полифиллы.

Шаг 5. Перенос работы на сервер

Самый эффективный JS — тот, который не отправляется в браузер.

  • Серверный рендеринг и React Server Components: компоненты без интерактивности рендерятся на сервере, их код и зависимости (например, парсер Markdown) не попадают в клиентский бандл.
  • Форматирование, сортировку и фильтрацию больших данных выполняйте на сервере и отдавайте готовый результат.
  • Держите "use client" как можно ниже по дереву компонентов, чтобы не тянуть на клиент лишнее.

Как фиксировать «до и после»

Записывайте результат каждого шага в одну таблицу — так видно, что дало эффект, а что нет:

ИзменениеНачальный JS (gzip/brotli)Начальный JS (несжатый)Lighthouse TBTINP (field)
База————
Tree shaking иконок————
Замена библиотеки дат————
Перенос парсера на сервер————

Заполняйте её своими замерами при одинаковых условиях (тот же билд-режим, та же страница, тот же троттлинг). Чтобы размер не рос обратно, добавьте бюджет в CI — например, size-limit или проверку в Lighthouse CI.

Частые ошибки

  • Оптимизировать по размеру node_modules, а не по реальному бандлу.
  • Смотреть dev-сборку вместо production.
  • Удалять зависимость, но оставлять её импорт в общем модуле.
  • Не следить за размером после релиза — бандл постепенно растёт снова.

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

Универсального числа нет: всё зависит от аудитории, устройств и типа приложения. Ориентируйтесь на Core Web Vitals реальных пользователей и задайте бюджет относительно своей базы.

Поможем с этим

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

Обсудить проект

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

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.