webpack
Version:
Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
619 lines (586 loc) • 20.2 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {string | number} ModuleId */
/** @typedef {Record<string, unknown>} HotData */
/** @typedef {(data: HotData) => void} DisposeHandler */
/** @typedef {(outdatedDependencies: ModuleId[]) => void} AcceptCallback */
/** @typedef {(err: unknown, context: { moduleId: ModuleId, dependencyId: ModuleId }) => void} AcceptErrorHandler */
/** @typedef {{ type: string, moduleId: ModuleId, dependencyId?: ModuleId, error: unknown, originalError?: unknown }} HotErrorEvent */
/** @typedef {(reportError: (err: unknown) => void) => Promise<ModuleId[]>} ApplyFn */
/**
* @typedef {object} ApplyOptions
* @property {boolean=} ignoreUnaccepted ignore unaccepted modules
* @property {boolean=} ignoreDeclined ignore declined modules
* @property {boolean=} ignoreErrored ignore errors thrown while applying
* @property {((event: ModuleEffect) => void)=} onDeclined called for declined modules
* @property {((event: ModuleEffect) => void)=} onUnaccepted called for unaccepted modules
* @property {((event: ModuleEffect) => void)=} onAccepted called for accepted modules
* @property {((event: ModuleEffect) => void)=} onDisposed called for disposed modules
* @property {((event: HotErrorEvent) => void)=} onErrored called on apply errors
*/
/**
* @typedef {object} ApplyResult
* @property {Error=} error fatal error that aborts the update
* @property {(() => void)=} dispose dispose phase of the update
* @property {ApplyFn=} apply apply phase of the update
*/
/** @typedef {(options: ApplyOptions) => ApplyResult} ApplyHandler */
/** @typedef {(moduleId: ModuleId, applyHandlers: ApplyHandler[]) => void} InvalidateModuleHandler */
/** @typedef {(chunkIds: ModuleId[], removedChunks: ModuleId[], removedModules: ModuleId[], promises: Promise<unknown>[], applyHandlers: ApplyHandler[], updatedModulesList: ModuleId[], css: ModuleId[] | undefined, forceLoadChunks: ModuleId[] | undefined) => void} DownloadUpdateHandler */
/** @typedef {(chunkId: ModuleId, promises: Promise<unknown>[]) => void} EnsureChunkHandler */
/** @typedef {(webpackRequire: (id: ModuleId) => unknown) => void} RuntimeModuleFn */
/**
* @typedef {object} Hot
* @property {Record<ModuleId, AcceptCallback>} _acceptedDependencies accept callbacks by dependency id
* @property {Record<ModuleId, AcceptErrorHandler | undefined>} _acceptedErrorHandlers error handlers by dependency id
* @property {Record<ModuleId, boolean>} _declinedDependencies declined dependency ids
* @property {boolean | EXPECTED_FUNCTION} _selfAccepted true or the self-accept error handler
* @property {boolean} _selfDeclined module declined itself
* @property {boolean} _selfInvalidated module invalidated itself
* @property {DisposeHandler[]} _disposeHandlers registered dispose handlers
* @property {boolean} _main module is the entry of the update
* @property {() => void} _requireSelf re-require the module on apply
* @property {boolean} active module is not disposed
*/
/**
* @typedef {object} HotModule
* @property {ModuleId} id module id
* @property {Hot} hot hot API of the module
* @property {ModuleId[]} parents ids of modules requiring this module
* @property {ModuleId[]} children ids of modules required by this module
*/
/**
* @typedef {object} ModuleEffect
* @property {string} type effect type
* @property {ModuleId} moduleId affected module id
* @property {ModuleId[]=} chain update propagation chain
* @property {ModuleId=} parentId declining parent id
* @property {ModuleId[]=} outdatedModules outdated module ids
* @property {Record<ModuleId, ModuleId[]>=} outdatedDependencies outdated dependencies by module id
*/
/** @typedef {{ chain: ModuleId[], id: ModuleId }} QueueItem */
/** @typedef {{ module: ModuleId, require: (id?: ModuleId) => void, errorHandler: boolean | EXPECTED_FUNCTION }} SelfAcceptedModule */
// Globals injected by code generation; declared here only to type the template.
/* eslint-disable no-unassigned-vars */
/** @type {Record<ModuleId, unknown>} */
var $installedChunks$;
/** @type {(chunkId: ModuleId, updatedModulesList?: ModuleId[]) => Promise<unknown>} */
var $loadUpdateChunk$;
/** @type {Record<ModuleId, HotModule>} */
var $moduleCache$;
/** @type {Record<ModuleId, EXPECTED_FUNCTION>} */
var $moduleFactories$;
/** @type {Record<string, EnsureChunkHandler>} */
var $ensureChunkHandlers$;
/** @type {(obj: object, key: ModuleId) => boolean} */
var $hasOwnProperty$;
/** @type {Record<ModuleId, HotData>} */
var $hmrModuleData$;
/** @type {Record<string, DownloadUpdateHandler>} */
var $hmrDownloadUpdateHandlers$;
/** @type {Record<string, InvalidateModuleHandler>} */
var $hmrInvalidateModuleHandlers$;
/** @type {(id: ModuleId) => unknown} */
var __webpack_require__;
/* eslint-enable no-unassigned-vars */
module.exports = function () {
/** @type {Record<ModuleId, boolean>} */
var currentUpdateChunks;
/** @type {Record<ModuleId, EXPECTED_FUNCTION | false>} */
var currentUpdate;
/** @type {ModuleId[]} */
var currentUpdateRemovedChunks;
/** @type {RuntimeModuleFn[]} */
var currentUpdateRuntime;
/**
* @param {ApplyOptions} options apply options
* @returns {ApplyResult} dispose/apply handlers or a fatal error
*/
function applyHandler(options) {
if ($ensureChunkHandlers$) delete $ensureChunkHandlers$.$key$Hmr;
currentUpdateChunks = /** @type {Record<ModuleId, boolean>} */ (
/** @type {unknown} */ (undefined)
);
/**
* @param {ModuleId} updateModuleId updated module id
* @returns {ModuleEffect} effect of updating the module
*/
function getAffectedModuleEffects(updateModuleId) {
/** @type {ModuleId[]} */
var outdatedModules = [updateModuleId];
/** @type {Record<ModuleId, ModuleId[]>} */
var outdatedDependencies = {};
/** @type {QueueItem[]} */
var queue = outdatedModules.map(function (id) {
return {
chain: [id],
id: id
};
});
while (queue.length > 0) {
var queueItem = /** @type {QueueItem} */ (queue.pop());
var moduleId = queueItem.id;
var chain = queueItem.chain;
var module = $moduleCache$[moduleId];
if (
!module ||
(module.hot._selfAccepted && !module.hot._selfInvalidated)
)
continue;
if (module.hot._selfDeclined) {
return {
type: "self-declined",
chain: chain,
moduleId: moduleId
};
}
if (module.hot._main) {
return {
type: "unaccepted",
chain: chain,
moduleId: moduleId
};
}
for (var i = 0; i < module.parents.length; i++) {
var parentId = module.parents[i];
var parent = $moduleCache$[parentId];
if (!parent) continue;
if (parent.hot._declinedDependencies[moduleId]) {
return {
type: "declined",
chain: chain.concat([parentId]),
moduleId: moduleId,
parentId: parentId
};
}
if (outdatedModules.indexOf(parentId) !== -1) continue;
if (parent.hot._acceptedDependencies[moduleId]) {
if (!outdatedDependencies[parentId])
outdatedDependencies[parentId] = [];
addAllToSet(outdatedDependencies[parentId], [moduleId]);
continue;
}
delete outdatedDependencies[parentId];
outdatedModules.push(parentId);
queue.push({
chain: chain.concat([parentId]),
id: parentId
});
}
}
return {
type: "accepted",
moduleId: updateModuleId,
outdatedModules: outdatedModules,
outdatedDependencies: outdatedDependencies
};
}
/**
* @param {ModuleId[]} a target set
* @param {ModuleId[]} b items to add
* @returns {void}
*/
function addAllToSet(a, b) {
for (var i = 0; i < b.length; i++) {
var item = b[i];
if (a.indexOf(item) === -1) a.push(item);
}
}
// at begin all updates modules are outdated
// the "outdated" status can propagate to parents if they don't accept the children
/** @type {Record<ModuleId, ModuleId[]>} */
var outdatedDependencies = {};
/** @type {ModuleId[]} */
var outdatedModules = [];
/** @type {Record<ModuleId, EXPECTED_FUNCTION>} */
var appliedUpdate = {};
/**
* @param {HotModule} module disposed module
* @returns {void}
*/
var warnUnexpectedRequire = function warnUnexpectedRequire(module) {
console.warn(
"[HMR] unexpected require(" + module.id + ") to disposed module"
);
};
for (var moduleId in currentUpdate) {
if ($hasOwnProperty$(currentUpdate, moduleId)) {
var newModuleFactory = currentUpdate[moduleId];
/** @type {ModuleEffect} */
var result = newModuleFactory
? getAffectedModuleEffects(moduleId)
: {
type: "disposed",
moduleId: moduleId
};
/** @type {Error|false} */
var abortError = false;
var doApply = false;
var doDispose = false;
var chainInfo = "";
if (result.chain) {
chainInfo = "\nUpdate propagation: " + result.chain.join(" -> ");
}
switch (result.type) {
case "self-declined":
if (options.onDeclined) options.onDeclined(result);
if (!options.ignoreDeclined)
abortError = new Error(
"Aborted because of self decline: " +
result.moduleId +
chainInfo
);
break;
case "declined":
if (options.onDeclined) options.onDeclined(result);
if (!options.ignoreDeclined)
abortError = new Error(
"Aborted because of declined dependency: " +
result.moduleId +
" in " +
result.parentId +
chainInfo
);
break;
case "unaccepted":
if (options.onUnaccepted) options.onUnaccepted(result);
if (!options.ignoreUnaccepted)
abortError = new Error(
"Aborted because " + moduleId + " is not accepted" + chainInfo
);
break;
case "accepted":
if (options.onAccepted) options.onAccepted(result);
doApply = true;
break;
case "disposed":
if (options.onDisposed) options.onDisposed(result);
doDispose = true;
break;
default:
throw new Error("Unexception type " + result.type);
}
if (abortError) {
return {
error: abortError
};
}
if (doApply) {
appliedUpdate[moduleId] = /** @type {EXPECTED_FUNCTION} */ (
newModuleFactory
);
addAllToSet(
outdatedModules,
/** @type {ModuleId[]} */ (result.outdatedModules)
);
var resultOutdatedDependencies =
/** @type {Record<ModuleId, ModuleId[]>} */ (
result.outdatedDependencies
);
for (moduleId in resultOutdatedDependencies) {
if ($hasOwnProperty$(resultOutdatedDependencies, moduleId)) {
if (!outdatedDependencies[moduleId])
outdatedDependencies[moduleId] = [];
addAllToSet(
outdatedDependencies[moduleId],
resultOutdatedDependencies[moduleId]
);
}
}
}
if (doDispose) {
addAllToSet(outdatedModules, [result.moduleId]);
appliedUpdate[moduleId] = warnUnexpectedRequire;
}
}
}
currentUpdate = /** @type {Record<ModuleId, EXPECTED_FUNCTION | false>} */ (
/** @type {unknown} */ (undefined)
);
// Store self accepted outdated modules to require them later by the module system
/** @type {SelfAcceptedModule[]} */
var outdatedSelfAcceptedModules = [];
for (var j = 0; j < outdatedModules.length; j++) {
var outdatedModuleId = outdatedModules[j];
var module = $moduleCache$[outdatedModuleId];
if (
module &&
(module.hot._selfAccepted || module.hot._main) &&
// removed self-accepted modules should not be required
appliedUpdate[outdatedModuleId] !== warnUnexpectedRequire &&
// when called invalidate self-accepting is not possible
!module.hot._selfInvalidated
) {
outdatedSelfAcceptedModules.push({
module: outdatedModuleId,
require: module.hot._requireSelf,
errorHandler: module.hot._selfAccepted
});
}
}
/** @type {ModuleId[]} */
var moduleOutdatedDependencies;
return {
dispose: function () {
currentUpdateRemovedChunks.forEach(function (chunkId) {
delete $installedChunks$[chunkId];
});
currentUpdateRemovedChunks = /** @type {ModuleId[]} */ (
/** @type {unknown} */ (undefined)
);
var idx;
var queue = outdatedModules.slice();
while (queue.length > 0) {
var moduleId = /** @type {ModuleId} */ (queue.pop());
var module = $moduleCache$[moduleId];
if (!module) continue;
/** @type {HotData} */
var data = {};
// Call dispose handlers
var disposeHandlers = module.hot._disposeHandlers;
for (j = 0; j < disposeHandlers.length; j++) {
disposeHandlers[j].call(null, data);
}
$hmrModuleData$[moduleId] = data;
// disable module (this disables requires from this module)
module.hot.active = false;
// remove module from cache
delete $moduleCache$[moduleId];
// when disposing there is no need to call dispose handler
delete outdatedDependencies[moduleId];
// remove "parents" references from all children
for (j = 0; j < module.children.length; j++) {
var child = $moduleCache$[module.children[j]];
if (!child) continue;
idx = child.parents.indexOf(moduleId);
if (idx >= 0) {
child.parents.splice(idx, 1);
}
}
}
// remove outdated dependency from module children
var dependency;
for (var outdatedModuleId in outdatedDependencies) {
if ($hasOwnProperty$(outdatedDependencies, outdatedModuleId)) {
module = $moduleCache$[outdatedModuleId];
if (module) {
moduleOutdatedDependencies =
outdatedDependencies[outdatedModuleId];
for (j = 0; j < moduleOutdatedDependencies.length; j++) {
dependency = moduleOutdatedDependencies[j];
idx = module.children.indexOf(dependency);
if (idx >= 0) module.children.splice(idx, 1);
}
}
}
}
},
apply: function (reportError) {
/** @type {Promise<unknown>[]} */
var acceptPromises = [];
// insert new code
for (var updateModuleId in appliedUpdate) {
if ($hasOwnProperty$(appliedUpdate, updateModuleId)) {
$moduleFactories$[updateModuleId] = appliedUpdate[updateModuleId];
}
}
// run new runtime modules
for (var i = 0; i < currentUpdateRuntime.length; i++) {
currentUpdateRuntime[i](__webpack_require__);
}
// call accept handlers
for (var outdatedModuleId in outdatedDependencies) {
if ($hasOwnProperty$(outdatedDependencies, outdatedModuleId)) {
var module = $moduleCache$[outdatedModuleId];
if (module) {
moduleOutdatedDependencies =
outdatedDependencies[outdatedModuleId];
/** @type {AcceptCallback[]} */
var callbacks = [];
/** @type {(AcceptErrorHandler | undefined)[]} */
var errorHandlers = [];
/** @type {ModuleId[]} */
var dependenciesForCallbacks = [];
for (var j = 0; j < moduleOutdatedDependencies.length; j++) {
var dependency = moduleOutdatedDependencies[j];
var acceptCallback =
module.hot._acceptedDependencies[dependency];
var errorHandler =
module.hot._acceptedErrorHandlers[dependency];
if (acceptCallback) {
if (callbacks.indexOf(acceptCallback) !== -1) continue;
callbacks.push(acceptCallback);
errorHandlers.push(errorHandler);
dependenciesForCallbacks.push(dependency);
}
}
for (var k = 0; k < callbacks.length; k++) {
/** @type {unknown} */
var result;
try {
result = callbacks[k].call(null, moduleOutdatedDependencies);
} catch (err) {
if (typeof errorHandlers[k] === "function") {
try {
/** @type {AcceptErrorHandler} */
(errorHandlers[k])(err, {
moduleId: outdatedModuleId,
dependencyId: dependenciesForCallbacks[k]
});
} catch (err2) {
if (options.onErrored) {
options.onErrored({
type: "accept-error-handler-errored",
moduleId: outdatedModuleId,
dependencyId: dependenciesForCallbacks[k],
error: err2,
originalError: err
});
}
if (!options.ignoreErrored) {
reportError(err2);
reportError(err);
}
}
} else {
if (options.onErrored) {
options.onErrored({
type: "accept-errored",
moduleId: outdatedModuleId,
dependencyId: dependenciesForCallbacks[k],
error: err
});
}
if (!options.ignoreErrored) {
reportError(err);
}
}
}
if (
result &&
typeof (/** @type {{ then?: unknown }} */ (result).then) ===
"function"
) {
acceptPromises.push(/** @type {Promise<unknown>} */ (result));
}
}
}
}
}
var onAccepted = function () {
// Load self accepted modules
for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) {
var item = outdatedSelfAcceptedModules[o];
var moduleId = item.module;
try {
item.require(moduleId);
} catch (err) {
if (typeof item.errorHandler === "function") {
try {
item.errorHandler(err, {
moduleId: moduleId,
module: $moduleCache$[moduleId]
});
} catch (err1) {
if (options.onErrored) {
options.onErrored({
type: "self-accept-error-handler-errored",
moduleId: moduleId,
error: err1,
originalError: err
});
}
if (!options.ignoreErrored) {
reportError(err1);
reportError(err);
}
}
} else {
if (options.onErrored) {
options.onErrored({
type: "self-accept-errored",
moduleId: moduleId,
error: err
});
}
if (!options.ignoreErrored) {
reportError(err);
}
}
}
}
};
return Promise.all(acceptPromises)
.then(onAccepted)
.then(function () {
return outdatedModules;
});
}
};
}
$hmrInvalidateModuleHandlers$.$key$ = function (moduleId, applyHandlers) {
if (!currentUpdate) {
currentUpdate = {};
currentUpdateRuntime = [];
currentUpdateRemovedChunks = [];
applyHandlers.push(applyHandler);
}
if (!$hasOwnProperty$(currentUpdate, moduleId)) {
currentUpdate[moduleId] = $moduleFactories$[moduleId];
}
};
$hmrDownloadUpdateHandlers$.$key$ = function (
chunkIds,
removedChunks,
removedModules,
promises,
applyHandlers,
updatedModulesList,
css,
forceLoadChunks
) {
applyHandlers.push(applyHandler);
currentUpdateChunks = {};
currentUpdateRemovedChunks = removedChunks;
currentUpdate = removedModules.reduce(function (obj, key) {
obj[key] = false;
return obj;
}, /** @type {Record<ModuleId, EXPECTED_FUNCTION | false>} */ ({}));
currentUpdateRuntime = [];
chunkIds.forEach(function (chunkId) {
if (
$hasOwnProperty$($installedChunks$, chunkId) &&
$installedChunks$[chunkId] !== undefined
) {
promises.push($loadUpdateChunk$(chunkId, updatedModulesList));
currentUpdateChunks[chunkId] = true;
} else {
currentUpdateChunks[chunkId] = false;
}
});
if ($ensureChunkHandlers$) {
$ensureChunkHandlers$.$key$Hmr = function (chunkId, promises) {
if (
currentUpdateChunks &&
$hasOwnProperty$(currentUpdateChunks, chunkId) &&
!currentUpdateChunks[chunkId]
) {
promises.push($loadUpdateChunk$(chunkId));
currentUpdateChunks[chunkId] = true;
}
};
// Force-load chunks that now own modules orphaned by a removed chunk;
// ensure handlers skip already-installed chunks, so no guard is needed.
if (forceLoadChunks) {
forceLoadChunks.forEach(function (chunkId) {
Object.keys($ensureChunkHandlers$).forEach(function (key) {
$ensureChunkHandlers$[key](chunkId, promises);
});
});
}
}
};
};