Webpack в своей основе представляет собой систему построения графа зависимостей и его последующей компиляции в набор оптимизированных бандлов. Центральным элементом этой системы является объект компиляции, который инкапсулирует весь процесс преобразования исходного кода в конечные артефакты сборки.
Компилятор Webpack не является «простой функцией сборки». Это сложная оркестрация этапов, включающая инициализацию конфигурации, создание окружения плагинов, построение графа модулей, оптимизацию, генерацию кода и эмиссию файлов.
Объект Compiler является корневой сущностью всей системы
Webpack. Он создаётся один раз при запуске сборки и далее управляет всем
жизненным циклом процесса компиляции.
Основные функции Compiler:
Compiler можно рассматривать как «движок», который управляет всеми внутренними подсистемами Webpack.
Компиляция проходит через строго определённые стадии, каждая из которых сопровождается хуками плагинов.
На этом этапе:
Ключевой момент: плагины получают доступ к compiler
через метод apply.
class ExamplePlugin {
apply(compiler) {
compiler.hooks.initialize.tap('ExamplePlugin', () => {
// логика инициализации
});
}
}
Метод compiler.run() инициирует процесс однократной
сборки.
Внутренне происходит:
При использовании compiler.watch() Webpack переходит в
режим постоянного наблюдения за файловой системой.
Особенности:
Если Compiler — это глобальный менеджер процесса, то
Compilation — это конкретный снимок одной сборки.
Каждый запуск run или watch создаёт новый
экземпляр Compilation.
Его задачи:
Compilation проходит следующие ключевые этапы:
Каждый этап сопровождается хуками:
buildModulesealoptimizeprocessAssetsСвязь между ними можно описать следующим образом:
В коде Webpack это выражается через создание нового объекта Compilation при каждом запуске:
compiler.hooks.compile.tap('Plugin', (params) => {
const compilation = params.compilation;
});
Webpack поддерживает асинхронность на уровне Compilation:
Это позволяет существенно ускорять сборку в больших проектах.
MultiCompiler — это надстройка над стандартным Compiler,
позволяющая запускать несколько независимых конфигураций в рамках одного
процесса Node.js.
Он создаётся при передаче массива конфигураций:
module.exports = [
configA,
configB,
configC
];
Webpack в этом случае не создаёт один Compiler, а формирует MultiCompiler, который агрегирует несколько независимых Compiler-инстансов.
MultiCompiler можно представить как контейнер:
Ключевая особенность: каждый Compiler остаётся полностью изолированным.
При вызове multiCompiler.run() происходит:
В режиме наблюдения:
Каждый Compiler внутри MultiCompiler:
Это исключает перекрёстное влияние конфигураций.
Несмотря на удобство, MultiCompiler имеет ряд ограничений:
Каждый Compiler работает со своим кешем, что увеличивает потребление памяти.
Одинаковые зависимости в разных конфигурациях обрабатываются независимо.
Ошибки разделены по контекстам компиляторов, что усложняет диагностику.
Типичный случай:
Каждая конфигурация изолирована, но запускается одновременно.
Примеры:
MultiCompiler часто используется для:
MultiCompiler не реализует собственный lifecycle hooks. Вместо этого он:
Каждый Compiler остаётся самостоятельной единицей, что упрощает внутреннюю архитектуру Webpack.
При использовании MultiCompiler события выглядят как:
Но наружу они могут агрегироваться в единый поток логирования.
Это создаёт иллюзию единой сборки при фактически независимых процессах.
Производительность зависит от:
В типичной ситуации MultiCompiler масштабируется линейно по числу конфигураций, что важно учитывать при архитектуре сборки.
Плагины в MultiCompiler:
Однако возможно создание плагинов, которые специально работают с MultiCompiler через проверку типа инстанса.
Архитектурно система выглядит так:
MultiCompiler (опциональный уровень)
Compiler (уровень конфигурации)
Compilation (уровень конкретной сборки)
Эта иерархия определяет масштабируемость Webpack и его поведение в сложных сценариях сборки.