react-carousel-query
Version:
A infinite carousel component made with react that handles the pagination for you.
1,447 lines (1,333 loc) • 170 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const asyncLib = require("neo-async");
const {
HookMap,
SyncHook,
SyncBailHook,
SyncWaterfallHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncParallelHook
} = require("tapable");
const util = require("util");
const { CachedSource } = require("webpack-sources");
const { MultiItemCache } = require("./CacheFacade");
const Chunk = require("./Chunk");
const ChunkGraph = require("./ChunkGraph");
const ChunkGroup = require("./ChunkGroup");
const ChunkRenderError = require("./ChunkRenderError");
const ChunkTemplate = require("./ChunkTemplate");
const CodeGenerationError = require("./CodeGenerationError");
const CodeGenerationResults = require("./CodeGenerationResults");
const Dependency = require("./Dependency");
const DependencyTemplates = require("./DependencyTemplates");
const Entrypoint = require("./Entrypoint");
const ErrorHelpers = require("./ErrorHelpers");
const FileSystemInfo = require("./FileSystemInfo");
const {
connectChunkGroupAndChunk,
connectChunkGroupParentAndChild
} = require("./GraphHelpers");
const {
makeWebpackError,
tryRunOrWebpackError
} = require("./HookWebpackError");
const MainTemplate = require("./MainTemplate");
const Module = require("./Module");
const ModuleDependencyError = require("./ModuleDependencyError");
const ModuleDependencyWarning = require("./ModuleDependencyWarning");
const ModuleGraph = require("./ModuleGraph");
const ModuleHashingError = require("./ModuleHashingError");
const ModuleNotFoundError = require("./ModuleNotFoundError");
const ModuleProfile = require("./ModuleProfile");
const ModuleRestoreError = require("./ModuleRestoreError");
const ModuleStoreError = require("./ModuleStoreError");
const ModuleTemplate = require("./ModuleTemplate");
const { WEBPACK_MODULE_TYPE_RUNTIME } = require("./ModuleTypeConstants");
const RuntimeGlobals = require("./RuntimeGlobals");
const RuntimeTemplate = require("./RuntimeTemplate");
const Stats = require("./Stats");
const WebpackError = require("./WebpackError");
const buildChunkGraph = require("./buildChunkGraph");
const BuildCycleError = require("./errors/BuildCycleError");
const { Logger, LogType } = require("./logging/Logger");
const StatsFactory = require("./stats/StatsFactory");
const StatsPrinter = require("./stats/StatsPrinter");
const { equals: arrayEquals } = require("./util/ArrayHelpers");
const AsyncQueue = require("./util/AsyncQueue");
const LazySet = require("./util/LazySet");
const { getOrInsert } = require("./util/MapHelpers");
const WeakTupleMap = require("./util/WeakTupleMap");
const { cachedCleverMerge } = require("./util/cleverMerge");
const {
compareLocations,
concatComparators,
compareSelect,
compareIds,
compareStringsNumeric,
compareModulesByIdentifier
} = require("./util/comparators");
const createHash = require("./util/createHash");
const {
arrayToSetDeprecation,
soonFrozenObjectDeprecation,
createFakeHook
} = require("./util/deprecation");
const processAsyncTree = require("./util/processAsyncTree");
const { getRuntimeKey } = require("./util/runtime");
const { isSourceEqual } = require("./util/source");
/** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
/** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("./Cache")} Cache */
/** @typedef {import("./CacheFacade")} CacheFacade */
/** @typedef {import("./Chunk").ChunkId} ChunkId */
/** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./Compiler").CompilationParams} CompilationParams */
/** @typedef {import("./Compiler").ModuleMemCachesItem} ModuleMemCachesItem */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
/** @typedef {import("./Module").BuildInfo} BuildInfo */
/** @typedef {import("./Module").ValueCacheVersions} ValueCacheVersions */
/** @typedef {import("./NormalModule").NormalModuleCompilationHooks} NormalModuleCompilationHooks */
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("./ModuleFactory")} ModuleFactory */
/** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
/** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./RuntimeModule")} RuntimeModule */
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsError} StatsError */
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsModule} StatsModule */
/** @typedef {import("./TemplatedPathPlugin").TemplatePath} TemplatePath */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/createHash").Algorithm} Algorithm */
/**
* @template T
* @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T>
*/
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
/** @typedef {WeakMap<Dependency, Module>} References */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/**
* @callback Callback
* @param {(WebpackError | null)=} err
* @returns {void}
*/
/**
* @callback ModuleCallback
* @param {(WebpackError | null)=} err
* @param {(Module | null)=} result
* @returns {void}
*/
/**
* @callback ModuleFactoryResultCallback
* @param {(WebpackError | null)=} err
* @param {ModuleFactoryResult=} result
* @returns {void}
*/
/**
* @callback ModuleOrFactoryResultCallback
* @param {(WebpackError | null)=} err
* @param {Module | ModuleFactoryResult=} result
* @returns {void}
*/
/**
* @callback ExecuteModuleCallback
* @param {WebpackError | null} err
* @param {ExecuteModuleResult=} result
* @returns {void}
*/
/**
* @callback DepBlockVarDependenciesCallback
* @param {Dependency} dependency
* @returns {any}
*/
/** @typedef {new (...args: any[]) => Dependency} DepConstructor */
/** @typedef {Record<string, Source>} CompilationAssets */
/**
* @typedef {object} AvailableModulesChunkGroupMapping
* @property {ChunkGroup} chunkGroup
* @property {Set<Module>} availableModules
* @property {boolean} needCopy
*/
/**
* @typedef {object} DependenciesBlockLike
* @property {Dependency[]} dependencies
* @property {AsyncDependenciesBlock[]} blocks
*/
/**
* @typedef {object} ChunkPathData
* @property {string|number} id
* @property {string=} name
* @property {string} hash
* @property {function(number): string=} hashWithLength
* @property {(Record<string, string>)=} contentHash
* @property {(Record<string, (length: number) => string>)=} contentHashWithLength
*/
/**
* @typedef {object} ChunkHashContext
* @property {CodeGenerationResults} codeGenerationResults results of code generation
* @property {RuntimeTemplate} runtimeTemplate the runtime template
* @property {ModuleGraph} moduleGraph the module graph
* @property {ChunkGraph} chunkGraph the chunk graph
*/
/**
* @typedef {object} RuntimeRequirementsContext
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {CodeGenerationResults} codeGenerationResults the code generation results
*/
/**
* @typedef {object} ExecuteModuleOptions
* @property {EntryOptions=} entryOptions
*/
/**
* @typedef {object} ExecuteModuleResult
* @property {any} exports
* @property {boolean} cacheable
* @property {Map<string, { source: Source, info: AssetInfo }>} assets
* @property {LazySet<string>} fileDependencies
* @property {LazySet<string>} contextDependencies
* @property {LazySet<string>} missingDependencies
* @property {LazySet<string>} buildDependencies
*/
/**
* @typedef {{ id: string, exports: any, loaded: boolean }} ModuleObject
*
* /**
* @typedef {object} ExecuteModuleArgument
* @property {Module} module
* @property {ModuleObject=} moduleObject
* @property {any} preparedInfo
* @property {CodeGenerationResult} codeGenerationResult
*/
/**
* @typedef {object} ExecuteModuleContext
* @property {Map<string, { source: Source, info: AssetInfo }>} assets
* @property {Chunk} chunk
* @property {ChunkGraph} chunkGraph
* @property {function(string): any=} __webpack_require__
*/
/**
* @typedef {object} EntryData
* @property {Dependency[]} dependencies dependencies of the entrypoint that should be evaluated at startup
* @property {Dependency[]} includeDependencies dependencies of the entrypoint that should be included but not evaluated
* @property {EntryOptions} options options of the entrypoint
*/
/**
* @typedef {object} LogEntry
* @property {string} type
* @property {any[]=} args
* @property {number} time
* @property {string[]=} trace
*/
/**
* @typedef {object} KnownAssetInfo
* @property {boolean=} immutable true, if the asset can be long term cached forever (contains a hash)
* @property {boolean=} minimized whether the asset is minimized
* @property {string | string[]=} fullhash the value(s) of the full hash used for this asset
* @property {string | string[]=} chunkhash the value(s) of the chunk hash used for this asset
* @property {string | string[]=} modulehash the value(s) of the module hash used for this asset
* @property {string | string[]=} contenthash the value(s) of the content hash used for this asset
* @property {string=} sourceFilename when asset was created from a source file (potentially transformed), the original filename relative to compilation context
* @property {number=} size size in bytes, only set after asset has been emitted
* @property {boolean=} development true, when asset is only used for development and doesn't count towards user-facing assets
* @property {boolean=} hotModuleReplacement true, when asset ships data for updating an existing application (HMR)
* @property {boolean=} javascriptModule true, when asset is javascript and an ESM
* @property {Record<string, string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
*/
/** @typedef {KnownAssetInfo & Record<string, any>} AssetInfo */
/** @typedef {{ path: string, info: AssetInfo }} InterpolatedPathAndAssetInfo */
/**
* @typedef {object} Asset
* @property {string} name the filename of the asset
* @property {Source} source source of the asset
* @property {AssetInfo} info info about the asset
*/
/**
* @typedef {object} ModulePathData
* @property {string|number} id
* @property {string} hash
* @property {function(number): string=} hashWithLength
*/
/**
* @typedef {object} PathData
* @property {ChunkGraph=} chunkGraph
* @property {string=} hash
* @property {function(number): string=} hashWithLength
* @property {(Chunk|ChunkPathData)=} chunk
* @property {(Module|ModulePathData)=} module
* @property {RuntimeSpec=} runtime
* @property {string=} filename
* @property {string=} basename
* @property {string=} query
* @property {string=} contentHashType
* @property {string=} contentHash
* @property {function(number): string=} contentHashWithLength
* @property {boolean=} noChunkHash
* @property {string=} url
*/
/**
* @typedef {object} KnownNormalizedStatsOptions
* @property {string} context
* @property {RequestShortener} requestShortener
* @property {string} chunksSort
* @property {string} modulesSort
* @property {string} chunkModulesSort
* @property {string} nestedModulesSort
* @property {string} assetsSort
* @property {boolean} ids
* @property {boolean} cachedAssets
* @property {boolean} groupAssetsByEmitStatus
* @property {boolean} groupAssetsByPath
* @property {boolean} groupAssetsByExtension
* @property {number} assetsSpace
* @property {((value: string, asset: StatsAsset) => boolean)[]} excludeAssets
* @property {((name: string, module: StatsModule, type: "module" | "chunk" | "root-of-chunk" | "nested") => boolean)[]} excludeModules
* @property {((warning: StatsError, textValue: string) => boolean)[]} warningsFilter
* @property {boolean} cachedModules
* @property {boolean} orphanModules
* @property {boolean} dependentModules
* @property {boolean} runtimeModules
* @property {boolean} groupModulesByCacheStatus
* @property {boolean} groupModulesByLayer
* @property {boolean} groupModulesByAttributes
* @property {boolean} groupModulesByPath
* @property {boolean} groupModulesByExtension
* @property {boolean} groupModulesByType
* @property {boolean | "auto"} entrypoints
* @property {boolean} chunkGroups
* @property {boolean} chunkGroupAuxiliary
* @property {boolean} chunkGroupChildren
* @property {number} chunkGroupMaxAssets
* @property {number} modulesSpace
* @property {number} chunkModulesSpace
* @property {number} nestedModulesSpace
* @property {false|"none"|"error"|"warn"|"info"|"log"|"verbose"} logging
* @property {((value: string) => boolean)[]} loggingDebug
* @property {boolean} loggingTrace
* @property {any} _env
*/
/** @typedef {KnownNormalizedStatsOptions & Omit<StatsOptions, keyof KnownNormalizedStatsOptions> & Record<string, any>} NormalizedStatsOptions */
/**
* @typedef {object} KnownCreateStatsOptionsContext
* @property {boolean=} forToString
*/
/** @typedef {Record<string, any> & KnownCreateStatsOptionsContext} CreateStatsOptionsContext */
/** @typedef {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} CodeGenerationJobs */
/** @typedef {{javascript: ModuleTemplate}} ModuleTemplates */
/** @typedef {Set<Module>} NotCodeGeneratedModules */
/** @type {AssetInfo} */
const EMPTY_ASSET_INFO = Object.freeze({});
const esmDependencyCategory = "esm";
// TODO webpack 6: remove
const deprecatedNormalModuleLoaderHook = util.deprecate(
/**
* @param {Compilation} compilation compilation
* @returns {NormalModuleCompilationHooks["loader"]} hooks
*/
compilation =>
require("./NormalModule").getCompilationHooks(compilation).loader,
"Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader",
"DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK"
);
// TODO webpack 6: remove
/**
* @param {ModuleTemplates | undefined} moduleTemplates module templates
*/
const defineRemovedModuleTemplates = moduleTemplates => {
Object.defineProperties(moduleTemplates, {
asset: {
enumerable: false,
configurable: false,
get: () => {
throw new WebpackError(
"Compilation.moduleTemplates.asset has been removed"
);
}
},
webassembly: {
enumerable: false,
configurable: false,
get: () => {
throw new WebpackError(
"Compilation.moduleTemplates.webassembly has been removed"
);
}
}
});
moduleTemplates = undefined;
};
const byId = compareSelect(c => c.id, compareIds);
const byNameOrHash = concatComparators(
compareSelect(c => c.name, compareIds),
compareSelect(c => c.fullHash, compareIds)
);
const byMessage = compareSelect(err => `${err.message}`, compareStringsNumeric);
const byModule = compareSelect(
err => (err.module && err.module.identifier()) || "",
compareStringsNumeric
);
const byLocation = compareSelect(err => err.loc, compareLocations);
const compareErrors = concatComparators(byModule, byLocation, byMessage);
/** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */
const unsafeCacheDependencies = new WeakMap();
/** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, object>} */
const unsafeCacheData = new WeakMap();
class Compilation {
/**
* Creates an instance of Compilation.
* @param {Compiler} compiler the compiler which created the compilation
* @param {CompilationParams} params the compilation parameters
*/
constructor(compiler, params) {
this._backCompat = compiler._backCompat;
const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
/** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
/** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
const processAssetsHook = new AsyncSeriesHook(["assets"]);
let savedAssets = new Set();
/**
* @param {CompilationAssets} assets assets
* @returns {CompilationAssets} new assets
*/
const popNewAssets = assets => {
let newAssets;
for (const file of Object.keys(assets)) {
if (savedAssets.has(file)) continue;
if (newAssets === undefined) {
newAssets = Object.create(null);
}
newAssets[file] = assets[file];
savedAssets.add(file);
}
return newAssets;
};
processAssetsHook.intercept({
name: "Compilation",
call: () => {
savedAssets = new Set(Object.keys(this.assets));
},
register: tap => {
const { type, name } = tap;
const { fn, additionalAssets, ...remainingTap } = tap;
const additionalAssetsFn =
additionalAssets === true ? fn : additionalAssets;
const processedAssets = additionalAssetsFn ? new WeakSet() : undefined;
switch (type) {
case "sync":
if (additionalAssetsFn) {
this.hooks.processAdditionalAssets.tap(name, assets => {
if (processedAssets.has(this.assets))
additionalAssetsFn(assets);
});
}
return {
...remainingTap,
type: "async",
fn: (assets, callback) => {
try {
fn(assets);
} catch (err) {
return callback(err);
}
if (processedAssets !== undefined)
processedAssets.add(this.assets);
const newAssets = popNewAssets(assets);
if (newAssets !== undefined) {
this.hooks.processAdditionalAssets.callAsync(
newAssets,
callback
);
return;
}
callback();
}
};
case "async":
if (additionalAssetsFn) {
this.hooks.processAdditionalAssets.tapAsync(
name,
(assets, callback) => {
if (processedAssets.has(this.assets))
return additionalAssetsFn(assets, callback);
callback();
}
);
}
return {
...remainingTap,
fn: (assets, callback) => {
fn(assets, err => {
if (err) return callback(err);
if (processedAssets !== undefined)
processedAssets.add(this.assets);
const newAssets = popNewAssets(assets);
if (newAssets !== undefined) {
this.hooks.processAdditionalAssets.callAsync(
newAssets,
callback
);
return;
}
callback();
});
}
};
case "promise":
if (additionalAssetsFn) {
this.hooks.processAdditionalAssets.tapPromise(name, assets => {
if (processedAssets.has(this.assets))
return additionalAssetsFn(assets);
return Promise.resolve();
});
}
return {
...remainingTap,
fn: assets => {
const p = fn(assets);
if (!p || !p.then) return p;
return p.then(() => {
if (processedAssets !== undefined)
processedAssets.add(this.assets);
const newAssets = popNewAssets(assets);
if (newAssets !== undefined) {
return this.hooks.processAdditionalAssets.promise(
newAssets
);
}
});
}
};
}
}
});
/** @type {SyncHook<[CompilationAssets]>} */
const afterProcessAssetsHook = new SyncHook(["assets"]);
/**
* @template T
* @param {string} name name of the hook
* @param {number} stage new stage
* @param {function(): AsArray<T>} getArgs get old hook function args
* @param {string=} code deprecation code (not deprecated when unset)
* @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects
*/
const createProcessAssetsHook = (name, stage, getArgs, code) => {
if (!this._backCompat && code) return;
/**
* @param {string} reason reason
* @returns {string} error message
*/
const errorMessage =
reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;
const getOptions = options => {
if (typeof options === "string") options = { name: options };
if (options.stage) {
throw new Error(errorMessage("it's using the 'stage' option"));
}
return { ...options, stage };
};
return createFakeHook(
{
name,
/** @type {AsyncSeriesHook<T>["intercept"]} */
intercept(interceptor) {
throw new Error(errorMessage("it's using 'intercept'"));
},
/** @type {AsyncSeriesHook<T>["tap"]} */
tap: (options, fn) => {
processAssetsHook.tap(getOptions(options), () => fn(...getArgs()));
},
/** @type {AsyncSeriesHook<T>["tapAsync"]} */
tapAsync: (options, fn) => {
processAssetsHook.tapAsync(
getOptions(options),
(assets, callback) =>
/** @type {any} */ (fn)(...getArgs(), callback)
);
},
/** @type {AsyncSeriesHook<T>["tapPromise"]} */
tapPromise: (options, fn) => {
processAssetsHook.tapPromise(getOptions(options), () =>
fn(...getArgs())
);
}
},
`${name} is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)`,
code
);
};
this.hooks = Object.freeze({
/** @type {SyncHook<[Module]>} */
buildModule: new SyncHook(["module"]),
/** @type {SyncHook<[Module]>} */
rebuildModule: new SyncHook(["module"]),
/** @type {SyncHook<[Module, WebpackError]>} */
failedModule: new SyncHook(["module", "error"]),
/** @type {SyncHook<[Module]>} */
succeedModule: new SyncHook(["module"]),
/** @type {SyncHook<[Module]>} */
stillValidModule: new SyncHook(["module"]),
/** @type {SyncHook<[Dependency, EntryOptions]>} */
addEntry: new SyncHook(["entry", "options"]),
/** @type {SyncHook<[Dependency, EntryOptions, Error]>} */
failedEntry: new SyncHook(["entry", "options", "error"]),
/** @type {SyncHook<[Dependency, EntryOptions, Module]>} */
succeedEntry: new SyncHook(["entry", "options", "module"]),
/** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency, RuntimeSpec]>} */
dependencyReferencedExports: new SyncWaterfallHook([
"referencedExports",
"dependency",
"runtime"
]),
/** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
executeModule: new SyncHook(["options", "context"]),
/** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
prepareModuleExecution: new AsyncParallelHook(["options", "context"]),
/** @type {AsyncSeriesHook<[Iterable<Module>]>} */
finishModules: new AsyncSeriesHook(["modules"]),
/** @type {AsyncSeriesHook<[Module]>} */
finishRebuildingModule: new AsyncSeriesHook(["module"]),
/** @type {SyncHook<[]>} */
unseal: new SyncHook([]),
/** @type {SyncHook<[]>} */
seal: new SyncHook([]),
/** @type {SyncHook<[]>} */
beforeChunks: new SyncHook([]),
/**
* The `afterChunks` hook is called directly after the chunks and module graph have
* been created and before the chunks and modules have been optimized. This hook is useful to
* inspect, analyze, and/or modify the chunk graph.
* @type {SyncHook<[Iterable<Chunk>]>}
*/
afterChunks: new SyncHook(["chunks"]),
/** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
optimizeDependencies: new SyncBailHook(["modules"]),
/** @type {SyncHook<[Iterable<Module>]>} */
afterOptimizeDependencies: new SyncHook(["modules"]),
/** @type {SyncHook<[]>} */
optimize: new SyncHook([]),
/** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
optimizeModules: new SyncBailHook(["modules"]),
/** @type {SyncHook<[Iterable<Module>]>} */
afterOptimizeModules: new SyncHook(["modules"]),
/** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]], boolean | void>} */
optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
/** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */
afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
/** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */
optimizeTree: new AsyncSeriesHook(["chunks", "modules"]),
/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
afterOptimizeTree: new SyncHook(["chunks", "modules"]),
/** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>], void>} */
optimizeChunkModules: new AsyncSeriesBailHook(["chunks", "modules"]),
/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
/** @type {SyncBailHook<[], boolean | void>} */
shouldRecord: new SyncBailHook([]),
/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
additionalChunkRuntimeRequirements: new SyncHook([
"chunk",
"runtimeRequirements",
"context"
]),
/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */
runtimeRequirementInChunk: new HookMap(
() => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
),
/** @type {SyncHook<[Module, Set<string>, RuntimeRequirementsContext]>} */
additionalModuleRuntimeRequirements: new SyncHook([
"module",
"runtimeRequirements",
"context"
]),
/** @type {HookMap<SyncBailHook<[Module, Set<string>, RuntimeRequirementsContext], void>>} */
runtimeRequirementInModule: new HookMap(
() => new SyncBailHook(["module", "runtimeRequirements", "context"])
),
/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
additionalTreeRuntimeRequirements: new SyncHook([
"chunk",
"runtimeRequirements",
"context"
]),
/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */
runtimeRequirementInTree: new HookMap(
() => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
),
/** @type {SyncHook<[RuntimeModule, Chunk]>} */
runtimeModule: new SyncHook(["module", "chunk"]),
/** @type {SyncHook<[Iterable<Module>, any]>} */
reviveModules: new SyncHook(["modules", "records"]),
/** @type {SyncHook<[Iterable<Module>]>} */
beforeModuleIds: new SyncHook(["modules"]),
/** @type {SyncHook<[Iterable<Module>]>} */
moduleIds: new SyncHook(["modules"]),
/** @type {SyncHook<[Iterable<Module>]>} */
optimizeModuleIds: new SyncHook(["modules"]),
/** @type {SyncHook<[Iterable<Module>]>} */
afterOptimizeModuleIds: new SyncHook(["modules"]),
/** @type {SyncHook<[Iterable<Chunk>, any]>} */
reviveChunks: new SyncHook(["chunks", "records"]),
/** @type {SyncHook<[Iterable<Chunk>]>} */
beforeChunkIds: new SyncHook(["chunks"]),
/** @type {SyncHook<[Iterable<Chunk>]>} */
chunkIds: new SyncHook(["chunks"]),
/** @type {SyncHook<[Iterable<Chunk>]>} */
optimizeChunkIds: new SyncHook(["chunks"]),
/** @type {SyncHook<[Iterable<Chunk>]>} */
afterOptimizeChunkIds: new SyncHook(["chunks"]),
/** @type {SyncHook<[Iterable<Module>, any]>} */
recordModules: new SyncHook(["modules", "records"]),
/** @type {SyncHook<[Iterable<Chunk>, any]>} */
recordChunks: new SyncHook(["chunks", "records"]),
/** @type {SyncHook<[Iterable<Module>]>} */
optimizeCodeGeneration: new SyncHook(["modules"]),
/** @type {SyncHook<[]>} */
beforeModuleHash: new SyncHook([]),
/** @type {SyncHook<[]>} */
afterModuleHash: new SyncHook([]),
/** @type {SyncHook<[]>} */
beforeCodeGeneration: new SyncHook([]),
/** @type {SyncHook<[]>} */
afterCodeGeneration: new SyncHook([]),
/** @type {SyncHook<[]>} */
beforeRuntimeRequirements: new SyncHook([]),
/** @type {SyncHook<[]>} */
afterRuntimeRequirements: new SyncHook([]),
/** @type {SyncHook<[]>} */
beforeHash: new SyncHook([]),
/** @type {SyncHook<[Chunk]>} */
contentHash: new SyncHook(["chunk"]),
/** @type {SyncHook<[]>} */
afterHash: new SyncHook([]),
/** @type {SyncHook<[any]>} */
recordHash: new SyncHook(["records"]),
/** @type {SyncHook<[Compilation, any]>} */
record: new SyncHook(["compilation", "records"]),
/** @type {SyncHook<[]>} */
beforeModuleAssets: new SyncHook([]),
/** @type {SyncBailHook<[], boolean | void>} */
shouldGenerateChunkAssets: new SyncBailHook([]),
/** @type {SyncHook<[]>} */
beforeChunkAssets: new SyncHook([]),
// TODO webpack 6 remove
/** @deprecated */
additionalChunkAssets: createProcessAssetsHook(
"additionalChunkAssets",
Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
() => [this.chunks],
"DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS"
),
// TODO webpack 6 deprecate
/** @deprecated */
additionalAssets: createProcessAssetsHook(
"additionalAssets",
Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
() => []
),
// TODO webpack 6 remove
/** @deprecated */
optimizeChunkAssets: createProcessAssetsHook(
"optimizeChunkAssets",
Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
() => [this.chunks],
"DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS"
),
// TODO webpack 6 remove
/** @deprecated */
afterOptimizeChunkAssets: createProcessAssetsHook(
"afterOptimizeChunkAssets",
Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1,
() => [this.chunks],
"DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS"
),
// TODO webpack 6 deprecate
/** @deprecated */
optimizeAssets: processAssetsHook,
// TODO webpack 6 deprecate
/** @deprecated */
afterOptimizeAssets: afterProcessAssetsHook,
processAssets: processAssetsHook,
afterProcessAssets: afterProcessAssetsHook,
/** @type {AsyncSeriesHook<[CompilationAssets]>} */
processAdditionalAssets: new AsyncSeriesHook(["assets"]),
/** @type {SyncBailHook<[], boolean | void>} */
needAdditionalSeal: new SyncBailHook([]),
/** @type {AsyncSeriesHook<[]>} */
afterSeal: new AsyncSeriesHook([]),
/** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
renderManifest: new SyncWaterfallHook(["result", "options"]),
/** @type {SyncHook<[Hash]>} */
fullHash: new SyncHook(["hash"]),
/** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */
chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]),
/** @type {SyncHook<[Module, string]>} */
moduleAsset: new SyncHook(["module", "filename"]),
/** @type {SyncHook<[Chunk, string]>} */
chunkAsset: new SyncHook(["chunk", "filename"]),
/** @type {SyncWaterfallHook<[string, object, AssetInfo | undefined]>} */
assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]),
/** @type {SyncBailHook<[], boolean | void>} */
needAdditionalPass: new SyncBailHook([]),
/** @type {SyncHook<[Compiler, string, number]>} */
childCompiler: new SyncHook([
"childCompiler",
"compilerName",
"compilerIndex"
]),
/** @type {SyncBailHook<[string, LogEntry], boolean | void>} */
log: new SyncBailHook(["origin", "logEntry"]),
/** @type {SyncWaterfallHook<[WebpackError[]]>} */
processWarnings: new SyncWaterfallHook(["warnings"]),
/** @type {SyncWaterfallHook<[WebpackError[]]>} */
processErrors: new SyncWaterfallHook(["errors"]),
/** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */
statsPreset: new HookMap(() => new SyncHook(["options", "context"])),
/** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */
statsNormalize: new SyncHook(["options", "context"]),
/** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */
statsFactory: new SyncHook(["statsFactory", "options"]),
/** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */
statsPrinter: new SyncHook(["statsPrinter", "options"]),
get normalModuleLoader() {
return getNormalModuleLoader();
}
});
/** @type {string=} */
this.name = undefined;
/** @type {number | undefined} */
this.startTime = undefined;
/** @type {number | undefined} */
this.endTime = undefined;
/** @type {Compiler} */
this.compiler = compiler;
this.resolverFactory = compiler.resolverFactory;
/** @type {InputFileSystem} */
this.inputFileSystem =
/** @type {InputFileSystem} */
(compiler.inputFileSystem);
this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, {
unmanagedPaths: compiler.unmanagedPaths,
managedPaths: compiler.managedPaths,
immutablePaths: compiler.immutablePaths,
logger: this.getLogger("webpack.FileSystemInfo"),
hashFunction: compiler.options.output.hashFunction
});
if (compiler.fileTimestamps) {
this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
}
if (compiler.contextTimestamps) {
this.fileSystemInfo.addContextTimestamps(
compiler.contextTimestamps,
true
);
}
/** @type {ValueCacheVersions} */
this.valueCacheVersions = new Map();
this.requestShortener = compiler.requestShortener;
this.compilerPath = compiler.compilerPath;
this.logger = this.getLogger("webpack.Compilation");
const options = /** @type {WebpackOptions} */ (compiler.options);
this.options = options;
this.outputOptions = options && options.output;
/** @type {boolean} */
this.bail = (options && options.bail) || false;
/** @type {boolean} */
this.profile = (options && options.profile) || false;
this.params = params;
this.mainTemplate = new MainTemplate(this.outputOptions, this);
this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
this.runtimeTemplate = new RuntimeTemplate(
this,
this.outputOptions,
this.requestShortener
);
/** @type {ModuleTemplates} */
this.moduleTemplates = {
javascript: new ModuleTemplate(this.runtimeTemplate, this)
};
defineRemovedModuleTemplates(this.moduleTemplates);
/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
this.moduleMemCaches = undefined;
/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
this.moduleMemCaches2 = undefined;
this.moduleGraph = new ModuleGraph();
/** @type {ChunkGraph} */
this.chunkGraph = undefined;
/** @type {CodeGenerationResults} */
this.codeGenerationResults = undefined;
/** @type {AsyncQueue<Module, Module, Module>} */
this.processDependenciesQueue = new AsyncQueue({
name: "processDependencies",
parallelism: options.parallelism || 100,
processor: this._processModuleDependencies.bind(this)
});
/** @type {AsyncQueue<Module, string, Module>} */
this.addModuleQueue = new AsyncQueue({
name: "addModule",
parent: this.processDependenciesQueue,
getKey: module => module.identifier(),
processor: this._addModule.bind(this)
});
/** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
this.factorizeQueue = new AsyncQueue({
name: "factorize",
parent: this.addModuleQueue,
processor: this._factorizeModule.bind(this)
});
/** @type {AsyncQueue<Module, Module, Module>} */
this.buildQueue = new AsyncQueue({
name: "build",
parent: this.factorizeQueue,
processor: this._buildModule.bind(this)
});
/** @type {AsyncQueue<Module, Module, Module>} */
this.rebuildQueue = new AsyncQueue({
name: "rebuild",
parallelism: options.parallelism || 100,
processor: this._rebuildModule.bind(this)
});
/**
* Modules in value are building during the build of Module in key.
* Means value blocking key from finishing.
* Needed to detect build cycles.
* @type {WeakMap<Module, Set<Module>>}
*/
this.creatingModuleDuringBuild = new WeakMap();
/** @type {Map<string, EntryData>} */
this.entries = new Map();
/** @type {EntryData} */
this.globalEntry = {
dependencies: [],
includeDependencies: [],
options: {
name: undefined
}
};
/** @type {Map<string, Entrypoint>} */
this.entrypoints = new Map();
/** @type {Entrypoint[]} */
this.asyncEntrypoints = [];
/** @type {Set<Chunk>} */
this.chunks = new Set();
/** @type {ChunkGroup[]} */
this.chunkGroups = [];
/** @type {Map<string, ChunkGroup>} */
this.namedChunkGroups = new Map();
/** @type {Map<string, Chunk>} */
this.namedChunks = new Map();
/** @type {Set<Module>} */
this.modules = new Set();
if (this._backCompat) {
arrayToSetDeprecation(this.chunks, "Compilation.chunks");
arrayToSetDeprecation(this.modules, "Compilation.modules");
}
/**
* @private
* @type {Map<string, Module>}
*/
this._modules = new Map();
this.records = null;
/** @type {string[]} */
this.additionalChunkAssets = [];
/** @type {CompilationAssets} */
this.assets = {};
/** @type {Map<string, AssetInfo>} */
this.assetsInfo = new Map();
/** @type {Map<string, Map<string, Set<string>>>} */
this._assetsRelatedIn = new Map();
/** @type {WebpackError[]} */
this.errors = [];
/** @type {WebpackError[]} */
this.warnings = [];
/** @type {Compilation[]} */
this.children = [];
/** @type {Map<string, LogEntry[]>} */
this.logging = new Map();
/** @type {Map<DepConstructor, ModuleFactory>} */
this.dependencyFactories = new Map();
/** @type {DependencyTemplates} */
this.dependencyTemplates = new DependencyTemplates(
this.outputOptions.hashFunction
);
/** @type {Record<string, number>} */
this.childrenCounters = {};
/** @type {Set<number|string>} */
this.usedChunkIds = null;
/** @type {Set<number>} */
this.usedModuleIds = null;
/** @type {boolean} */
this.needAdditionalPass = false;
/** @type {Set<Module & { restoreFromUnsafeCache: Function }>} */
this._restoredUnsafeCacheModuleEntries = new Set();
/** @type {Map<string, Module & { restoreFromUnsafeCache: Function }>} */
this._restoredUnsafeCacheEntries = new Map();
/** @type {WeakSet<Module>} */
this.builtModules = new WeakSet();
/** @type {WeakSet<Module>} */
this.codeGeneratedModules = new WeakSet();
/** @type {WeakSet<Module>} */
this.buildTimeExecutedModules = new WeakSet();
/** @type {Set<string>} */
this.emittedAssets = new Set();
/** @type {Set<string>} */
this.comparedForEmitAssets = new Set();
/** @type {LazySet<string>} */
this.fileDependencies = new LazySet();
/** @type {LazySet<string>} */
this.contextDependencies = new LazySet();
/** @type {LazySet<string>} */
this.missingDependencies = new LazySet();
/** @type {LazySet<string>} */
this.buildDependencies = new LazySet();
// TODO webpack 6 remove
this.compilationDependencies = {
add: util.deprecate(
/**
* @param {string} item item
* @returns {LazySet<string>} file dependencies
*/
item => this.fileDependencies.add(item),
"Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)",
"DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES"
)
};
this._modulesCache = this.getCache("Compilation/modules");
this._assetsCache = this.getCache("Compilation/assets");
this._codeGenerationCache = this.getCache("Compilation/codeGeneration");
const unsafeCache = options.module.unsafeCache;
this._unsafeCache = Boolean(unsafeCache);
this._unsafeCachePredicate =
typeof unsafeCache === "function" ? unsafeCache : () => true;
}
getStats() {
return new Stats(this);
}
/**
* @param {string | boolean | StatsOptions | undefined} optionsOrPreset stats option value
* @param {CreateStatsOptionsContext=} context context
* @returns {NormalizedStatsOptions} normalized options
*/
createStatsOptions(optionsOrPreset, context = {}) {
if (typeof optionsOrPreset === "boolean") {
optionsOrPreset = {
preset: optionsOrPreset === false ? "none" : "normal"
};
} else if (typeof optionsOrPreset === "string") {
optionsOrPreset = { preset: optionsOrPreset };
}
if (typeof optionsOrPreset === "object" && optionsOrPreset !== null) {
// We use this method of shallow cloning this object to include
// properties in the prototype chain
/** @type {Partial<NormalizedStatsOptions>} */
const options = {};
// eslint-disable-next-line guard-for-in
for (const key in optionsOrPreset) {
options[key] = optionsOrPreset[/** @type {keyof StatsOptions} */ (key)];
}
if (options.preset !== undefined) {
this.hooks.statsPreset.for(options.preset).call(options, context);
}
this.hooks.statsNormalize.call(options, context);
return /** @type {NormalizedStatsOptions} */ (options);
}
/** @type {Partial<NormalizedStatsOptions>} */
const options = {};
this.hooks.statsNormalize.call(options, context);
return /** @type {NormalizedStatsOptions} */ (options);
}
/**
* @param {NormalizedStatsOptions} options options
* @returns {StatsFactory} the stats factory
*/
createStatsFactory(options) {
const statsFactory = new StatsFactory();
this.hooks.statsFactory.call(statsFactory, options);
return statsFactory;
}
/**
* @param {NormalizedStatsOptions} options options
* @returns {StatsPrinter} the stats printer
*/
createStatsPrinter(options) {
const statsPrinter = new StatsPrinter();
this.hooks.statsPrinter.call(statsPrinter, options);
return statsPrinter;
}
/**
* @param {string} name cache name
* @returns {CacheFacade} the cache facade instance
*/
getCache(name) {
return this.compiler.getCache(name);
}
/**
* @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
* @returns {Logger} a logger with that name
*/
getLogger(name) {
if (!name) {
throw new TypeError("Compilation.getLogger(name) called without a name");
}
/** @type {LogEntry[] | undefined} */
let logEntries;
return new Logger(
(type, args) => {
if (typeof name === "function") {
name = name();
if (!name) {
throw new TypeError(
"Compilation.getLogger(name) called with a function not returning a name"
);
}
}
let trace;
switch (type) {
case LogType.warn:
case LogType.error:
case LogType.trace:
trace = ErrorHelpers.cutOffLoaderExecution(
/** @type {string} */ (new Error("Trace").stack)
)
.split("\n")
.slice(3);
break;
}
/** @type {LogEntry} */
const logEntry = {
time: Date.now(),
type,
args,
trace
};
if (this.hooks.log.call(name, logEntry) === undefined) {
if (
logEntry.type === LogType.profileEnd &&
typeof console.profileEnd === "function"
) {
console.profileEnd(
`[${name}] ${/** @type {NonNullable<LogEntry["args"]>} */ (logEntry.args)[0]}`
);
}
if (logEntries === undefined) {
logEntries = this.logging.get(name);
if (logEntries === undefined) {
logEntries = [];
this.logging.set(name, logEntries);
}
}
logEntries.push(logEntry);
if (
logEntry.type === LogType.profile &&
typeof console.profile === "function"
) {
console.profile(
`[${name}] ${
/** @type {NonNullable<LogEntry["args"]>} */
(logEntry.args)[0]
}`
);
}
}
},
childName => {
if (typeof name === "function") {
if (typeof childName === "function") {
return this.getLogger(() => {
if (typeof name === "function") {
name = name();
if (!name) {
throw new TypeError(
"Compilation.getLogger(name) called with a function not returning a name"
);
}
}
if (typeof childName === "function") {
childName = childName();
if (!childName) {
throw new TypeError(
"Logger.getChildLogger(name) called with a function not returning a name"
);
}
}
return `${name}/${childName}`;
});
}
return this.getLogger(() => {
if (typeof name === "function") {
name = name();
if (!name) {
throw new TypeError(
"Compilation.getLogger(name) called with a function not returning a name"
);
}
}
return `${name}/${childName}`;
});
}
if (typeof childName === "function") {
return this.getLogger(() => {
if (typeof childName === "function") {
childName = childName();
if (!childName) {
throw new TypeError(
"Logger.getChildLogger(name) called with a function not returning a name"
);
}
}
return `${name}/${childName}`;
});
}
return this.getLogger(`${name}/${childName}`);
}
);
}
/**
* @param {Module} module module to be added that was created
* @param {ModuleCallback} callback returns the module in the compilation,
* it could be the passed one (if new), or an already existing in the compilation
* @returns {void}
*/
addModule(module, callback) {
this.addModuleQueue.add(module, callback);
}
/**
* @param {Module} module module to be added that was created
* @param {ModuleCallback} callback returns the module in the compilation,
* it could be the passed one (if new), or an already existing in the compilation
* @returns {void}
*/
_addModule(module, callback) {
const identifier = module.identifier();
const alreadyAddedModule = this._modules.get(identifier);
if (alreadyAddedModule) {
return callback(null, alreadyAddedModule);
}
const currentProfile = this.profile
? this.moduleGraph.getProfile(module)
: undefined;
if (currentProfile !== undefined) {
currentProfile.markRestoringStart();
}
this._modulesCache.get(identifier, null, (err, cacheModule) => {
if (err) return callback(new ModuleRestoreError(module, err));
if (currentProfile !== undefined) {
currentProfile.markRestoringEnd();
currentProfile.markIntegrationStart();
}
if (cacheModule) {
cacheModule.updateCacheModule(module);
module = cacheModule;
}
this._modules.set(identifier, module);
this.modules.add(module);
if (this._backCompat)
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
if (currentProfile !== undefined) {
currentProfile.markIntegrationEnd();
}
callback(null, module);
});
}
/**
* Fetches a module from a compilation by its identifier
* @param {Module} module the module provided
* @returns {Module} the module requested
*/
getModule(module) {
const identifier = module.identifier();
return /** @type {Module} */ (this._modules.get(identifier));
}
/**
* Attempts to search for a module by its identifier
* @param {string} identifier identifier (usually path) for module
* @returns {Module|undefined} attempt to search for module and return it, else undefined
*/
findModule(identifier) {
return this._modules.get(identifier);
}
/**
* Schedules a build of the module object
* @param {Module} module module to be built
* @param {ModuleCallback} callback the callback
* @returns {void}
*/
buildModule(module, callback) {
this.buildQueue.add(module, callback);
}
/**
* Builds the module object
* @param {Module} module module to be built
* @param {ModuleCallback} callback the callback
* @returns {void}
*/
_buildModule(module, callback) {
const currentProfile = this.profile
? this.moduleGraph.getProfile(module)
: undefined;
if (currentProfile !== undefined) {
currentProfile.markBuildingStart();
}
module.needBuild(
{
compilation: this,
fileSystemInfo: this.fileSystemInfo,
valueCacheVersions: this.valueCacheVersions
},
(err, needBuild) => {
if (err) return callback(err);
if (!needBuild) {
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
this.hooks.stillValidModule.call(module);
return callback();
}
this.hooks.buildModule.call(module);
this.builtModules.add(module);
module.build(
this.options,
this,
this.resolverFactory.get("normal", module.resolveOptions),
/** @type {InputFileSystem} */ (this.inputFileSystem),
err => {
if (currentProfile !== undefined) {
currentProfile.markBuildingEnd();
}
if (err) {
this.hooks.failedModule.call(module, err);
return callback(err);
}
if (currentProfile !== undefined) {
currentProfile.markStoringStart();
}
this._modulesCache.store(module.identifier(), null, module, err => {
if (currentProfile !== undefined) {
currentProfile.markStoringEnd();
}
if (err) {
this.hooks.failedModule.call(
module,
/** @type {WebpackError} */ (err)
);
return callback(new Module