После завершения сборки Webpack формирует не только набор модулей приложения, но и специальный служебный слой — рантайм. Этот код отвечает за запуск, связывание и выполнение модулей в браузере или другой среде выполнения. Он представляет собой bootstrap-обвязку, без которой сгенерированный бандл не способен корректно интерпретировать систему модулей.
Рантайм Webpack выполняет роль минимальной виртуальной модульной системы, реализующей механику загрузки CommonJS-подобных модулей, управление зависимостями и ленивую подгрузку чанков.
Сгенерированный Webpack бандл обычно представляет собой IIFE (Immediately Invoked Function Expression), внутри которой располагаются:
Упрощённая форма выглядит следующим образом:
(() => {
const modules = {
"./src/index.js": (module, exports, __webpack_require__) => {
const dep = __webpack_require__("./src/util.js");
console.log(dep);
},
"./src/util.js": (module, exports) => {
module.exports = "util result";
}
};
const cache = {};
function __webpack_require__(id) {
if (cache[id]) return cache[id].exports;
const module = cache[id] = {
exports: {}
};
modules[id](module, module.exports, __webpack_require__);
return module.exports;
}
__webpack_require__("./src/index.js");
})();
Этот пример отражает базовую идею: Webpack превращает модули в функции, а рантайм обеспечивает их исполнение и кеширование.
Центральным элементом bootstrap-кода является функция
__webpack_require__. Она заменяет стандартную систему
модулей и выполняет несколько ключевых задач:
Каждый модуль выполняется только один раз. Результат сохраняется в кеше:
const cache = {};
if (cache[id]) return cache[id].exports;
Это поведение полностью повторяет семантику ES Modules и CommonJS, где повторный импорт не приводит к повторному выполнению кода.
При первом обращении создаётся объект:
const module = {
exports: {}
};
После выполнения функции модуля этот объект наполняется экспортами.
Каждый модуль получает доступ к __webpack_require__, что
позволяет рекурсивно загружать зависимости:
modules[id](module, module.exports, __webpack_require__);
Webpack компилирует все файлы в единый объект, где ключами выступают идентификаторы модулей (путь, хеш или числовой id), а значениями — функции-обёртки.
Особенности:
__webpack_require__Так достигается изоляция и предсказуемость выполнения кода.
Кеш модулей играет критическую роль в производительности и корректности выполнения.
const cache = {};
function __webpack_require__(id) {
if (cache[id]) {
return cache[id].exports;
}
const module = cache[id] = { exports: {} };
modules[id](module, module.exports, __webpack_require__);
return module.exports;
}
Это обеспечивает:
Webpack runtime способен обрабатывать циклические импорты за счёт
раннего создания объекта module.exports.
При цикле:
Это поведение совпадает с моделью CommonJS.
Одной из ключевых функций рантайма является поддержка code splitting.
При использовании import() Webpack создаёт отдельные
чанки и добавляет механизм их загрузки.
Упрощённая логика выглядит так:
__webpack_require__.e = function(chunkId) {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = chunkId + ".js";
script.onl oad = () => resolve();
script.oner ror = () => reject();
document.head.appendChild(script);
});
};
Загрузка чанка включает:
<script> тегаWebpack часто использует JSONP-подход для интеграции новых модулей в рантайм.
Каждый чанк при загрузке вызывает глобальный callback:
webpackJsonpCallback([chunkIds, modules]);
Рантайм:
Это позволяет асинхронно расширять модульную систему без перезагрузки страницы.
Внутри рантайма присутствуют несколько ключевых структур:
var modules = {};
Хранит все синхронно доступные модули.
var cache = {};
Хранит уже выполненные модули.
var installedChunks = {
main: 0
};
Используется для отслеживания состояния загрузки:
Webpack runtime поддерживает совместимость с ES Modules через специальные helpers:
__webpack_require__.r — пометка модуля как
ESModule__webpack_require__.d — определение
getter-экспортов__webpack_require__.n — обработка default-экспортаПример:
__webpack_require__.r(exports);
__webpack_require__.d(exports, {
value: () => value
});
Это позволяет объединять CommonJS и ES Modules в одном графе зависимостей.
Рантайм Webpack строго контролирует порядок выполнения:
Это обеспечивает детерминированный порядок инициализации.
В production-сборках рантайм подвергается агрессивной оптимизации:
__webpack_require__ →
__webpack_require__ или ещё короче)Это уменьшает размер bootstrap-кода до минимально возможного.
Рантайм является связующим слоем между:
Без него Webpack-выход представлял бы собой набор изолированных функций без механизма взаимодействия.
Фактически рантайм превращает набор файлов в работающую модульную систему, реализующую: