Конфигурация chunks: initial, async, all

В механизме разделения кода Webpack ключевую роль играет настройка optimization.splitChunks.chunks, определяющая, какие типы модулей будут учитываться при формировании отдельных чанков. Значение этого параметра влияет на стратегию кеширования, загрузку асинхронных зависимостей и структуру итогового бандла.

Доступные значения: initial, async, all.


initial

Режим initial ограничивает область анализа только синхронными зависимостями, которые входят в стартовый граф приложения.

Поведение

При chunks: 'initial' Webpack:

  • рассматривает только модули, попадающие в entry chunks;
  • игнорирует динамические импорты (import()), формирующие async chunks;
  • выделяет общие зависимости между entry точками;
  • не влияет на код, загружаемый лениво.

Структура результата

Типичная структура при нескольких entry:

entry A → module shared → vendor
entry B → module shared → vendor

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

Особенности кеширования

  • хорошо работает для классических multi-page приложений;
  • позволяет стабилизировать vendor-часть для первоначальной загрузки;
  • не оптимизирует lazy-loaded код.

Пример конфигурации

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'initial'
    }
  }
};

Ограничения

  • динамические импорты полностью исключены;
  • возможна дубликация кода между async чанками;
  • менее эффективен для SPA архитектур.

async

Режим async ориентирован на код, который загружается лениво через динамические импорты.

Поведение

При chunks: 'async' Webpack:

  • анализирует только async chunks, создаваемые через import();
  • игнорирует начальные (initial) чанки;
  • выделяет общие зависимости только внутри lazy-loaded графов;
  • не влияет на основной bundle.

Принцип работы

Если несколько динамических импортов используют одинаковый модуль, он может быть вынесен в отдельный async chunk:

route A (lazy) ─┐
                ├── shared module → async shared chunk
route B (lazy) ─┘

Пример использования

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'async'
    }
  }
};

Сценарии применения

  • SPA с маршрутизацией (React Router, Vue Router);
  • ленивые страницы и модули;
  • плагины, подгружаемые по требованию.

Плюсы

  • минимальный размер initial bundle;
  • оптимизация времени первой загрузки;
  • изоляция редко используемого кода.

Минусы

  • отсутствие оптимизации между entry и async частями;
  • возможное дублирование общих зависимостей между entry chunks;
  • vendor-библиотеки могут повторяться в разных частях приложения.

all

Режим all является наиболее агрессивной стратегией разделения кода.

Поведение

При chunks: 'all' Webpack:

  • анализирует и initial, и async чанки;
  • ищет повторяющиеся зависимости во всём графе модулей;
  • выносит общие модули в отдельные shared chunks независимо от способа загрузки;
  • стремится минимизировать дублирование максимально глобально.

Общая схема

entry A ─┐
         ├── shared vendor chunk
entry B ─┘

route X (async) ─┐
                 ├── shared async chunk
route Y (async) ─┘

entry + async могут разделять общие зависимости

Конфигурация

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

Особенности

  • единая стратегия оптимизации всего приложения;
  • объединение vendor-библиотек независимо от типа загрузки;
  • максимальное переиспользование кода.

Сравнение режимов

Область анализа

  • initial — только стартовые чанки
  • async — только динамические чанки
  • all — весь граф модулей

Эффективность кеширования

  • initial — средняя
  • async — высокая для ленивых модулей
  • all — максимальная глобальная

Дублирование кода

  • initial — возможно в async части
  • async — возможно в initial части
  • all — минимальное

Влияние на vendor-библиотеки

initial

Библиотеки типа react, lodash, axios попадают только в синхронный граф.

async

Та же библиотека может оказаться в нескольких async чанках, если используется в разных lazy маршрутах.

all

Vendor-логика выносится в единые shared chunks:

vendors~main.js
vendors~routes.js

Влияние на производительность

initial

Оптимален для:

  • серверного рендеринга с минимальной динамикой;
  • приложений с фиксированным набором страниц.

Проблема: слабая оптимизация lazy частей.

async

Оптимален для:

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

Проблема: дублирование общего кода между entry.

all

Оптимален для:

  • крупных SPA;
  • приложений с большим числом пересекающихся зависимостей;
  • сложных UI систем.

Проблема: более сложная стратегия кеширования, возможен рост количества мелких чанков.


Взаимодействие с cacheGroups

Параметр chunks всегда работает в связке с cacheGroups.

Пример:

optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      },
      common: {
        name: 'common',
        minChunks: 2,
        chunks: 'all'
      }
    }
  }
}

Даже при глобальном chunks: 'all', отдельные cacheGroups могут переопределять поведение и дополнительно уточнять стратегию разделения.


Поведение при смешанных сценариях

Entry + dynamic imports

При all:

  • общий код между entry и async будет выделен;
  • динамические и статические зависимости могут попасть в один shared chunk.

При initial:

  • entry оптимизируются отдельно;
  • async полностью изолирован.

При async:

  • entry не участвует в оптимизации;
  • async оптимизируется локально.

Практическая модель выбора

Когда использовать initial

  • multi-page приложения без активного lazy loading;
  • строгая изоляция entry точек;
  • простая архитектура без сложного динамического импорта.

Когда использовать async

  • SPA с маршрутизацией;
  • heavy lazy loading;
  • минимизация initial bundle критична.

Когда использовать all

  • крупные приложения с пересечением зависимостей;
  • необходимость максимального переиспользования кода;
  • сложные системы с множеством entry и dynamic import одновременно.

Тонкости поведения Webpack

Приоритет анализа графа

Webpack сначала строит полный dependency graph, после чего:

  • фильтрует его по значению chunks;
  • применяет cacheGroups;
  • формирует финальные чанки.

Влияние на naming

При all чаще появляются:

  • vendors~
  • common~
  • комбинированные чанки вида vendors~main~route

Это результат пересечения нескольких графов.


Ошибки конфигурации

Избыточное дробление

При all и агрессивных cacheGroups возможно появление слишком большого числа мелких файлов:

  • ухудшение HTTP/2 multiplexing эффекта;
  • рост времени загрузки из-за overhead запросов.

Недоиспользование shared кода

При initial и async часто наблюдается дублирование lodash, date-fns и аналогичных библиотек.

Непредсказуемые чанки

При сложных зависимостях и all структура может становиться менее очевидной без анализа stats.json.