Порядок обработки точек входа

Порядок обработки точек входа в Webpack определяется внутренним механизмом построения графа зависимостей и тем, как сборщик интерпретирует конфигурацию entry. Несмотря на кажущуюся простоту объявления точек входа, фактический процесс их обработки включает несколько стадий: нормализацию входных данных, создание начальных модулей, построение связей между чанками и последующую оптимизацию результирующего графа.

На первом этапе Webpack преобразует значение entry к унифицированному внутреннему виду. Конфигурация может быть задана в нескольких формах: строка, массив строк или объект с именованными точками входа.

Строковое значение рассматривается как единственная точка входа:

entry: "./src/index.js"

Массив трактуется как объединённая точка входа, где все модули загружаются последовательно в один чанк:

entry: ["./src/polyfill.js", "./src/index.js"]

Объектная форма используется для создания нескольких независимых графов:

entry: {
  app: "./src/app.js",
  admin: "./src/admin.js"
}

После нормализации Webpack преобразует каждую запись в структуру, содержащую идентификатор, абсолютный путь и набор дополнительных параметров, если они заданы через объектную форму с dependOn, import, runtime.

Формирование начальных модулей

Каждая точка входа преобразуется в так называемый entry module. Этот модуль становится корнем подграфа зависимостей.

При запуске компиляции происходит резолвинг пути через систему resolver’а Webpack. В этот момент учитываются:

  • алиасы resolve.alias
  • расширения resolve.extensions
  • модули node_modules
  • условные поля exports и main в package.json

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

После этого создаётся объект Module, содержащий:

  • идентификатор модуля
  • путь к файлу
  • тип (ESM, CommonJS, AMD)
  • список зависимостей
  • исходный код после применения loader’ов

Построение графа зависимостей

После создания entry-модулей Webpack начинает рекурсивный обход импортов. Каждый импорт в исходном коде становится ребром графа.

Пример:

import utils from "./utils";
import api from "./api";

Каждый импорт добавляет новый модуль в очередь обработки. Этот процесс называется dependency graph traversal.

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

Если несколько entry точек используют один и тот же модуль, он не создаётся заново, а переиспользуется через систему module graph deduplication.

Разделение на чанки

После построения графа Webpack начинает группировать модули в чанки. Каждая entry точка создаёт отдельный initial chunk.

При этом учитываются следующие правила:

  • каждый entry формирует свой runtime-контекст, если не используется runtime sharing
  • общие модули могут быть вынесены в shared chunks через optimization.splitChunks
  • динамические импорты создают отдельные async chunks

В случае нескольких entry точек возможна следующая структура:

  • app chunk
  • admin chunk
  • vendor chunk (если включена оптимизация разделения)

Обработка зависимостей между entry точками

Webpack поддерживает явное указание зависимостей между entry через dependOn. Это влияет на порядок выполнения и структуру runtime.

Пример:

entry: {
  shared: "./src/shared.js",
  app: {
    import: "./src/app.js",
    dependOn: "shared"
  },
  admin: {
    import: "./src/admin.js",
    dependOn: "shared"
  }
}

В этом случае сначала формируется chunk shared, затем он становится зависимостью для app и admin. Runtime гарантирует, что общий код будет загружен до исполнения зависимых точек входа.

Инициализация runtime и порядок выполнения

После формирования чанков Webpack генерирует runtime-код, который управляет загрузкой модулей. Порядок выполнения entry точек определяется следующим образом:

  1. Сначала исполняются runtime-скрипты
  2. Затем загружаются initial chunks
  3. После загрузки выполняются entry-модули

Если entry точки независимы, порядок их выполнения не гарантируется и зависит от порядка подключения в HTML или загрузчике.

При использовании dependOn или общего runtime порядок становится детерминированным.

Объединение общих зависимостей

Если несколько entry точек используют одинаковые модули, Webpack применяет механизм deduplication:

  • модуль создаётся один раз
  • ссылки на него переиспользуются
  • код может быть вынесен в отдельный chunk

Это особенно важно при больших приложениях, где shared зависимости составляют значительную часть кода.

Влияние cache group на порядок формирования

Оптимизация через splitChunks.cacheGroups влияет на то, как модули распределяются между чанками.

Приоритет групп определяет, в какой chunk попадёт модуль, если он используется в нескольких entry точках.

optimization: {
  splitChunks: {
    cacheGroups: {
      vendor: {
        test: /node_modules/,
        chunks: "all"
      }
    }
  }
}

В этом случае сначала формируются entry chunks, затем анализируются общие зависимости, которые могут быть выделены в vendor chunk.

Асинхронные точки входа и влияние на порядок

Динамические импорты:

import("./module")

не участвуют напрямую в порядке обработки entry, но влияют на расширение графа во время выполнения. Такие чанки создаются лениво и загружаются по требованию, что разрывает строгую последовательность формирования графа.

Приоритеты обработки при компиляции

Webpack внутренне использует очереди задач для модулей:

  • entry modules имеют максимальный приоритет
  • синхронные зависимости обрабатываются сразу после родительского модуля
  • асинхронные модули помещаются в отдельную очередь
  • shared modules могут обрабатываться параллельно

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

Влияние режима сборки

Режим mode влияет на порядок и глубину оптимизации:

  • development: минимальная агрегация, более прямолинейный порядок обработки entry
  • production: агрессивное объединение чанков, перестройка графа для минимизации дублирования

В production порядке формирования чанков может отличаться от декларативного порядка entry, поскольку Webpack оптимизирует структуру исходя из стоимости кода и повторного использования модулей.

Стабильность порядка между сборками

Порядок обработки entry точек не всегда гарантирован между разными запусками сборки. На него могут влиять:

  • параллелизм компиляции
  • кэширование модулей
  • изменения в dependency graph
  • обновление версий loader’ов и plugins

Для стабилизации используется deterministic chunk ids и module ids, что уменьшает вариативность итогового порядка, но не полностью устраняет её в сложных конфигурациях.