Реализация Code Splitting по маршрутам для веб-приложения

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

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Реализация Code Splitting по маршрутам для веб-приложения
Средний
от 1 дня до 3 дней
Часто задаваемые вопросы

Code splitting по маршрутам: где ломается скорость загрузки

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

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

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

Разбираем, как это закрывается: где именно ставить границы разделения, как не породить дубли и чем измерять результат до и после.

Что даёт разделение сборки по маршрутам

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

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

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

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

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

Способы организации разделения: сравнение подходов

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

Вариант Когда подходит Ограничения
Разделение по маршрутам Крупное приложение с чёткими разделами: каталог, кабинет, админка. Каждый маршрут — отдельная точка входа через динамический импорт Общий код дублируется между чанками, если не вынести его в общий модуль; переход между разделами даёт задержку без предзагрузки
Разделение по компонентам Тяжёлые виджеты внутри одной страницы: редактор, графики, карты, модальные окна Много мелких запросов; без грамотной предзагрузки чанков пользователь видит «мигание» при первом взаимодействии
Гибридная схема Продакшн-приложения, где важны и старт, и переходы: маршруты как основа, тяжёлые компоненты — отдельными чанками Сложнее конфигурация сборки и правила предзагрузки; нужен контроль, чтобы чанки не разрастались

Как выбирают на практике

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

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

Этапы внедрения разделения сборки

Внедрение разделения сборки — это не «включить галочку в конфиге», а последовательность инженерных шагов с проверяемым результатом на каждом. Ниже — процесс, по которому мы ведём работы: от аудита текущего бандла до передачи с метриками до/после.

  1. Аудит сборки. Разбираем текущий бандл по чанкам: смотрим, что попадает в стартовый загрузчик, какие зависимости тянут за собой тяжёлые библиотеки, где дублируются модули. На выходе — карта «что грузится всегда, а что нужно только на конкретном экране» и список очевидных кандидатов на вынос.
  2. Схема границ маршрутов. Проектируем, где именно разрезать приложение: по маршрутам верхнего уровня, по вложенным разделам или по сценариям внутри одного экрана. Фиксируем общие модули (авторизация, шапка, дизайн-система) в отдельный общий чанк, чтобы они не дублировались в каждом куске.
  3. Настройка сборщика. Переводим схему в конфигурацию: динамические импорты на границах маршрутов, именование чанков, вынос вендорных зависимостей, предзагрузка вероятных следующих экранов. Отдельно настраиваем поведение при обрыве загрузки чанка — пользователь не должен видеть белый экран.
  4. Проверка метрик. Сравниваем до/после: объём стартового бандла, время до первого рендера, число запросов на первый экран, доля кода, загружаемого по требованию. Смотрим не средние, а худший сценарий — медленное соединение и холодный кеш.
  5. Регресс и краевые случаи. Прогоняем переходы между маршрутами, прямые заходы по глубоким ссылкам, возврат по истории, откат на предыдущую версию приложения при незакрытых чанках.
  6. Документация и передача. Отдаём схему границ, конфигурацию сборщика и правила добавления новых маршрутов, чтобы следующий разработчик не сломал разбиение одной строкой импорта.

Каждый этап заканчивается артефактом, который можно проверить, а не устным «готово».

Конфигурации, схемы маршрутов и регламенты на выходе

Разбиение по маршрутам живёт не в коде, а в конфигурации и договорённостях. Если границы чанков заданы только «на глаз» в одном файле сборщика, через пару релизов никто не вспомнит, почему маршрут оплаты грузится вместе с каталогом, а новый разработчик добавит страницу в общий бандл. Поэтому мы фиксируем результат в артефактах, которые читаются без нас.

  • Конфигурация сборки — правила разбиения: какие маршруты получают отдельный чанк, что выносится в общий (общие компоненты, клиент API, стили), как называются файлы. С комментариями, почему граница проведена именно здесь.
  • Карта маршрутов — таблица «маршрут → чанк → что в нём лежит → когда грузится». По ней видно, где пересекаются зависимости и какой маршрут тянет за собой лишнее.
  • Правила кэширования — заголовки для хешированных чанков и для точек входа: неизменяемые файлы кэшируются надолго, точка входа перепроверяется. Отдельно — поведение при выкатке, чтобы пользователь не получил старую точку входа с новыми чанками.
  • Предзагрузка и приоритеты — какие маршруты подгружаются заранее по навигации, какие по наведению, какие только по клику. Это осознанное решение, а не побочный эффект.
  • Документация — как читать карту маршрутов, где смотреть размеры чанков, что делать при росте бандла.
  • Регламент добавления маршрутов — пошаговый чек-лист: завести маршрут, назначить чанк, проверить пересечения, обновить карту, прогнать проверку размеров в сборке.
  • Проверки в сборке — автоматический контроль: если чанк превысил порог или маршрут попал в общий бандл, сборка предупреждает. Правило работает без напоминаний.

Такой набор переживает смену подрядчика: границы чанков, кэш и порядок добавления страниц описаны явно, а не восстанавливаются по истории коммитов.

Кейс: сокращение стартовой загрузки личного кабинета

Личный кабинет банковского клиента: единый стартовый бандл на 2.8 МБ, время до интерактивности на среднем мобильном канале — 6.4 с. На медленных каналах (3G, перегруженный Wi-Fi в торговых центрах) доля отказов до первого взаимодействия доходила до 23% — пользователь видел белый экран и уходил раньше, чем приложение успевало отрисоваться.

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

Метрики до и после

Метрика До После
Стартовый бандл 2.8 МБ 640 КБ
Время до интерактивности (средний мобильный) 6.4 с 2.1 с
Отказы до первого взаимодействия 23% 7%

Стартовый бандл сократился в 4.4 раза — на экран входа теперь грузится только форма авторизации и общий рантайм. Время до интерактивности упало втрое, а доля отказов на медленных каналах — с 23% до 7%. Конверсия в первый вход выросла на 11 п.п. без изменений в самом сценарии авторизации.

Отдельно настроили метрики производительности в реальном времени: разбивка по маршрутам, время загрузки каждого чанка, доля пользователей, у которых интерактивность не наступает за 4 с. Это позволяет ловить регрессии при каждом релизе, а не через месяц по жалобам. Инструмент — webpack-bundle-analyzer для контроля состава бандлов на этапе сборки.

Чем разделение по маршрутам отличается от разделения по компонентам?

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

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

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

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

Технические сомнения перед внедрением

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

Не пострадает ли SEO, если часть кода грузится по требованию?

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

Как работает предзагрузка и не съедает ли она выгоду от разделения?

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

Что с инвалидацией кэша при обновлении?

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

Как откатывать изменения, если релиз дал регрессию?

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

Если какой-то из этих сценариев у вас уже болел — опишите задачу, вернёмся с оценкой и планом под ваш стек.

Обсудим вашу задачу по разделению сборки

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

Что уточним на нашей стороне:

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

Что нужно от вас для оценки работ:

  • доступ к репозиторию или выгрузка конфигурации сборки и карты маршрутов;
  • описание целевых метрик: время до интерактивности, вес стартового чанка, доля отложенного кода;
  • перечень браузеров и устройств, которые обязаны поддерживаться;
  • ограничения по инфраструктуре: где хостится статика, есть ли CDN, как настроено кеширование.

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

Опишите задачу в свободной форме — что за приложение, какие маршруты и что беспокоит в текущей загрузке. Мы вернёмся с оценкой работ и планом внедрения по этапам.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060