2013-01-31 01:49:25 +08:00
/ *
2017-01-24 03:31:53 +08:00
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
2018-07-30 23:08:51 +08:00
* /
2017-01-06 01:00:36 +08:00
"use strict" ;
2018-02-11 12:27:09 +08:00
const asyncLib = require ( "neo-async" ) ;
2018-03-22 19:05:58 +08:00
const {
2018-11-06 02:03:12 +08:00
HookMap ,
2018-03-22 19:05:58 +08:00
SyncHook ,
SyncBailHook ,
SyncWaterfallHook ,
2019-12-11 05:58:26 +08:00
AsyncSeriesHook ,
2021-04-14 20:37:11 +08:00
AsyncSeriesBailHook ,
AsyncParallelHook
2018-03-22 19:05:58 +08:00
} = require ( "tapable" ) ;
2018-11-13 21:45:26 +08:00
const util = require ( "util" ) ;
2018-07-30 23:08:51 +08:00
const { CachedSource } = require ( "webpack-sources" ) ;
2020-07-28 00:09:48 +08:00
const { MultiItemCache } = require ( "./CacheFacade" ) ;
2017-01-06 01:00:36 +08:00
const Chunk = require ( "./Chunk" ) ;
2018-08-14 17:18:22 +08:00
const ChunkGraph = require ( "./ChunkGraph" ) ;
2018-07-30 23:08:51 +08:00
const ChunkGroup = require ( "./ChunkGroup" ) ;
2017-01-06 01:00:36 +08:00
const ChunkRenderError = require ( "./ChunkRenderError" ) ;
2018-07-30 23:08:51 +08:00
const ChunkTemplate = require ( "./ChunkTemplate" ) ;
2019-10-09 04:29:46 +08:00
const CodeGenerationError = require ( "./CodeGenerationError" ) ;
2020-07-28 00:09:48 +08:00
const CodeGenerationResults = require ( "./CodeGenerationResults" ) ;
2021-09-27 22:43:34 +08:00
const Dependency = require ( "./Dependency" ) ;
2018-07-30 23:08:51 +08:00
const DependencyTemplates = require ( "./DependencyTemplates" ) ;
const Entrypoint = require ( "./Entrypoint" ) ;
2019-07-24 16:51:04 +08:00
const ErrorHelpers = require ( "./ErrorHelpers" ) ;
2018-09-27 13:22:19 +08:00
const FileSystemInfo = require ( "./FileSystemInfo" ) ;
2020-02-07 17:05:51 +08:00
const {
connectChunkGroupAndChunk ,
connectChunkGroupParentAndChild
} = require ( "./GraphHelpers" ) ;
2021-04-09 21:50:25 +08:00
const {
makeWebpackError ,
tryRunOrWebpackError
} = require ( "./HookWebpackError" ) ;
2018-07-30 23:08:51 +08:00
const MainTemplate = require ( "./MainTemplate" ) ;
2019-09-26 21:51:40 +08:00
const Module = require ( "./Module" ) ;
2018-07-30 23:08:51 +08:00
const ModuleDependencyError = require ( "./ModuleDependencyError" ) ;
const ModuleDependencyWarning = require ( "./ModuleDependencyWarning" ) ;
2018-07-17 22:41:07 +08:00
const ModuleGraph = require ( "./ModuleGraph" ) ;
2022-02-22 19:23:24 +08:00
const ModuleHashingError = require ( "./ModuleHashingError" ) ;
2018-07-30 23:08:51 +08:00
const ModuleNotFoundError = require ( "./ModuleNotFoundError" ) ;
2018-08-22 20:54:28 +08:00
const ModuleProfile = require ( "./ModuleProfile" ) ;
2018-10-18 04:54:07 +08:00
const ModuleRestoreError = require ( "./ModuleRestoreError" ) ;
2019-12-16 21:50:10 +08:00
const ModuleStoreError = require ( "./ModuleStoreError" ) ;
2018-07-30 23:08:51 +08:00
const ModuleTemplate = require ( "./ModuleTemplate" ) ;
2023-05-05 07:19:11 +08:00
const { WEBPACK _MODULE _TYPE _RUNTIME } = require ( "./ModuleTypeConstants" ) ;
2018-11-17 01:18:44 +08:00
const RuntimeGlobals = require ( "./RuntimeGlobals" ) ;
2018-07-30 23:08:51 +08:00
const RuntimeTemplate = require ( "./RuntimeTemplate" ) ;
const Stats = require ( "./Stats" ) ;
2018-12-03 00:00:16 +08:00
const WebpackError = require ( "./WebpackError" ) ;
2019-07-25 14:07:55 +08:00
const buildChunkGraph = require ( "./buildChunkGraph" ) ;
2019-12-20 19:45:55 +08:00
const BuildCycleError = require ( "./errors/BuildCycleError" ) ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
const { Logger , LogType } = require ( "./logging/Logger" ) ;
2018-12-19 01:29:12 +08:00
const StatsFactory = require ( "./stats/StatsFactory" ) ;
const StatsPrinter = require ( "./stats/StatsPrinter" ) ;
2020-10-06 23:55:22 +08:00
const { equals : arrayEquals } = require ( "./util/ArrayHelpers" ) ;
2018-09-12 00:47:55 +08:00
const AsyncQueue = require ( "./util/AsyncQueue" ) ;
2019-08-07 15:54:43 +08:00
const LazySet = require ( "./util/LazySet" ) ;
2023-04-26 04:45:43 +08:00
const { getOrInsert } = require ( "./util/MapHelpers" ) ;
2021-09-27 22:41:26 +08:00
const WeakTupleMap = require ( "./util/WeakTupleMap" ) ;
2020-08-01 04:03:14 +08:00
const { cachedCleverMerge } = require ( "./util/cleverMerge" ) ;
2018-09-07 20:11:48 +08:00
const {
2018-12-20 15:51:54 +08:00
compareLocations ,
2018-09-07 20:11:48 +08:00
concatComparators ,
compareSelect ,
2018-10-21 17:11:21 +08:00
compareIds ,
2019-10-09 15:26:33 +08:00
compareStringsNumeric ,
2019-10-16 22:38:04 +08:00
compareModulesByIdentifier
2018-09-07 20:11:48 +08:00
} = require ( "./util/comparators" ) ;
2018-07-30 23:08:51 +08:00
const createHash = require ( "./util/createHash" ) ;
2020-05-12 18:16:51 +08:00
const {
arrayToSetDeprecation ,
soonFrozenObjectDeprecation ,
2020-07-14 18:02:32 +08:00
createFakeHook
2020-05-12 18:16:51 +08:00
} = require ( "./util/deprecation" ) ;
2021-04-09 21:50:25 +08:00
const processAsyncTree = require ( "./util/processAsyncTree" ) ;
2021-09-29 06:06:44 +08:00
const { getRuntimeKey } = require ( "./util/runtime" ) ;
2020-12-09 23:10:32 +08:00
const { isSourceEqual } = require ( "./util/source" ) ;
2013-01-31 01:49:25 +08:00
2020-05-12 18:16:51 +08:00
/** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
2018-05-04 00:57:02 +08:00
/** @typedef {import("webpack-sources").Source} Source */
2020-02-26 20:08:05 +08:00
/** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */
2020-02-20 03:25:49 +08:00
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
2020-12-18 01:51:55 +08:00
/** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */
2024-03-14 23:15:13 +08:00
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
2020-11-09 21:54:40 +08:00
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
2018-05-12 00:12:30 +08:00
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
2020-07-15 17:14:28 +08:00
/** @typedef {import("./Cache")} Cache */
/** @typedef {import("./CacheFacade")} CacheFacade */
2019-06-14 17:44:54 +08:00
/** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */
2018-07-30 23:08:51 +08:00
/** @typedef {import("./Compiler")} Compiler */
2021-09-28 01:03:55 +08:00
/** @typedef {import("./Compiler").CompilationParams} CompilationParams */
2018-07-30 23:08:51 +08:00
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
2018-06-25 16:43:59 +08:00
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
2020-05-28 02:34:55 +08:00
/** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
2018-07-23 23:33:29 +08:00
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
2020-09-08 00:02:14 +08:00
/** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
2024-03-18 01:15:44 +08:00
/** @typedef {import("./Module").BuildInfo} BuildInfo */
/** @typedef {import("./NormalModule").NormalModuleCompilationHooks} NormalModuleCompilationHooks */
2019-10-09 04:29:46 +08:00
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
2019-01-05 02:17:37 +08:00
/** @typedef {import("./ModuleFactory")} ModuleFactory */
2024-02-22 22:20:17 +08:00
/** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */
2020-12-22 21:51:09 +08:00
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
2021-09-28 01:03:55 +08:00
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
2020-12-18 01:51:55 +08:00
/** @typedef {import("./RequestShortener")} RequestShortener */
2018-11-06 02:03:12 +08:00
/** @typedef {import("./RuntimeModule")} RuntimeModule */
2018-09-27 13:22:19 +08:00
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
2019-10-02 14:54:21 +08:00
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */
2021-02-22 20:18:27 +08:00
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsError} StatsError */
/** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsModule} StatsModule */
2019-07-17 22:02:33 +08:00
/** @typedef {import("./util/Hash")} Hash */
2024-02-22 22:20:17 +08:00
/ * *
* @ template T
* @ typedef { import ( "./util/deprecation" ) . FakeHook < T > } FakeHook < T >
* /
2020-07-28 00:09:48 +08:00
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
2024-02-22 22:20:17 +08:00
/** @typedef {WeakMap<Dependency, Module>} References */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
2018-12-10 18:34:59 +08:00
/ * *
* @ callback Callback
2021-12-24 20:27:31 +08:00
* @ param { ( WebpackError | null ) = } err
2018-12-10 18:34:59 +08:00
* @ returns { void }
* /
/ * *
* @ callback ModuleCallback
2021-12-24 20:27:31 +08:00
* @ param { ( WebpackError | null ) = } err
2018-12-10 18:34:59 +08:00
* @ param { Module = } result
* @ returns { void }
* /
2021-09-28 01:03:55 +08:00
/ * *
* @ callback ModuleFactoryResultCallback
2021-12-24 20:27:31 +08:00
* @ param { ( WebpackError | null ) = } err
2021-09-28 01:03:55 +08:00
* @ param { ModuleFactoryResult = } result
* @ returns { void }
* /
/ * *
* @ callback ModuleOrFactoryResultCallback
2021-12-24 20:27:31 +08:00
* @ param { ( WebpackError | null ) = } err
2021-09-28 01:03:55 +08:00
* @ param { Module | ModuleFactoryResult = } result
* @ returns { void }
* /
2021-04-09 21:50:25 +08:00
/ * *
2021-04-12 15:17:43 +08:00
* @ callback ExecuteModuleCallback
2021-12-24 20:27:31 +08:00
* @ param { ( WebpackError | null ) = } err
2021-04-12 15:17:43 +08:00
* @ param { ExecuteModuleResult = } result
2021-04-09 21:50:25 +08:00
* @ returns { void }
* /
2018-12-10 18:34:59 +08:00
/ * *
* @ callback DepBlockVarDependenciesCallback
* @ param { Dependency } dependency
* @ returns { any }
* /
2018-05-04 00:57:02 +08:00
/** @typedef {new (...args: any[]) => Dependency} DepConstructor */
2018-12-10 18:34:59 +08:00
/** @typedef {Record<string, Source>} CompilationAssets */
2018-05-04 00:57:02 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } AvailableModulesChunkGroupMapping
2018-05-04 00:57:02 +08:00
* @ property { ChunkGroup } chunkGroup
* @ property { Set < Module > } availableModules
2018-10-05 07:10:12 +08:00
* @ property { boolean } needCopy
2018-05-04 00:57:02 +08:00
* /
2018-05-07 05:01:47 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } DependenciesBlockLike
2018-05-07 05:01:47 +08:00
* @ property { Dependency [ ] } dependencies
* @ property { AsyncDependenciesBlock [ ] } blocks
* /
2018-08-23 01:23:48 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ChunkPathData
2018-08-23 01:23:48 +08:00
* @ 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
* /
2019-10-02 14:54:21 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ChunkHashContext
2022-02-11 22:59:35 +08:00
* @ property { CodeGenerationResults } codeGenerationResults results of code generation
2019-10-02 14:54:21 +08:00
* @ property { RuntimeTemplate } runtimeTemplate the runtime template
* @ property { ModuleGraph } moduleGraph the module graph
* @ property { ChunkGraph } chunkGraph the chunk graph
* /
2021-04-09 21:50:25 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } RuntimeRequirementsContext
2021-04-09 21:50:25 +08:00
* @ property { ChunkGraph } chunkGraph the chunk graph
* @ property { CodeGenerationResults } codeGenerationResults the code generation results
* /
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ExecuteModuleOptions
2021-04-09 21:50:25 +08:00
* @ property { EntryOptions = } entryOptions
* /
2021-04-10 02:45:59 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ExecuteModuleResult
2021-04-10 02:45:59 +08:00
* @ property { any } exports
2021-04-14 20:37:11 +08:00
* @ property { boolean } cacheable
2021-04-10 02:45:59 +08:00
* @ property { Map < string , { source : Source , info : AssetInfo } > } assets
* @ property { LazySet < string > } fileDependencies
* @ property { LazySet < string > } contextDependencies
* @ property { LazySet < string > } missingDependencies
* @ property { LazySet < string > } buildDependencies
* /
2021-04-09 21:50:25 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ExecuteModuleArgument
2021-04-09 21:50:25 +08:00
* @ property { Module } module
2021-04-14 20:37:11 +08:00
* @ property { { id : string , exports : any , loaded : boolean } = } moduleObject
* @ property { any } preparedInfo
2021-04-09 21:50:25 +08:00
* @ property { CodeGenerationResult } codeGenerationResult
* /
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ExecuteModuleContext
2021-04-10 02:45:59 +08:00
* @ property { Map < string , { source : Source , info : AssetInfo } > } assets
2021-04-09 21:50:25 +08:00
* @ property { Chunk } chunk
* @ property { ChunkGraph } chunkGraph
2021-04-14 20:37:11 +08:00
* @ property { function ( string ) : any = } _ _webpack _require _ _
2021-04-09 21:50:25 +08:00
* /
2020-02-05 04:35:01 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } EntryData
2020-05-23 22:08:51 +08:00
* @ property { Dependency [ ] } dependencies dependencies of the entrypoint that should be evaluated at startup
2020-06-05 12:42:33 +08:00
* @ property { Dependency [ ] } includeDependencies dependencies of the entrypoint that should be included but not evaluated
2020-02-05 04:35:01 +08:00
* @ property { EntryOptions } options options of the entrypoint
* /
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } LogEntry
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
* @ property { string } type
* @ property { any [ ] } args
2019-07-23 15:28:06 +08:00
* @ property { number } time
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
* @ property { string [ ] = } trace
* /
2019-09-11 17:13:46 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } KnownAssetInfo
2019-09-11 17:13:46 +08:00
* @ property { boolean = } immutable true , if the asset can be long term cached forever ( contains a hash )
2020-11-11 14:15:35 +08:00
* @ property { boolean = } minimized whether the asset is minimized
2020-08-19 03:14:43 +08:00
* @ 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
2020-10-22 15:35:14 +08:00
* @ property { string = } sourceFilename when asset was created from a source file ( potentially transformed ) , the original filename relative to compilation context
2019-09-11 17:13:46 +08:00
* @ 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 )
2020-10-22 15:35:14 +08:00
* @ property { boolean = } javascriptModule true , when asset is javascript and an ESM
2020-08-01 04:03:14 +08:00
* @ property { Record < string , string | string [ ] >= } related object of pointers to other assets , keyed by type of relation ( only points from parent to child )
2019-09-11 17:13:46 +08:00
* /
2020-12-17 17:07:29 +08:00
/** @typedef {KnownAssetInfo & Record<string, any>} AssetInfo */
2019-09-11 17:13:46 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } Asset
2019-09-11 17:13:46 +08:00
* @ property { string } name the filename of the asset
* @ property { Source } source source of the asset
* @ property { AssetInfo } info info about the asset
* /
2018-08-23 01:23:48 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } ModulePathData
2018-08-23 01:23:48 +08:00
* @ property { string | number } id
* @ property { string } hash
* @ property { function ( number ) : string = } hashWithLength
* /
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } PathData
2018-08-23 01:23:48 +08:00
* @ property { ChunkGraph = } chunkGraph
* @ property { string = } hash
* @ property { function ( number ) : string = } hashWithLength
* @ property { ( Chunk | ChunkPathData ) = } chunk
* @ property { ( Module | ModulePathData ) = } module
2020-07-28 00:09:48 +08:00
* @ property { RuntimeSpec = } runtime
2018-08-23 01:23:48 +08:00
* @ property { string = } filename
* @ property { string = } basename
* @ property { string = } query
* @ property { string = } contentHashType
* @ property { string = } contentHash
* @ property { function ( number ) : string = } contentHashWithLength
* @ property { boolean = } noChunkHash
2019-07-17 22:02:33 +08:00
* @ property { string = } url
2018-08-23 01:23:48 +08:00
* /
2020-12-18 01:51:55 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } KnownNormalizedStatsOptions
2020-12-18 01:51:55 +08:00
* @ 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
2021-02-22 20:18:27 +08:00
* @ 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
2020-12-18 01:51:55 +08:00
* @ property { boolean } cachedModules
* @ property { boolean } orphanModules
* @ property { boolean } dependentModules
* @ property { boolean } runtimeModules
* @ property { boolean } groupModulesByCacheStatus
2020-12-22 21:51:09 +08:00
* @ property { boolean } groupModulesByLayer
2020-12-18 01:51:55 +08:00
* @ 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
2021-02-22 20:18:27 +08:00
* @ property { ( ( value : string ) => boolean ) [ ] } loggingDebug
2020-12-18 01:51:55 +08:00
* @ property { boolean } loggingTrace
* @ property { any } _env
* /
2021-02-22 18:38:11 +08:00
/** @typedef {KnownNormalizedStatsOptions & Omit<StatsOptions, keyof KnownNormalizedStatsOptions> & Record<string, any>} NormalizedStatsOptions */
2020-12-18 01:51:55 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } KnownCreateStatsOptionsContext
2020-12-18 01:51:55 +08:00
* @ property { boolean = } forToString
* /
/** @typedef {KnownCreateStatsOptionsContext & Record<string, any>} CreateStatsOptionsContext */
2024-03-14 02:23:33 +08:00
/** @typedef {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} CodeGenerationJobs */
2024-03-14 23:15:13 +08:00
/** @typedef {{javascript: ModuleTemplate}} ModuleTemplates */
/** @typedef {Set<Module>} NotCodeGeneratedModules */
2020-08-01 04:03:14 +08:00
/** @type {AssetInfo} */
const EMPTY _ASSET _INFO = Object . freeze ( { } ) ;
2020-05-28 06:23:54 +08:00
const esmDependencyCategory = "esm" ;
2024-03-14 23:15:13 +08:00
2018-11-14 20:14:05 +08:00
// TODO webpack 6: remove
2019-11-14 22:01:25 +08:00
const deprecatedNormalModuleLoaderHook = util . deprecate (
2024-03-18 01:15:44 +08:00
/ * *
* @ param { Compilation } compilation compilation
* @ returns { NormalModuleCompilationHooks [ "loader" ] } hooks
* /
2019-11-14 22:01:25 +08:00
compilation => {
return require ( "./NormalModule" ) . getCompilationHooks ( compilation ) . loader ;
} ,
"Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader" ,
"DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK"
) ;
2018-11-13 21:45:26 +08:00
2021-06-17 16:11:24 +08:00
// TODO webpack 6: remove
2024-03-14 23:15:13 +08:00
/ * *
* @ param { ModuleTemplates | undefined } moduleTemplates module templates
* /
2021-06-17 16:11:24 +08:00
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 ;
} ;
2024-03-14 23:15:13 +08:00
const byId = compareSelect ( c => c . id , compareIds ) ;
2015-08-18 19:35:57 +08:00
2018-10-21 17:11:21 +08:00
const byNameOrHash = concatComparators (
2024-03-14 23:15:13 +08:00
compareSelect ( c => c . name , compareIds ) ,
compareSelect ( c => c . fullHash , compareIds )
2018-10-21 17:11:21 +08:00
) ;
2018-04-03 23:23:41 +08:00
2019-10-28 21:02:37 +08:00
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 ) ;
2021-10-12 16:56:14 +08:00
/** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */
2021-09-28 01:03:55 +08:00
const unsafeCacheDependencies = new WeakMap ( ) ;
2021-10-12 16:56:14 +08:00
/** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, object>} */
2021-09-28 01:03:55 +08:00
const unsafeCacheData = new WeakMap ( ) ;
2018-06-26 14:27:44 +08:00
class Compilation {
2018-05-04 00:57:02 +08:00
/ * *
* Creates an instance of Compilation .
* @ param { Compiler } compiler the compiler which created the compilation
2021-09-28 01:03:55 +08:00
* @ param { CompilationParams } params the compilation parameters
2018-05-04 00:57:02 +08:00
* /
2021-09-28 01:03:55 +08:00
constructor ( compiler , params ) {
2021-11-05 16:53:32 +08:00
this . _backCompat = compiler . _backCompat ;
2018-11-13 21:45:26 +08:00
const getNormalModuleLoader = ( ) => deprecatedNormalModuleLoaderHook ( this ) ;
2020-11-09 18:58:18 +08:00
/** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
/** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
2020-05-12 18:16:51 +08:00
const processAssetsHook = new AsyncSeriesHook ( [ "assets" ] ) ;
2020-11-09 18:58:18 +08:00
let savedAssets = new Set ( ) ;
2024-03-18 01:15:44 +08:00
/ * *
* @ param { CompilationAssets } assets assets
* @ returns { CompilationAssets } new assets
* /
2020-11-09 18:58:18 +08:00
const popNewAssets = assets => {
let newAssets = undefined ;
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 : ( ) => {
2020-12-11 00:39:42 +08:00
savedAssets = new Set ( Object . keys ( this . assets ) ) ;
2020-11-09 18:58:18 +08:00
} ,
register : tap => {
const { type , name } = tap ;
const { fn , additionalAssets , ... remainingTap } = tap ;
const additionalAssetsFn =
additionalAssets === true ? fn : additionalAssets ;
2021-04-08 02:48:07 +08:00
const processedAssets = additionalAssetsFn ? new WeakSet ( ) : undefined ;
2020-11-09 18:58:18 +08:00
switch ( type ) {
case "sync" :
if ( additionalAssetsFn ) {
this . hooks . processAdditionalAssets . tap ( name , assets => {
2021-04-08 02:48:07 +08:00
if ( processedAssets . has ( this . assets ) )
additionalAssetsFn ( assets ) ;
2020-11-09 18:58:18 +08:00
} ) ;
}
return {
... remainingTap ,
type : "async" ,
fn : ( assets , callback ) => {
try {
fn ( assets ) ;
} catch ( e ) {
return callback ( e ) ;
}
2021-04-08 02:48:07 +08:00
if ( processedAssets !== undefined )
processedAssets . add ( this . assets ) ;
2020-11-09 18:58:18 +08:00
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 ) => {
2021-04-08 02:48:07 +08:00
if ( processedAssets . has ( this . assets ) )
2020-11-09 18:58:18 +08:00
return additionalAssetsFn ( assets , callback ) ;
callback ( ) ;
}
) ;
}
return {
... remainingTap ,
fn : ( assets , callback ) => {
fn ( assets , err => {
if ( err ) return callback ( err ) ;
2021-04-08 02:48:07 +08:00
if ( processedAssets !== undefined )
processedAssets . add ( this . assets ) ;
2020-11-09 18:58:18 +08:00
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 => {
2021-04-08 02:48:07 +08:00
if ( processedAssets . has ( this . assets ) )
2020-11-09 18:58:18 +08:00
return additionalAssetsFn ( assets ) ;
return Promise . resolve ( ) ;
} ) ;
}
return {
... remainingTap ,
fn : assets => {
const p = fn ( assets ) ;
if ( ! p || ! p . then ) return p ;
return p . then ( ( ) => {
2021-04-08 02:48:07 +08:00
if ( processedAssets !== undefined )
processedAssets . add ( this . assets ) ;
2020-11-09 18:58:18 +08:00
const newAssets = popNewAssets ( assets ) ;
if ( newAssets !== undefined ) {
return this . hooks . processAdditionalAssets . promise (
newAssets
) ;
}
} ) ;
}
} ;
}
}
} ) ;
2020-05-12 18:16:51 +08:00
/** @type {SyncHook<[CompilationAssets]>} */
const afterProcessAssetsHook = new SyncHook ( [ "assets" ] ) ;
2020-11-09 18:58:18 +08:00
2020-05-12 18:16:51 +08:00
/ * *
* @ 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 )
2020-07-14 18:02:32 +08:00
* @ returns { FakeHook < Pick < AsyncSeriesHook < T > , "tap" | "tapAsync" | "tapPromise" | "name" >> } fake hook which redirects
2020-05-12 18:16:51 +08:00
* /
const createProcessAssetsHook = ( name , stage , getArgs , code ) => {
2021-11-05 16:53:32 +08:00
if ( ! this . _backCompat && code ) return undefined ;
2021-05-11 15:31:46 +08:00
const errorMessage =
reason => ` Can't automatically convert plugin using Compilation.hooks. ${ name } to Compilation.hooks.processAssets because ${ reason } .
2020-05-12 18:16:51 +08:00
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 : stage } ;
} ;
2020-07-14 18:02:32 +08:00
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 ( ) )
) ;
}
2020-05-12 18:16:51 +08:00
} ,
2021-02-23 19:23:50 +08:00
` ${ name } is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option) ` ,
2020-07-14 18:02:32 +08:00
code
2020-05-12 18:16:51 +08:00
) ;
} ;
2018-07-30 20:25:40 +08:00
this . hooks = Object . freeze ( {
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Module]>} */
2017-11-27 22:27:30 +08:00
buildModule : new SyncHook ( [ "module" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Module]>} */
2017-12-07 00:39:42 +08:00
rebuildModule : new SyncHook ( [ "module" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Module, WebpackError]>} */
2017-11-27 22:27:30 +08:00
failedModule : new SyncHook ( [ "module" , "error" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Module]>} */
2017-11-27 22:27:30 +08:00
succeedModule : new SyncHook ( [ "module" ] ) ,
2019-07-25 21:47:31 +08:00
/** @type {SyncHook<[Module]>} */
stillValidModule : new SyncHook ( [ "module" ] ) ,
2017-11-27 22:27:30 +08:00
2020-02-05 04:21:42 +08:00
/** @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" ] ) ,
2018-10-29 20:49:31 +08:00
2020-07-28 00:09:48 +08:00
/** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency, RuntimeSpec]>} */
2019-10-30 05:28:42 +08:00
dependencyReferencedExports : new SyncWaterfallHook ( [
"referencedExports" ,
2020-07-28 00:09:48 +08:00
"dependency" ,
"runtime"
2018-06-08 16:34:38 +08:00
] ) ,
2021-04-12 15:17:43 +08:00
/** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
executeModule : new SyncHook ( [ "options" , "context" ] ) ,
2021-04-14 20:37:11 +08:00
/** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
prepareModuleExecution : new AsyncParallelHook ( [ "options" , "context" ] ) ,
2021-04-09 21:50:25 +08:00
2018-12-09 19:54:17 +08:00
/** @type {AsyncSeriesHook<[Iterable<Module>]>} */
2018-12-30 21:54:47 +08:00
finishModules : new AsyncSeriesHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {AsyncSeriesHook<[Module]>} */
2018-12-30 21:54:47 +08:00
finishRebuildingModule : new AsyncSeriesHook ( [ "module" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
unseal : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
seal : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2018-07-02 22:18:49 +08:00
beforeChunks : new SyncHook ( [ ] ) ,
2023-05-17 06:34:18 +08:00
/ * *
* 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 > ] > }
* /
2018-07-02 22:18:49 +08:00
afterChunks : new SyncHook ( [ "chunks" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncBailHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
optimizeDependencies : new SyncBailHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeDependencies : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
optimize : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncBailHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
optimizeModules : new SyncBailHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeModules : new SyncHook ( [ "modules" ] ) ,
2024-03-14 23:15:13 +08:00
/** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]], boolean | void>} */
2018-01-20 00:06:59 +08:00
optimizeChunks : new SyncBailHook ( [ "chunks" , "chunkGroups" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */
2018-01-20 00:06:59 +08:00
afterOptimizeChunks : new SyncHook ( [ "chunks" , "chunkGroups" ] ) ,
2017-11-27 22:27:30 +08:00
2018-12-09 19:54:17 +08:00
/** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
optimizeTree : new AsyncSeriesHook ( [ "chunks" , "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeTree : new SyncHook ( [ "chunks" , "modules" ] ) ,
2024-03-14 23:15:13 +08:00
/** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>], void>} */
2019-12-11 05:58:26 +08:00
optimizeChunkModules : new AsyncSeriesBailHook ( [ "chunks" , "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeChunkModules : new SyncHook ( [ "chunks" , "modules" ] ) ,
2023-05-25 06:41:32 +08:00
/** @type {SyncBailHook<[], boolean | undefined>} */
2017-11-27 22:27:30 +08:00
shouldRecord : new SyncBailHook ( [ ] ) ,
2021-04-09 21:50:25 +08:00
/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
2018-11-06 02:03:12 +08:00
additionalChunkRuntimeRequirements : new SyncHook ( [
"chunk" ,
2021-04-09 21:50:25 +08:00
"runtimeRequirements" ,
"context"
2018-11-06 02:03:12 +08:00
] ) ,
2024-03-14 02:23:33 +08:00
/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */
2018-11-06 02:03:12 +08:00
runtimeRequirementInChunk : new HookMap (
2021-04-09 21:50:25 +08:00
( ) => new SyncBailHook ( [ "chunk" , "runtimeRequirements" , "context" ] )
2018-11-06 02:03:12 +08:00
) ,
2021-04-09 21:50:25 +08:00
/** @type {SyncHook<[Module, Set<string>, RuntimeRequirementsContext]>} */
2018-11-17 01:18:44 +08:00
additionalModuleRuntimeRequirements : new SyncHook ( [
"module" ,
2021-04-09 21:50:25 +08:00
"runtimeRequirements" ,
"context"
2018-11-17 01:18:44 +08:00
] ) ,
2021-04-09 21:50:25 +08:00
/** @type {HookMap<SyncBailHook<[Module, Set<string>, RuntimeRequirementsContext]>>} */
2018-11-17 01:18:44 +08:00
runtimeRequirementInModule : new HookMap (
2021-04-09 21:50:25 +08:00
( ) => new SyncBailHook ( [ "module" , "runtimeRequirements" , "context" ] )
2018-11-17 01:18:44 +08:00
) ,
2021-04-09 21:50:25 +08:00
/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
2018-11-06 02:03:12 +08:00
additionalTreeRuntimeRequirements : new SyncHook ( [
"chunk" ,
2021-04-09 21:50:25 +08:00
"runtimeRequirements" ,
"context"
2018-11-06 02:03:12 +08:00
] ) ,
2021-04-09 21:50:25 +08:00
/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext]>>} */
2018-11-06 02:03:12 +08:00
runtimeRequirementInTree : new HookMap (
2021-04-09 21:50:25 +08:00
( ) => new SyncBailHook ( [ "chunk" , "runtimeRequirements" , "context" ] )
2018-11-06 02:03:12 +08:00
) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[RuntimeModule, Chunk]>} */
2018-11-15 00:31:32 +08:00
runtimeModule : new SyncHook ( [ "module" , "chunk" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>, any]>} */
2017-11-27 22:27:30 +08:00
reviveModules : new SyncHook ( [ "modules" , "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
beforeModuleIds : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
moduleIds : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
optimizeModuleIds : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeModuleIds : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>, any]>} */
2017-11-27 22:27:30 +08:00
reviveChunks : new SyncHook ( [ "chunks" , "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>]>} */
2017-11-27 22:27:30 +08:00
beforeChunkIds : new SyncHook ( [ "chunks" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>]>} */
2018-09-05 20:22:10 +08:00
chunkIds : new SyncHook ( [ "chunks" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>]>} */
2017-11-27 22:27:30 +08:00
optimizeChunkIds : new SyncHook ( [ "chunks" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>]>} */
2017-11-27 22:27:30 +08:00
afterOptimizeChunkIds : new SyncHook ( [ "chunks" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>, any]>} */
2017-11-27 22:27:30 +08:00
recordModules : new SyncHook ( [ "modules" , "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Chunk>, any]>} */
2017-11-27 22:27:30 +08:00
recordChunks : new SyncHook ( [ "chunks" , "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Iterable<Module>]>} */
2019-01-28 17:40:32 +08:00
optimizeCodeGeneration : new SyncHook ( [ "modules" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2018-11-15 00:31:32 +08:00
beforeModuleHash : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2018-11-15 00:31:32 +08:00
afterModuleHash : new SyncHook ( [ ] ) ,
2019-10-09 04:29:46 +08:00
/** @type {SyncHook<[]>} */
beforeCodeGeneration : new SyncHook ( [ ] ) ,
/** @type {SyncHook<[]>} */
afterCodeGeneration : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2018-11-15 00:31:32 +08:00
beforeRuntimeRequirements : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2018-11-15 00:31:32 +08:00
afterRuntimeRequirements : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
beforeHash : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Chunk]>} */
2018-03-23 02:52:11 +08:00
contentHash : new SyncHook ( [ "chunk" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
afterHash : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[any]>} */
2017-11-27 22:27:30 +08:00
recordHash : new SyncHook ( [ "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Compilation, any]>} */
2017-11-27 22:27:30 +08:00
record : new SyncHook ( [ "compilation" , "records" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
beforeModuleAssets : new SyncHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncBailHook<[], boolean>} */
2017-11-27 22:27:30 +08:00
shouldGenerateChunkAssets : new SyncBailHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[]>} */
2017-11-27 22:27:30 +08:00
beforeChunkAssets : new SyncHook ( [ ] ) ,
2020-05-12 18:16:51 +08:00
// TODO webpack 6 remove
/** @deprecated */
additionalChunkAssets : createProcessAssetsHook (
"additionalChunkAssets" ,
Compilation . PROCESS _ASSETS _STAGE _ADDITIONAL ,
( ) => [ this . chunks ] ,
"DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS"
) ,
2017-11-27 22:27:30 +08:00
2020-05-12 18:16:51 +08:00
// 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 ,
2017-11-27 22:27:30 +08:00
2020-05-12 18:16:51 +08:00
processAssets : processAssetsHook ,
afterProcessAssets : afterProcessAssetsHook ,
2020-11-09 18:58:18 +08:00
/** @type {AsyncSeriesHook<[CompilationAssets]>} */
processAdditionalAssets : new AsyncSeriesHook ( [ "assets" ] ) ,
2019-10-31 03:47:17 +08:00
2024-02-22 22:20:17 +08:00
/** @type {SyncBailHook<[], boolean | undefined>} */
2017-11-27 22:27:30 +08:00
needAdditionalSeal : new SyncBailHook ( [ ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {AsyncSeriesHook<[]>} */
2017-11-27 22:27:30 +08:00
afterSeal : new AsyncSeriesHook ( [ ] ) ,
2019-10-02 14:54:21 +08:00
/** @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" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Module, string]>} */
2017-11-27 22:27:30 +08:00
moduleAsset : new SyncHook ( [ "module" , "filename" ] ) ,
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Chunk, string]>} */
2017-11-27 22:27:30 +08:00
chunkAsset : new SyncHook ( [ "chunk" , "filename" ] ) ,
2024-03-21 20:09:45 +08:00
/** @type {SyncWaterfallHook<[string, object, AssetInfo | undefined]>} */
2019-10-02 14:54:21 +08:00
assetPath : new SyncWaterfallHook ( [ "path" , "options" , "assetInfo" ] ) ,
2017-11-27 22:27:30 +08:00
2018-12-09 19:54:17 +08:00
/** @type {SyncBailHook<[], boolean>} */
2017-11-27 22:27:30 +08:00
needAdditionalPass : new SyncBailHook ( [ ] ) ,
2018-05-04 00:57:02 +08:00
2018-12-09 19:54:17 +08:00
/** @type {SyncHook<[Compiler, string, number]>} */
2018-02-25 09:00:20 +08:00
childCompiler : new SyncHook ( [
"childCompiler" ,
"compilerName" ,
"compilerIndex"
2018-11-13 21:45:26 +08:00
] ) ,
2019-07-24 16:51:04 +08:00
/** @type {SyncBailHook<[string, LogEntry], true>} */
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
log : new SyncBailHook ( [ "origin" , "logEntry" ] ) ,
2020-09-21 03:24:15 +08:00
/** @type {SyncWaterfallHook<[WebpackError[]]>} */
processWarnings : new SyncWaterfallHook ( [ "warnings" ] ) ,
/** @type {SyncWaterfallHook<[WebpackError[]]>} */
processErrors : new SyncWaterfallHook ( [ "errors" ] ) ,
2020-12-18 01:51:55 +08:00
/** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */
2018-12-19 01:29:12 +08:00
statsPreset : new HookMap ( ( ) => new SyncHook ( [ "options" , "context" ] ) ) ,
2020-12-18 01:51:55 +08:00
/** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */
2018-12-19 01:29:12 +08:00
statsNormalize : new SyncHook ( [ "options" , "context" ] ) ,
2020-12-18 01:51:55 +08:00
/** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */
2018-12-19 01:29:12 +08:00
statsFactory : new SyncHook ( [ "statsFactory" , "options" ] ) ,
2020-12-18 01:51:55 +08:00
/** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */
2018-12-19 01:29:12 +08:00
statsPrinter : new SyncHook ( [ "statsPrinter" , "options" ] ) ,
2018-11-13 21:45:26 +08:00
get normalModuleLoader ( ) {
return getNormalModuleLoader ( ) ;
}
2018-07-30 20:25:40 +08:00
} ) ;
2018-05-04 00:57:02 +08:00
/** @type {string=} */
2018-03-30 08:33:19 +08:00
this . name = undefined ;
2024-02-22 22:20:17 +08:00
/** @type {number | undefined} */
2020-09-04 04:01:25 +08:00
this . startTime = undefined ;
2024-02-22 22:20:17 +08:00
/** @type {number | undefined} */
2020-09-04 04:01:25 +08:00
this . endTime = undefined ;
2018-05-04 00:57:02 +08:00
/** @type {Compiler} */
2017-01-06 01:00:36 +08:00
this . compiler = compiler ;
2017-11-17 21:26:23 +08:00
this . resolverFactory = compiler . resolverFactory ;
2024-03-12 00:33:52 +08:00
/** @type {InputFileSystem} */
this . inputFileSystem =
/** @type {InputFileSystem} */
( compiler . inputFileSystem ) ;
2019-08-13 04:59:09 +08:00
this . fileSystemInfo = new FileSystemInfo ( this . inputFileSystem , {
2023-10-05 05:28:11 +08:00
unmanagedPaths : compiler . unmanagedPaths ,
2019-08-16 17:55:10 +08:00
managedPaths : compiler . managedPaths ,
2019-11-04 17:06:53 +08:00
immutablePaths : compiler . immutablePaths ,
2021-09-22 18:12:46 +08:00
logger : this . getLogger ( "webpack.FileSystemInfo" ) ,
hashFunction : compiler . options . output . hashFunction
2019-08-13 04:59:09 +08:00
} ) ;
2018-09-28 03:28:07 +08:00
if ( compiler . fileTimestamps ) {
2021-07-16 19:05:18 +08:00
this . fileSystemInfo . addFileTimestamps ( compiler . fileTimestamps , true ) ;
2018-09-28 03:28:07 +08:00
}
if ( compiler . contextTimestamps ) {
2021-07-16 19:05:18 +08:00
this . fileSystemInfo . addContextTimestamps (
compiler . contextTimestamps ,
true
) ;
2018-09-28 03:28:07 +08:00
}
2021-04-12 18:21:49 +08:00
/** @type {Map<string, string | Set<string>>} */
2021-03-15 21:28:49 +08:00
this . valueCacheVersions = new Map ( ) ;
2017-12-01 17:44:22 +08:00
this . requestShortener = compiler . requestShortener ;
2018-09-26 16:28:16 +08:00
this . compilerPath = compiler . compilerPath ;
2017-01-06 01:00:36 +08:00
2020-01-30 18:34:33 +08:00
this . logger = this . getLogger ( "webpack.Compilation" ) ;
2024-03-14 23:15:13 +08:00
const options = /** @type {WebpackOptions} */ ( compiler . options ) ;
2018-09-19 19:05:22 +08:00
this . options = options ;
2017-01-06 01:00:36 +08:00
this . outputOptions = options && options . output ;
2018-08-22 20:54:28 +08:00
/** @type {boolean} */
this . bail = ( options && options . bail ) || false ;
/** @type {boolean} */
this . profile = ( options && options . profile ) || false ;
2017-01-06 01:00:36 +08:00
2021-09-28 01:03:55 +08:00
this . params = params ;
2019-10-02 14:54:21 +08:00
this . mainTemplate = new MainTemplate ( this . outputOptions , this ) ;
this . chunkTemplate = new ChunkTemplate ( this . outputOptions , this ) ;
2018-02-25 09:00:20 +08:00
this . runtimeTemplate = new RuntimeTemplate (
2021-03-11 23:41:19 +08:00
this ,
2018-02-25 09:00:20 +08:00
this . outputOptions ,
this . requestShortener
) ;
2024-03-14 23:15:13 +08:00
/** @type {ModuleTemplates} */
2017-10-30 20:56:57 +08:00
this . moduleTemplates = {
2019-10-02 14:54:21 +08:00
javascript : new ModuleTemplate ( this . runtimeTemplate , this )
2017-10-30 20:56:57 +08:00
} ;
2021-06-17 16:11:24 +08:00
defineRemovedModuleTemplates ( this . moduleTemplates ) ;
2017-01-06 01:00:36 +08:00
2021-10-05 19:08:21 +08:00
/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
2021-09-24 17:35:28 +08:00
this . moduleMemCaches = undefined ;
2021-10-05 19:08:21 +08:00
/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
this . moduleMemCaches2 = undefined ;
2018-07-17 22:41:07 +08:00
this . moduleGraph = new ModuleGraph ( ) ;
2021-04-12 15:17:43 +08:00
/** @type {ChunkGraph} */
2018-08-14 17:18:22 +08:00
this . chunkGraph = undefined ;
2020-07-28 00:09:48 +08:00
/** @type {CodeGenerationResults} */
2019-10-09 04:29:46 +08:00
this . codeGenerationResults = undefined ;
2018-07-17 22:41:07 +08:00
2021-02-02 08:22:19 +08:00
/** @type {AsyncQueue<Module, Module, Module>} */
this . processDependenciesQueue = new AsyncQueue ( {
name : "processDependencies" ,
2018-09-12 00:47:55 +08:00
parallelism : options . parallelism || 100 ,
2021-02-02 08:22:19 +08:00
processor : this . _processModuleDependencies . bind ( this )
2018-09-12 00:47:55 +08:00
} ) ;
2018-09-26 16:27:09 +08:00
/** @type {AsyncQueue<Module, string, Module>} */
this . addModuleQueue = new AsyncQueue ( {
name : "addModule" ,
2021-02-02 08:22:19 +08:00
parent : this . processDependenciesQueue ,
2018-09-26 16:27:09 +08:00
getKey : module => module . identifier ( ) ,
processor : this . _addModule . bind ( this )
} ) ;
2021-09-28 01:03:55 +08:00
/** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
2021-02-02 08:22:19 +08:00
this . factorizeQueue = new AsyncQueue ( {
name : "factorize" ,
parent : this . addModuleQueue ,
processor : this . _factorizeModule . bind ( this )
} ) ;
2018-09-26 16:27:09 +08:00
/** @type {AsyncQueue<Module, Module, Module>} */
2018-09-12 00:47:55 +08:00
this . buildQueue = new AsyncQueue ( {
name : "build" ,
2021-02-02 08:22:19 +08:00
parent : this . factorizeQueue ,
2018-09-12 00:47:55 +08:00
processor : this . _buildModule . bind ( this )
} ) ;
2018-09-26 16:27:09 +08:00
/** @type {AsyncQueue<Module, Module, Module>} */
2018-09-12 00:47:55 +08:00
this . rebuildQueue = new AsyncQueue ( {
name : "rebuild" ,
parallelism : options . parallelism || 100 ,
processor : this . _rebuildModule . bind ( this )
} ) ;
2017-08-11 22:11:17 +08:00
2019-12-20 19:45:55 +08:00
/ * *
* 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 ( ) ;
2020-02-05 04:35:01 +08:00
/** @type {Map<string, EntryData>} */
this . entries = new Map ( ) ;
2020-05-23 22:08:51 +08:00
/** @type {EntryData} */
this . globalEntry = {
dependencies : [ ] ,
includeDependencies : [ ] ,
options : {
name : undefined
}
} ;
2018-08-14 22:40:37 +08:00
/** @type {Map<string, Entrypoint>} */
2018-01-20 00:06:59 +08:00
this . entrypoints = new Map ( ) ;
2020-09-08 00:02:14 +08:00
/** @type {Entrypoint[]} */
this . asyncEntrypoints = [ ] ;
2018-09-06 22:59:11 +08:00
/** @type {Set<Chunk>} */
this . chunks = new Set ( ) ;
2018-05-04 00:57:02 +08:00
/** @type {ChunkGroup[]} */
2018-01-20 00:06:59 +08:00
this . chunkGroups = [ ] ;
2018-05-04 00:57:02 +08:00
/** @type {Map<string, ChunkGroup>} */
2018-01-20 00:06:59 +08:00
this . namedChunkGroups = new Map ( ) ;
2018-05-04 00:57:02 +08:00
/** @type {Map<string, Chunk>} */
2018-01-20 00:06:59 +08:00
this . namedChunks = new Map ( ) ;
2018-09-05 22:12:48 +08:00
/** @type {Set<Module>} */
this . modules = new Set ( ) ;
2021-11-05 16:53:32 +08:00
if ( this . _backCompat ) {
arrayToSetDeprecation ( this . chunks , "Compilation.chunks" ) ;
arrayToSetDeprecation ( this . modules , "Compilation.modules" ) ;
}
2024-06-11 20:32:02 +08:00
/ * *
* @ private
* @ type { Map < string , Module > }
* /
2017-11-06 20:02:35 +08:00
this . _modules = new Map ( ) ;
2017-01-06 01:00:36 +08:00
this . records = null ;
2018-05-04 00:57:02 +08:00
/** @type {string[]} */
2017-01-06 01:00:36 +08:00
this . additionalChunkAssets = [ ] ;
2018-05-04 00:57:02 +08:00
/** @type {CompilationAssets} */
2017-01-06 01:00:36 +08:00
this . assets = { } ;
2019-09-11 17:13:46 +08:00
/** @type {Map<string, AssetInfo>} */
this . assetsInfo = new Map ( ) ;
2020-08-19 03:14:43 +08:00
/** @type {Map<string, Map<string, Set<string>>>} */
this . _assetsRelatedIn = new Map ( ) ;
2018-05-04 00:57:02 +08:00
/** @type {WebpackError[]} */
2017-01-06 01:00:36 +08:00
this . errors = [ ] ;
2018-05-04 00:57:02 +08:00
/** @type {WebpackError[]} */
2017-01-06 01:00:36 +08:00
this . warnings = [ ] ;
2018-05-04 00:57:02 +08:00
/** @type {Compilation[]} */
2017-01-06 01:00:36 +08:00
this . children = [ ] ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
/** @type {Map<string, LogEntry[]>} */
this . logging = new Map ( ) ;
2018-05-04 00:57:02 +08:00
/** @type {Map<DepConstructor, ModuleFactory>} */
2017-01-06 01:00:36 +08:00
this . dependencyFactories = new Map ( ) ;
2018-07-12 23:12:00 +08:00
/** @type {DependencyTemplates} */
2022-01-18 18:42:13 +08:00
this . dependencyTemplates = new DependencyTemplates (
this . outputOptions . hashFunction
) ;
2017-04-13 19:43:51 +08:00
this . childrenCounters = { } ;
2018-05-15 18:20:17 +08:00
/** @type {Set<number|string>} */
2018-01-05 14:41:09 +08:00
this . usedChunkIds = null ;
2018-05-04 00:57:02 +08:00
/** @type {Set<number>} */
2018-01-05 14:41:09 +08:00
this . usedModuleIds = null ;
2018-07-20 19:35:01 +08:00
/** @type {boolean} */
this . needAdditionalPass = false ;
2021-10-12 16:56:14 +08:00
/** @type {Set<Module & { restoreFromUnsafeCache: Function }>} */
this . _restoredUnsafeCacheModuleEntries = new Set ( ) ;
/** @type {Map<string, Module & { restoreFromUnsafeCache: Function }>} */
this . _restoredUnsafeCacheEntries = new Map ( ) ;
2018-08-22 21:33:16 +08:00
/** @type {WeakSet<Module>} */
this . builtModules = new WeakSet ( ) ;
2020-09-02 00:08:09 +08:00
/** @type {WeakSet<Module>} */
this . codeGeneratedModules = new WeakSet ( ) ;
2021-04-09 21:50:25 +08:00
/** @type {WeakSet<Module>} */
this . buildTimeExecutedModules = new WeakSet ( ) ;
2024-06-11 20:32:02 +08:00
/ * *
* @ private
* @ type { Map < Module , Callback [ ] > }
* /
2017-11-06 20:02:35 +08:00
this . _rebuildingModules = new Map ( ) ;
2019-01-19 03:38:34 +08:00
/** @type {Set<string>} */
this . emittedAssets = new Set ( ) ;
2019-11-04 16:23:18 +08:00
/** @type {Set<string>} */
this . comparedForEmitAssets = new Set ( ) ;
2019-08-07 15:54:43 +08:00
/** @type {LazySet<string>} */
this . fileDependencies = new LazySet ( ) ;
/** @type {LazySet<string>} */
this . contextDependencies = new LazySet ( ) ;
/** @type {LazySet<string>} */
this . missingDependencies = new LazySet ( ) ;
2019-08-09 20:46:42 +08:00
/** @type {LazySet<string>} */
this . buildDependencies = new LazySet ( ) ;
2019-10-10 19:48:56 +08:00
// TODO webpack 6 remove
this . compilationDependencies = {
add : util . deprecate (
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } item item
* @ returns { LazySet < string > } file dependencies
* /
2019-10-10 19:48:56 +08:00
item => this . fileDependencies . add ( item ) ,
"Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)" ,
"DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES"
)
} ;
2020-07-15 17:14:28 +08:00
this . _modulesCache = this . getCache ( "Compilation/modules" ) ;
this . _assetsCache = this . getCache ( "Compilation/assets" ) ;
2020-07-28 00:09:48 +08:00
this . _codeGenerationCache = this . getCache ( "Compilation/codeGeneration" ) ;
2021-09-28 01:03:55 +08:00
const unsafeCache = options . module . unsafeCache ;
this . _unsafeCache = ! ! unsafeCache ;
this . _unsafeCachePredicate =
typeof unsafeCache === "function" ? unsafeCache : ( ) => true ;
2017-01-06 01:00:36 +08:00
}
2014-12-22 23:10:23 +08:00
2017-04-06 19:52:06 +08:00
getStats ( ) {
return new Stats ( this ) ;
2017-01-06 01:00:36 +08:00
}
2014-12-22 23:10:23 +08:00
2020-12-18 01:51:55 +08:00
/ * *
2024-02-16 20:47:38 +08:00
* @ param { string | boolean | StatsOptions | undefined } optionsOrPreset stats option value
2020-12-18 01:51:55 +08:00
* @ param { CreateStatsOptionsContext } context context
* @ returns { NormalizedStatsOptions } normalized options
* /
2018-12-19 01:29:12 +08:00
createStatsOptions ( optionsOrPreset , context = { } ) {
if (
typeof optionsOrPreset === "boolean" ||
typeof optionsOrPreset === "string"
) {
optionsOrPreset = { preset : optionsOrPreset } ;
}
if ( typeof optionsOrPreset === "object" && optionsOrPreset !== null ) {
2019-07-25 21:51:11 +08:00
// We use this method of shallow cloning this object to include
// properties in the prototype chain
2020-12-18 01:51:55 +08:00
/** @type {Partial<NormalizedStatsOptions>} */
2019-07-25 21:51:11 +08:00
const options = { } ;
for ( const key in optionsOrPreset ) {
options [ key ] = optionsOrPreset [ key ] ;
}
2018-12-19 01:29:12 +08:00
if ( options . preset !== undefined ) {
2019-05-11 03:50:13 +08:00
this . hooks . statsPreset . for ( options . preset ) . call ( options , context ) ;
2018-12-19 01:29:12 +08:00
}
this . hooks . statsNormalize . call ( options , context ) ;
2020-12-18 01:51:55 +08:00
return /** @type {NormalizedStatsOptions} */ ( options ) ;
2018-12-19 01:29:12 +08:00
} else {
2020-12-18 01:51:55 +08:00
/** @type {Partial<NormalizedStatsOptions>} */
2018-12-19 01:29:12 +08:00
const options = { } ;
this . hooks . statsNormalize . call ( options , context ) ;
2020-12-18 01:51:55 +08:00
return /** @type {NormalizedStatsOptions} */ ( options ) ;
2018-12-19 01:29:12 +08:00
}
}
2024-03-18 01:15:44 +08:00
/ * *
* @ param { NormalizedStatsOptions } options options
* @ returns { StatsFactory } the stats factory
* /
2018-12-19 01:29:12 +08:00
createStatsFactory ( options ) {
const statsFactory = new StatsFactory ( ) ;
this . hooks . statsFactory . call ( statsFactory , options ) ;
return statsFactory ;
}
2024-03-18 01:15:44 +08:00
/ * *
* @ param { NormalizedStatsOptions } options options
* @ returns { StatsPrinter } the stats printer
* /
2018-12-19 01:29:12 +08:00
createStatsPrinter ( options ) {
const statsPrinter = new StatsPrinter ( ) ;
this . hooks . statsPrinter . call ( statsPrinter , options ) ;
return statsPrinter ;
}
2020-07-15 17:14:28 +08:00
/ * *
* @ param { string } name cache name
* @ returns { CacheFacade } the cache facade instance
* /
getCache ( name ) {
return this . compiler . getCache ( name ) ;
}
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
/ * *
* @ 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" ) ;
}
2019-07-23 15:28:06 +08:00
/** @type {LogEntry[] | undefined} */
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
let logEntries ;
2019-11-05 23:47:45 +08:00
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"
) ;
}
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
}
2019-11-05 23:47:45 +08:00
let trace ;
switch ( type ) {
case LogType . warn :
case LogType . error :
case LogType . trace :
2024-03-18 01:15:44 +08:00
trace = ErrorHelpers . cutOffLoaderExecution (
/** @type {string} */ ( new Error ( "Trace" ) . stack )
)
2019-11-05 23:47:45 +08:00
. 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 ) {
if ( typeof console . profileEnd === "function" ) {
console . profileEnd ( ` [ ${ name } ] ${ logEntry . args [ 0 ] } ` ) ;
}
2019-07-22 14:19:30 +08:00
}
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
if ( logEntries === undefined ) {
2019-11-05 23:47:45 +08:00
logEntries = this . logging . get ( name ) ;
if ( logEntries === undefined ) {
logEntries = [ ] ;
this . logging . set ( name , logEntries ) ;
}
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
}
2019-11-05 23:47:45 +08:00
logEntries . push ( logEntry ) ;
if ( logEntry . type === LogType . profile ) {
if ( typeof console . profile === "function" ) {
console . profile ( ` [ ${ name } ] ${ 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 } ` ;
} ) ;
} else {
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 } ` ;
} ) ;
}
} else {
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 } ` ;
} ) ;
} else {
return this . getLogger ( ` ${ name } / ${ childName } ` ) ;
2019-07-22 14:19:30 +08:00
}
}
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
}
2019-11-05 23:47:45 +08:00
) ;
add logging API
Plugins:
Compiler.getInfrastructureLogger(name)
Compilation.getLogger(name)
Loader:
this.getLogger([name])
API equal to console API with these methods:
error, warn, info, log, debug,
time, timeLog, timeEnd,
group, groupCollapsed, groupEnd,
profile, profileEnd,
clear
2019-07-18 23:13:40 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
* @ param { Module } module module to be added that was created
2018-09-26 16:27:09 +08:00
* @ 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 ,
2018-09-12 00:47:55 +08:00
* it could be the passed one ( if new ) , or an already existing in the compilation
2018-09-26 16:27:09 +08:00
* @ returns { void }
2018-05-04 00:57:02 +08:00
* /
2018-09-26 16:27:09 +08:00
_addModule ( module , callback ) {
2017-01-06 01:00:36 +08:00
const identifier = module . identifier ( ) ;
2017-12-07 00:22:10 +08:00
const alreadyAddedModule = this . _modules . get ( identifier ) ;
2018-02-25 09:00:20 +08:00
if ( alreadyAddedModule ) {
2018-09-26 16:27:09 +08:00
return callback ( null , alreadyAddedModule ) ;
2013-01-31 01:49:25 +08:00
}
2013-02-01 01:00:22 +08:00
2018-10-09 20:30:59 +08:00
const currentProfile = this . profile
? this . moduleGraph . getProfile ( module )
: undefined ;
if ( currentProfile !== undefined ) {
currentProfile . markRestoringStart ( ) ;
}
2020-07-15 17:14:28 +08:00
this . _modulesCache . get ( identifier , null , ( err , cacheModule ) => {
2018-10-18 04:54:07 +08:00
if ( err ) return callback ( new ModuleRestoreError ( module , err ) ) ;
2018-03-28 22:19:15 +08:00
2018-10-09 20:30:59 +08:00
if ( currentProfile !== undefined ) {
currentProfile . markRestoringEnd ( ) ;
currentProfile . markIntegrationStart ( ) ;
}
2018-09-27 13:22:19 +08:00
if ( cacheModule ) {
cacheModule . updateCacheModule ( module ) ;
module = cacheModule ;
2018-09-26 16:27:09 +08:00
}
2018-09-27 13:22:19 +08:00
this . _modules . set ( identifier , module ) ;
this . modules . add ( module ) ;
2021-11-05 16:53:32 +08:00
if ( this . _backCompat )
ModuleGraph . setModuleGraphForModule ( module , this . moduleGraph ) ;
2018-10-09 20:30:59 +08:00
if ( currentProfile !== undefined ) {
currentProfile . markIntegrationEnd ( ) ;
}
2018-09-27 13:22:19 +08:00
callback ( null , module ) ;
} ) ;
2013-01-31 01:49:25 +08:00
}
2017-01-06 01:00:36 +08:00
2018-05-04 00:57:02 +08:00
/ * *
* Fetches a module from a compilation by its identifier
* @ param { Module } module the module provided
* @ returns { Module } the module requested
* /
2017-01-06 01:00:36 +08:00
getModule ( module ) {
const identifier = module . identifier ( ) ;
2024-03-14 23:15:13 +08:00
return /** @type {Module} */ ( this . _modules . get ( identifier ) ) ;
2013-01-31 01:49:25 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
* 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
* /
2017-01-06 01:00:36 +08:00
findModule ( identifier ) {
2017-11-06 20:02:35 +08:00
return this . _modules . get ( identifier ) ;
}
2018-05-04 00:57:02 +08:00
/ * *
2018-09-12 00:47:55 +08:00
* Schedules a build of the module object
*
* @ param { Module } module module to be built
* @ param { ModuleCallback } callback the callback
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2018-09-12 00:47:55 +08:00
buildModule ( module , callback ) {
this . buildQueue . add ( module , callback ) ;
2017-01-06 01:00:36 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
* Builds the module object
*
* @ param { Module } module module to be built
2018-09-12 00:47:55 +08:00
* @ param { ModuleCallback } callback the callback
2018-12-10 18:34:59 +08:00
* @ returns { void }
2018-05-04 00:57:02 +08:00
* /
2018-09-12 00:47:55 +08:00
_buildModule ( module , callback ) {
const currentProfile = this . profile
? this . moduleGraph . getProfile ( module )
: undefined ;
if ( currentProfile !== undefined ) {
currentProfile . markBuildingStart ( ) ;
2017-01-06 01:00:36 +08:00
}
2017-11-06 20:02:35 +08:00
2018-09-26 15:14:44 +08:00
module . needBuild (
{
2021-08-04 21:55:58 +08:00
compilation : this ,
2021-03-15 21:28:49 +08:00
fileSystemInfo : this . fileSystemInfo ,
valueCacheVersions : this . valueCacheVersions
2018-09-26 15:14:44 +08:00
} ,
( err , needBuild ) => {
if ( err ) return callback ( err ) ;
if ( ! needBuild ) {
if ( currentProfile !== undefined ) {
currentProfile . markBuildingEnd ( ) ;
}
2019-07-25 21:47:31 +08:00
this . hooks . stillValidModule . call ( module ) ;
2018-09-26 15:14:44 +08:00
return callback ( ) ;
2018-09-12 00:47:55 +08:00
}
2018-09-26 15:14:44 +08:00
this . hooks . buildModule . call ( module ) ;
this . builtModules . add ( module ) ;
module . build (
this . options ,
this ,
this . resolverFactory . get ( "normal" , module . resolveOptions ) ,
2024-02-22 22:20:17 +08:00
/** @type {InputFileSystem} */ ( this . inputFileSystem ) ,
2018-09-26 15:14:44 +08:00
err => {
if ( currentProfile !== undefined ) {
currentProfile . markBuildingEnd ( ) ;
}
if ( err ) {
this . hooks . failedModule . call ( module , err ) ;
return callback ( err ) ;
}
2018-09-27 13:22:19 +08:00
if ( currentProfile !== undefined ) {
currentProfile . markStoringStart ( ) ;
}
2020-07-15 17:14:28 +08:00
this . _modulesCache . store ( module . identifier ( ) , null , module , err => {
if ( currentProfile !== undefined ) {
currentProfile . markStoringEnd ( ) ;
2018-09-27 13:22:19 +08:00
}
2020-07-15 17:14:28 +08:00
if ( err ) {
2024-03-18 23:28:40 +08:00
this . hooks . failedModule . call (
module ,
/** @type {WebpackError} */ ( err )
) ;
2020-07-15 17:14:28 +08:00
return callback ( new ModuleStoreError ( module , err ) ) ;
}
this . hooks . succeedModule . call ( module ) ;
return callback ( ) ;
} ) ;
2018-09-26 15:14:44 +08:00
}
) ;
2013-01-31 01:49:25 +08:00
}
2018-02-25 09:00:20 +08:00
) ;
2017-01-06 01:00:36 +08:00
}
2015-07-08 20:15:21 +08:00
2018-05-04 00:57:02 +08:00
/ * *
* @ param { Module } module to be processed for deps
2018-05-07 05:01:47 +08:00
* @ param { ModuleCallback } callback callback to be triggered
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2017-01-06 01:00:36 +08:00
processModuleDependencies ( module , callback ) {
2018-09-12 00:47:55 +08:00
this . processDependenciesQueue . add ( module , callback ) ;
}
2020-04-26 23:40:12 +08:00
/ * *
* @ param { Module } module to be processed for deps
* @ returns { void }
* /
processModuleDependenciesNonRecursive ( module ) {
2024-02-22 22:20:17 +08:00
/ * *
* @ param { DependenciesBlock } block block
* /
2020-04-26 23:40:12 +08:00
const processDependenciesBlock = block => {
if ( block . dependencies ) {
2021-10-05 23:25:33 +08:00
let i = 0 ;
2020-04-26 23:40:12 +08:00
for ( const dep of block . dependencies ) {
2021-10-05 23:25:33 +08:00
this . moduleGraph . setParents ( dep , block , module , i ++ ) ;
2020-04-26 23:40:12 +08:00
}
}
if ( block . blocks ) {
for ( const b of block . blocks ) processDependenciesBlock ( b ) ;
}
} ;
processDependenciesBlock ( module ) ;
}
2018-09-12 00:47:55 +08:00
/ * *
* @ param { Module } module to be processed for deps
* @ param { ModuleCallback } callback callback to be triggered
* @ returns { void }
* /
_processModuleDependencies ( module , callback ) {
2022-03-25 21:28:18 +08:00
/** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], context: string|undefined, originModule: Module|null}>} */
2019-08-07 17:57:11 +08:00
const sortedDependencies = [ ] ;
2021-04-28 16:27:27 +08:00
/** @type {DependenciesBlock} */
let currentBlock ;
2018-08-07 20:20:53 +08:00
2021-04-28 16:27:27 +08:00
/** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
let dependencies ;
/** @type {DepConstructor} */
2019-07-26 19:35:29 +08:00
let factoryCacheKey ;
2021-04-28 16:27:27 +08:00
/** @type {ModuleFactory} */
let factoryCacheKey2 ;
/** @type {Map<string, Dependency[]>} */
2019-07-26 19:35:29 +08:00
let factoryCacheValue ;
2021-04-28 16:27:27 +08:00
/** @type {string} */
let listCacheKey1 ;
/** @type {string} */
let listCacheKey2 ;
/** @type {Dependency[]} */
2019-07-26 19:35:29 +08:00
let listCacheValue ;
2021-10-12 16:56:14 +08:00
let inProgressSorting = 1 ;
let inProgressTransitive = 1 ;
2024-03-14 23:15:13 +08:00
/ * *
* @ param { WebpackError = } err error
* @ returns { void }
* /
2021-10-12 16:56:14 +08:00
const onDependenciesSorted = err => {
if ( err ) return callback ( err ) ;
// early exit without changing parallelism back and forth
if ( sortedDependencies . length === 0 && inProgressTransitive === 1 ) {
return callback ( ) ;
}
// This is nested so we need to allow one additional task
this . processDependenciesQueue . increaseParallelism ( ) ;
for ( const item of sortedDependencies ) {
inProgressTransitive ++ ;
this . handleModuleCreation ( item , err => {
// In V8, the Error objects keep a reference to the functions on the stack. These warnings &
// errors are created inside closures that keep a reference to the Compilation, so errors are
// leaking the Compilation object.
if ( err && this . bail ) {
if ( inProgressTransitive <= 0 ) return ;
inProgressTransitive = - 1 ;
// eslint-disable-next-line no-self-assign
err . stack = err . stack ;
onTransitiveTasksFinished ( err ) ;
return ;
}
if ( -- inProgressTransitive === 0 ) onTransitiveTasksFinished ( ) ;
} ) ;
}
if ( -- inProgressTransitive === 0 ) onTransitiveTasksFinished ( ) ;
} ;
2024-02-22 22:20:17 +08:00
/ * *
* @ param { WebpackError = } err error
* @ returns { void }
* /
2021-10-12 16:56:14 +08:00
const onTransitiveTasksFinished = err => {
if ( err ) return callback ( err ) ;
this . processDependenciesQueue . decreaseParallelism ( ) ;
return callback ( ) ;
} ;
2021-09-28 01:03:55 +08:00
2021-04-28 16:27:27 +08:00
/ * *
* @ param { Dependency } dep dependency
2021-10-05 23:25:33 +08:00
* @ param { number } index index in block
2021-04-28 16:27:27 +08:00
* @ returns { void }
* /
2021-10-05 23:25:33 +08:00
const processDependency = ( dep , index ) => {
this . moduleGraph . setParents ( dep , currentBlock , module , index ) ;
2021-09-28 01:03:55 +08:00
if ( this . _unsafeCache ) {
try {
2021-10-12 16:56:14 +08:00
const unsafeCachedModule = unsafeCacheDependencies . get ( dep ) ;
if ( unsafeCachedModule === null ) return ;
if ( unsafeCachedModule !== undefined ) {
if (
this . _restoredUnsafeCacheModuleEntries . has ( unsafeCachedModule )
) {
this . _handleExistingModuleFromUnsafeCache (
module ,
dep ,
unsafeCachedModule
) ;
return ;
}
const identifier = unsafeCachedModule . identifier ( ) ;
const cachedModule =
this . _restoredUnsafeCacheEntries . get ( identifier ) ;
if ( cachedModule !== undefined ) {
// update unsafe cache to new module
unsafeCacheDependencies . set ( dep , cachedModule ) ;
this . _handleExistingModuleFromUnsafeCache (
module ,
dep ,
cachedModule
2021-09-28 01:03:55 +08:00
) ;
2021-10-12 16:56:14 +08:00
return ;
}
inProgressSorting ++ ;
this . _modulesCache . get ( identifier , null , ( err , cachedModule ) => {
if ( err ) {
if ( inProgressSorting <= 0 ) return ;
inProgressSorting = - 1 ;
2024-03-18 23:28:40 +08:00
onDependenciesSorted ( /** @type {WebpackError} */ ( err ) ) ;
2021-09-28 01:03:55 +08:00
return ;
}
2021-10-12 16:56:14 +08:00
try {
if ( ! this . _restoredUnsafeCacheEntries . has ( identifier ) ) {
const data = unsafeCacheData . get ( cachedModule ) ;
if ( data === undefined ) {
processDependencyForResolving ( dep ) ;
if ( -- inProgressSorting === 0 ) onDependenciesSorted ( ) ;
return ;
}
if ( cachedModule !== unsafeCachedModule ) {
unsafeCacheDependencies . set ( dep , cachedModule ) ;
}
cachedModule . restoreFromUnsafeCache (
data ,
this . params . normalModuleFactory ,
this . params
) ;
this . _restoredUnsafeCacheEntries . set (
identifier ,
cachedModule
) ;
this . _restoredUnsafeCacheModuleEntries . add ( cachedModule ) ;
if ( ! this . modules . has ( cachedModule ) ) {
inProgressTransitive ++ ;
this . _handleNewModuleFromUnsafeCache (
module ,
dep ,
cachedModule ,
err => {
if ( err ) {
if ( inProgressTransitive <= 0 ) return ;
inProgressTransitive = - 1 ;
onTransitiveTasksFinished ( err ) ;
}
if ( -- inProgressTransitive === 0 )
return onTransitiveTasksFinished ( ) ;
}
) ;
if ( -- inProgressSorting === 0 ) onDependenciesSorted ( ) ;
return ;
}
}
if ( unsafeCachedModule !== cachedModule ) {
unsafeCacheDependencies . set ( dep , cachedModule ) ;
}
this . _handleExistingModuleFromUnsafeCache (
module ,
dep ,
cachedModule
) ; // a3
} catch ( err ) {
if ( inProgressSorting <= 0 ) return ;
inProgressSorting = - 1 ;
2024-03-18 01:15:44 +08:00
onDependenciesSorted ( /** @type {WebpackError} */ ( err ) ) ;
2021-10-12 16:56:14 +08:00
return ;
}
if ( -- inProgressSorting === 0 ) onDependenciesSorted ( ) ;
} ) ;
2021-09-28 01:03:55 +08:00
return ;
}
} catch ( e ) {
console . error ( e ) ;
}
}
2021-10-12 16:56:14 +08:00
processDependencyForResolving ( dep ) ;
} ;
/ * *
* @ param { Dependency } dep dependency
* @ returns { void }
* /
const processDependencyForResolving = dep => {
2020-05-28 15:10:31 +08:00
const resourceIdent = dep . getResourceIdentifier ( ) ;
2021-04-28 16:27:27 +08:00
if ( resourceIdent !== undefined && resourceIdent !== null ) {
2020-06-18 05:01:18 +08:00
const category = dep . category ;
2021-04-28 16:27:27 +08:00
const constructor = /** @type {DepConstructor} */ ( dep . constructor ) ;
2019-07-26 19:35:29 +08:00
if ( factoryCacheKey === constructor ) {
2021-04-28 16:27:27 +08:00
// Fast path 1: same constructor as prev item
if ( listCacheKey1 === category && listCacheKey2 === resourceIdent ) {
// Super fast path 1: also same resource
2019-07-26 19:35:29 +08:00
listCacheValue . push ( dep ) ;
return ;
}
} else {
2021-04-28 16:27:27 +08:00
const factory = this . dependencyFactories . get ( constructor ) ;
2019-07-26 19:35:29 +08:00
if ( factory === undefined ) {
throw new Error (
2021-04-27 19:57:54 +08:00
` No module factory available for dependency type: ${ constructor . name } `
2019-07-26 19:35:29 +08:00
) ;
}
2021-04-28 16:27:27 +08:00
if ( factoryCacheKey2 === factory ) {
// Fast path 2: same factory as prev item
factoryCacheKey = constructor ;
if ( listCacheKey1 === category && listCacheKey2 === resourceIdent ) {
// Super fast path 2: also same resource
listCacheValue . push ( dep ) ;
return ;
}
} else {
// Slow path
if ( factoryCacheKey2 !== undefined ) {
// Archive last cache entry
if ( dependencies === undefined ) dependencies = new Map ( ) ;
dependencies . set ( factoryCacheKey2 , factoryCacheValue ) ;
factoryCacheValue = dependencies . get ( factory ) ;
if ( factoryCacheValue === undefined ) {
factoryCacheValue = new Map ( ) ;
}
} else {
factoryCacheValue = new Map ( ) ;
}
factoryCacheKey = constructor ;
factoryCacheKey2 = factory ;
2019-07-26 19:35:29 +08:00
}
2018-05-29 20:50:40 +08:00
}
2021-04-28 16:27:27 +08:00
// Here webpack is using heuristic that assumes
// mostly esm dependencies would be used
// so we don't allocate extra string for them
const cacheKey =
category === esmDependencyCategory
? resourceIdent
: ` ${ category } ${ resourceIdent } ` ;
let list = factoryCacheValue . get ( cacheKey ) ;
2019-08-07 17:57:11 +08:00
if ( list === undefined ) {
2021-04-28 16:27:27 +08:00
factoryCacheValue . set ( cacheKey , ( list = [ ] ) ) ;
2019-08-07 17:57:11 +08:00
sortedDependencies . push ( {
2021-04-28 16:27:27 +08:00
factory : factoryCacheKey2 ,
2019-08-07 17:57:11 +08:00
dependencies : list ,
2022-03-25 21:28:18 +08:00
context : dep . getContext ( ) ,
2019-08-07 17:57:11 +08:00
originModule : module
} ) ;
}
2017-11-19 07:22:38 +08:00
list . push ( dep ) ;
2021-04-28 16:27:27 +08:00
listCacheKey1 = category ;
listCacheKey2 = resourceIdent ;
2019-07-26 19:35:29 +08:00
listCacheValue = list ;
2014-06-04 03:03:21 +08:00
}
2017-11-08 18:32:05 +08:00
} ;
2017-01-06 01:00:36 +08:00
2017-11-19 16:06:40 +08:00
try {
2021-04-28 16:27:27 +08:00
/** @type {DependenciesBlock[]} */
const queue = [ module ] ;
do {
2024-03-18 01:15:44 +08:00
const block = /** @type {DependenciesBlock} */ ( queue . pop ( ) ) ;
2021-04-28 16:27:27 +08:00
if ( block . dependencies ) {
currentBlock = block ;
2021-10-05 23:25:33 +08:00
let i = 0 ;
for ( const dep of block . dependencies ) processDependency ( dep , i ++ ) ;
2021-04-28 16:27:27 +08:00
}
if ( block . blocks ) {
for ( const b of block . blocks ) queue . push ( b ) ;
}
} while ( queue . length !== 0 ) ;
2018-02-25 09:00:20 +08:00
} catch ( e ) {
2018-09-07 21:51:27 +08:00
return callback ( e ) ;
2017-11-19 16:06:40 +08:00
}
2017-11-19 07:22:38 +08:00
2021-10-12 16:56:14 +08:00
if ( -- inProgressSorting === 0 ) onDependenciesSorted ( ) ;
2021-09-28 01:03:55 +08:00
}
2024-03-18 01:15:44 +08:00
/ * *
* @ private
* @ param { Module } originModule original module
* @ param { Dependency } dependency dependency
* @ param { Module } module cached module
* @ param { Callback } callback callback
* /
2021-10-12 16:56:14 +08:00
_handleNewModuleFromUnsafeCache ( originModule , dependency , module , callback ) {
2021-09-28 01:03:55 +08:00
const moduleGraph = this . moduleGraph ;
moduleGraph . setResolvedModule ( originModule , dependency , module ) ;
moduleGraph . setIssuerIfUnset (
module ,
originModule !== undefined ? originModule : null
2019-11-08 19:23:04 +08:00
) ;
2021-09-28 01:03:55 +08:00
this . _modules . set ( module . identifier ( ) , module ) ;
this . modules . add ( module ) ;
2021-11-05 16:53:32 +08:00
if ( this . _backCompat )
ModuleGraph . setModuleGraphForModule ( module , this . moduleGraph ) ;
2021-10-12 16:56:14 +08:00
this . _handleModuleBuildAndDependencies (
originModule ,
module ,
true ,
2024-01-23 18:07:58 +08:00
false ,
2021-10-12 16:56:14 +08:00
callback
) ;
2021-09-28 01:03:55 +08:00
}
2024-03-18 01:15:44 +08:00
/ * *
* @ private
* @ param { Module } originModule original modules
* @ param { Dependency } dependency dependency
* @ param { Module } module cached module
* /
2021-09-28 01:03:55 +08:00
_handleExistingModuleFromUnsafeCache ( originModule , dependency , module ) {
const moduleGraph = this . moduleGraph ;
moduleGraph . setResolvedModule ( originModule , dependency , module ) ;
2017-01-06 01:00:36 +08:00
}
2013-05-08 19:28:54 +08:00
2018-05-04 00:57:02 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } HandleModuleCreationOptions
2018-09-12 00:47:55 +08:00
* @ property { ModuleFactory } factory
2018-09-07 21:51:27 +08:00
* @ property { Dependency [ ] } dependencies
2018-09-12 00:47:55 +08:00
* @ property { Module | null } originModule
2020-12-22 21:51:09 +08:00
* @ property { Partial < ModuleFactoryCreateDataContextInfo >= } contextInfo
2018-09-12 00:47:55 +08:00
* @ property { string = } context
2019-12-20 19:45:55 +08:00
* @ property { boolean = } recursive recurse into dependencies of the created module
2021-04-10 02:45:59 +08:00
* @ property { boolean = } connectOrigin connect the resolved module with the origin module
2024-01-23 17:32:02 +08:00
* @ property { boolean = } checkCycle check the cycle dependencies of the created module
2018-09-07 21:51:27 +08:00
* /
/ * *
2018-09-12 00:47:55 +08:00
* @ param { HandleModuleCreationOptions } options options object
2018-09-07 21:51:27 +08:00
* @ param { ModuleCallback } callback callback
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2018-09-12 00:47:55 +08:00
handleModuleCreation (
2020-12-22 21:51:09 +08:00
{
factory ,
dependencies ,
originModule ,
contextInfo ,
context ,
2021-04-10 02:45:59 +08:00
recursive = true ,
2024-01-23 17:32:02 +08:00
connectOrigin = recursive ,
checkCycle = ! recursive
2020-12-22 21:51:09 +08:00
} ,
2018-09-07 21:51:27 +08:00
callback
) {
2018-09-12 00:47:55 +08:00
const moduleGraph = this . moduleGraph ;
2018-08-22 20:54:28 +08:00
2018-09-12 00:47:55 +08:00
const currentProfile = this . profile ? new ModuleProfile ( ) : undefined ;
2013-01-31 01:49:25 +08:00
2018-09-12 00:47:55 +08:00
this . factorizeModule (
2020-12-22 21:51:09 +08:00
{
currentProfile ,
factory ,
dependencies ,
2021-09-28 01:03:55 +08:00
factoryResult : true ,
2020-12-22 21:51:09 +08:00
originModule ,
contextInfo ,
context
} ,
2021-09-28 01:03:55 +08:00
( err , factoryResult ) => {
const applyFactoryResultDependencies = ( ) => {
const { fileDependencies , contextDependencies , missingDependencies } =
factoryResult ;
if ( fileDependencies ) {
this . fileDependencies . addAll ( fileDependencies ) ;
}
if ( contextDependencies ) {
this . contextDependencies . addAll ( contextDependencies ) ;
}
if ( missingDependencies ) {
this . missingDependencies . addAll ( missingDependencies ) ;
}
} ;
2018-09-12 00:47:55 +08:00
if ( err ) {
2021-09-28 01:03:55 +08:00
if ( factoryResult ) applyFactoryResultDependencies ( ) ;
2018-09-12 00:47:55 +08:00
if ( dependencies . every ( d => d . optional ) ) {
this . warnings . push ( err ) ;
2021-08-06 18:09:55 +08:00
return callback ( ) ;
2018-09-12 00:47:55 +08:00
} else {
this . errors . push ( err ) ;
2021-08-06 18:09:55 +08:00
return callback ( err ) ;
2018-09-12 00:47:55 +08:00
}
2018-09-07 21:51:27 +08:00
}
2021-09-28 01:03:55 +08:00
const newModule = factoryResult . module ;
2018-09-12 00:47:55 +08:00
if ( ! newModule ) {
2021-09-28 01:03:55 +08:00
applyFactoryResultDependencies ( ) ;
2018-09-12 00:47:55 +08:00
return callback ( ) ;
2018-09-07 21:51:27 +08:00
}
2018-09-12 00:47:55 +08:00
2018-10-09 20:30:59 +08:00
if ( currentProfile !== undefined ) {
moduleGraph . setProfile ( newModule , currentProfile ) ;
}
2024-03-18 01:15:44 +08:00
this . addModule ( newModule , ( err , _module ) => {
2018-09-26 16:27:09 +08:00
if ( err ) {
2021-09-28 01:03:55 +08:00
applyFactoryResultDependencies ( ) ;
2018-09-07 21:51:27 +08:00
if ( ! err . module ) {
2024-03-18 01:15:44 +08:00
err . module = _module ;
2018-09-07 21:51:27 +08:00
}
this . errors . push ( err ) ;
2018-09-12 00:47:55 +08:00
return callback ( err ) ;
2018-09-07 20:11:48 +08:00
}
2018-09-07 21:51:27 +08:00
2024-03-18 01:15:44 +08:00
const module =
/** @type {Module & { restoreFromUnsafeCache?: Function }} */
( _module ) ;
2021-09-28 01:03:55 +08:00
if (
this . _unsafeCache &&
factoryResult . cacheable !== false &&
2024-03-18 01:15:44 +08:00
module . restoreFromUnsafeCache &&
2021-09-28 01:03:55 +08:00
this . _unsafeCachePredicate ( module )
) {
2021-10-12 16:56:14 +08:00
const unsafeCacheableModule =
2024-03-18 01:15:44 +08:00
/** @type {Module & { restoreFromUnsafeCache: Function }} */
( module ) ;
2021-09-28 01:03:55 +08:00
for ( let i = 0 ; i < dependencies . length ; i ++ ) {
const dependency = dependencies [ i ] ;
moduleGraph . setResolvedModule (
connectOrigin ? originModule : null ,
dependency ,
2021-10-12 16:56:14 +08:00
unsafeCacheableModule
2021-09-28 01:03:55 +08:00
) ;
2021-10-12 16:56:14 +08:00
unsafeCacheDependencies . set ( dependency , unsafeCacheableModule ) ;
2021-09-28 01:03:55 +08:00
}
2021-10-12 16:56:14 +08:00
if ( ! unsafeCacheData . has ( unsafeCacheableModule ) ) {
unsafeCacheData . set (
unsafeCacheableModule ,
unsafeCacheableModule . getUnsafeCacheData ( )
) ;
2021-09-28 01:03:55 +08:00
}
} else {
applyFactoryResultDependencies ( ) ;
for ( let i = 0 ; i < dependencies . length ; i ++ ) {
const dependency = dependencies [ i ] ;
moduleGraph . setResolvedModule (
connectOrigin ? originModule : null ,
dependency ,
module
) ;
}
2018-09-26 16:27:09 +08:00
}
2019-08-07 17:56:26 +08:00
moduleGraph . setIssuerIfUnset (
module ,
originModule !== undefined ? originModule : null
) ;
2018-10-09 20:30:59 +08:00
if ( module !== newModule ) {
2018-09-26 16:27:09 +08:00
if ( currentProfile !== undefined ) {
2018-10-09 20:30:59 +08:00
const otherProfile = moduleGraph . getProfile ( module ) ;
if ( otherProfile !== undefined ) {
currentProfile . mergeInto ( otherProfile ) ;
} else {
moduleGraph . setProfile ( module , currentProfile ) ;
}
2018-09-26 16:27:09 +08:00
}
2018-02-25 09:00:20 +08:00
}
2018-09-07 21:51:27 +08:00
2021-09-28 01:03:55 +08:00
this . _handleModuleBuildAndDependencies (
originModule ,
module ,
recursive ,
2024-01-23 17:32:02 +08:00
checkCycle ,
2021-09-28 01:03:55 +08:00
callback
) ;
} ) ;
}
) ;
}
2019-12-20 19:45:55 +08:00
2024-03-18 01:15:44 +08:00
/ * *
* @ private
* @ param { Module } originModule original module
* @ param { Module } module module
* @ param { boolean } recursive true if make it recursive , otherwise false
* @ param { boolean } checkCycle true if need to check cycle , otherwise false
* @ param { ModuleCallback } callback callback
* @ returns { void }
* /
2024-01-23 17:32:02 +08:00
_handleModuleBuildAndDependencies (
originModule ,
module ,
recursive ,
checkCycle ,
callback
) {
2021-09-28 01:03:55 +08:00
// Check for cycles when build is trigger inside another build
let creatingModuleDuringBuildSet = undefined ;
2024-01-23 17:32:02 +08:00
if ( checkCycle && this . buildQueue . isProcessing ( originModule ) ) {
2021-09-28 01:03:55 +08:00
// Track build dependency
creatingModuleDuringBuildSet =
this . creatingModuleDuringBuild . get ( originModule ) ;
if ( creatingModuleDuringBuildSet === undefined ) {
creatingModuleDuringBuildSet = new Set ( ) ;
this . creatingModuleDuringBuild . set (
originModule ,
creatingModuleDuringBuildSet
) ;
}
2021-10-19 03:20:23 +08:00
creatingModuleDuringBuildSet . add ( module ) ;
2021-09-28 01:03:55 +08:00
// When building is blocked by another module
// search for a cycle, cancel the cycle by throwing
// an error (otherwise this would deadlock)
const blockReasons = this . creatingModuleDuringBuild . get ( module ) ;
if ( blockReasons !== undefined ) {
const set = new Set ( blockReasons ) ;
for ( const item of set ) {
const blockReasons = this . creatingModuleDuringBuild . get ( item ) ;
if ( blockReasons !== undefined ) {
for ( const m of blockReasons ) {
if ( m === module ) {
return callback ( new BuildCycleError ( module ) ) ;
2018-09-26 16:27:09 +08:00
}
2021-09-28 01:03:55 +08:00
set . add ( m ) ;
2018-09-12 00:47:55 +08:00
}
2021-09-28 01:03:55 +08:00
}
}
}
}
2018-09-26 16:27:09 +08:00
2021-09-28 01:03:55 +08:00
this . buildModule ( module , err => {
if ( creatingModuleDuringBuildSet !== undefined ) {
creatingModuleDuringBuildSet . delete ( module ) ;
}
if ( err ) {
if ( ! err . module ) {
err . module = module ;
}
this . errors . push ( err ) ;
2019-12-20 19:45:55 +08:00
2021-09-28 01:03:55 +08:00
return callback ( err ) ;
}
2018-09-26 16:27:09 +08:00
2021-09-28 01:03:55 +08:00
if ( ! recursive ) {
this . processModuleDependenciesNonRecursive ( module ) ;
callback ( null , module ) ;
return ;
2018-09-07 21:51:27 +08:00
}
2021-09-28 01:03:55 +08:00
// This avoids deadlocks for circular dependencies
if ( this . processDependenciesQueue . isProcessing ( module ) ) {
2022-08-06 18:22:33 +08:00
return callback ( null , module ) ;
2021-09-28 01:03:55 +08:00
}
2018-09-07 21:51:27 +08:00
2021-09-28 01:03:55 +08:00
this . processModuleDependencies ( module , err => {
if ( err ) {
return callback ( err ) ;
}
callback ( null , module ) ;
} ) ;
} ) ;
2018-09-07 21:51:27 +08:00
}
/ * *
2018-09-12 00:47:55 +08:00
* @ param { FactorizeModuleOptions } options options object
2021-09-28 01:03:55 +08:00
* @ param { ModuleOrFactoryResultCallback } callback callback
2018-09-07 21:51:27 +08:00
* @ returns { void }
* /
2018-09-12 00:47:55 +08:00
_factorizeModule (
2020-12-22 21:51:09 +08:00
{
currentProfile ,
factory ,
dependencies ,
originModule ,
2021-09-28 01:03:55 +08:00
factoryResult ,
2020-12-22 21:51:09 +08:00
contextInfo ,
context
} ,
2018-09-12 00:47:55 +08:00
callback
) {
if ( currentProfile !== undefined ) {
currentProfile . markFactoryStart ( ) ;
}
factory . create (
{
contextInfo : {
issuer : originModule ? originModule . nameForCondition ( ) : "" ,
2020-12-22 21:51:09 +08:00
issuerLayer : originModule ? originModule . layer : null ,
compiler : this . compiler . name ,
... contextInfo
2018-09-12 00:47:55 +08:00
} ,
resolveOptions : originModule ? originModule . resolveOptions : undefined ,
context : context
? context
: originModule
2024-01-14 09:41:34 +08:00
? originModule . context
: this . compiler . context ,
2018-09-12 00:47:55 +08:00
dependencies : dependencies
2018-02-25 09:00:20 +08:00
} ,
2019-01-05 02:17:37 +08:00
( err , result ) => {
if ( result ) {
2019-09-26 21:51:40 +08:00
// TODO webpack 6: remove
// For backward-compat
if ( result . module === undefined && result instanceof Module ) {
result = {
module : result
} ;
}
2021-09-28 01:03:55 +08:00
if ( ! factoryResult ) {
const {
fileDependencies ,
contextDependencies ,
missingDependencies
} = result ;
if ( fileDependencies ) {
this . fileDependencies . addAll ( fileDependencies ) ;
}
if ( contextDependencies ) {
this . contextDependencies . addAll ( contextDependencies ) ;
}
if ( missingDependencies ) {
this . missingDependencies . addAll ( missingDependencies ) ;
}
2019-01-05 02:17:37 +08:00
}
}
2018-02-25 09:00:20 +08:00
if ( err ) {
2018-09-12 00:47:55 +08:00
const notFoundError = new ModuleNotFoundError (
originModule ,
err ,
dependencies . map ( d => d . loc ) . filter ( Boolean ) [ 0 ]
) ;
2021-09-28 01:03:55 +08:00
return callback ( notFoundError , factoryResult ? result : undefined ) ;
2018-09-12 00:47:55 +08:00
}
2019-01-05 02:17:37 +08:00
if ( ! result ) {
return callback ( ) ;
}
2021-09-28 01:03:55 +08:00
2018-09-12 00:47:55 +08:00
if ( currentProfile !== undefined ) {
currentProfile . markFactoryEnd ( ) ;
2018-02-25 09:00:20 +08:00
}
2013-01-31 01:49:25 +08:00
2021-09-28 01:03:55 +08:00
callback ( null , factoryResult ? result : result . module ) ;
2017-01-06 01:00:36 +08:00
}
2018-02-25 09:00:20 +08:00
) ;
2014-06-04 03:03:21 +08:00
}
2013-01-31 01:49:25 +08:00
2018-05-04 00:57:02 +08:00
/ * *
* @ param { string } context context string path
* @ param { Dependency } dependency dependency used to create Module chain
2018-09-12 00:47:55 +08:00
* @ param { ModuleCallback } callback callback for when module chain is complete
2018-05-15 18:20:17 +08:00
* @ returns { void } will throw if dependency instance is not a valid Dependency
2018-05-04 00:57:02 +08:00
* /
2018-08-22 21:19:05 +08:00
addModuleChain ( context , dependency , callback ) {
2020-12-22 21:51:09 +08:00
return this . addModuleTree ( { context , dependency } , callback ) ;
}
/ * *
2024-06-11 21:09:50 +08:00
* @ param { object } options options
2020-12-22 21:51:09 +08:00
* @ param { string } options . context context string path
* @ param { Dependency } options . dependency dependency used to create Module chain
* @ param { Partial < ModuleFactoryCreateDataContextInfo >= } options . contextInfo additional context info for the root module
* @ param { ModuleCallback } callback callback for when module chain is complete
* @ returns { void } will throw if dependency instance is not a valid Dependency
* /
addModuleTree ( { context , dependency , contextInfo } , callback ) {
2018-02-25 09:00:20 +08:00
if (
typeof dependency !== "object" ||
dependency === null ||
! dependency . constructor
) {
2018-12-03 00:00:16 +08:00
return callback (
new WebpackError ( "Parameter 'dependency' must be a Dependency" )
) ;
2014-06-04 03:03:21 +08:00
}
2018-06-25 22:23:40 +08:00
const Dep = /** @type {DepConstructor} */ ( dependency . constructor ) ;
const moduleFactory = this . dependencyFactories . get ( Dep ) ;
2018-02-25 09:00:20 +08:00
if ( ! moduleFactory ) {
2018-12-03 00:00:16 +08:00
return callback (
new WebpackError (
2019-06-13 16:51:12 +08:00
` No dependency factory available for this dependency type: ${ dependency . constructor . name } `
2018-12-03 00:00:16 +08:00
)
2018-02-25 09:00:20 +08:00
) ;
2013-05-13 19:34:00 +08:00
}
2018-09-07 21:51:27 +08:00
this . handleModuleCreation (
{
factory : moduleFactory ,
dependencies : [ dependency ] ,
originModule : null ,
2020-12-22 21:51:09 +08:00
contextInfo ,
2018-09-12 00:47:55 +08:00
context
2018-09-07 21:51:27 +08:00
} ,
2021-08-17 03:40:35 +08:00
( err , result ) => {
2019-01-14 22:52:27 +08:00
if ( err && this . bail ) {
2018-11-23 18:04:03 +08:00
callback ( err ) ;
2018-09-12 00:47:55 +08:00
this . buildQueue . stop ( ) ;
this . rebuildQueue . stop ( ) ;
this . processDependenciesQueue . stop ( ) ;
this . factorizeQueue . stop ( ) ;
2021-08-17 03:40:35 +08:00
} else if ( ! err && result ) {
callback ( null , result ) ;
2019-01-14 22:52:27 +08:00
} else {
callback ( ) ;
2018-09-12 00:47:55 +08:00
}
}
2018-09-07 21:51:27 +08:00
) ;
2017-01-06 01:00:36 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
* @ param { string } context context path for entry
2020-05-23 22:08:51 +08:00
* @ param { Dependency } entry entry dependency that should be followed
2020-02-05 04:35:01 +08:00
* @ param { string | EntryOptions } optionsOrName options or deprecated name of entry
2018-05-04 00:57:02 +08:00
* @ param { ModuleCallback } callback callback function
* @ returns { void } returns
* /
2020-02-05 04:35:01 +08:00
addEntry ( context , entry , optionsOrName , callback ) {
2020-02-05 04:21:42 +08:00
// TODO webpack 6 remove
2020-02-05 04:35:01 +08:00
const options =
typeof optionsOrName === "object"
? optionsOrName
: { name : optionsOrName } ;
2018-10-29 20:49:31 +08:00
2020-05-23 22:08:51 +08:00
this . _addEntryItem ( context , entry , "dependencies" , options , callback ) ;
}
/ * *
* @ param { string } context context path for entry
* @ param { Dependency } dependency dependency that should be followed
* @ param { EntryOptions } options options
* @ param { ModuleCallback } callback callback function
* @ returns { void } returns
* /
addInclude ( context , dependency , options , callback ) {
this . _addEntryItem (
context ,
dependency ,
"includeDependencies" ,
options ,
callback
) ;
}
2020-10-06 23:42:03 +08:00
2020-05-23 22:08:51 +08:00
/ * *
* @ param { string } context context path for entry
* @ param { Dependency } entry entry dependency that should be followed
* @ param { "dependencies" | "includeDependencies" } target type of entry
* @ param { EntryOptions } options options
* @ param { ModuleCallback } callback callback function
* @ returns { void } returns
* /
_addEntryItem ( context , entry , target , options , callback ) {
2020-02-05 04:21:42 +08:00
const { name } = options ;
2020-05-27 00:08:16 +08:00
let entryData =
name !== undefined ? this . entries . get ( name ) : this . globalEntry ;
2020-02-05 04:35:01 +08:00
if ( entryData === undefined ) {
entryData = {
2020-05-23 22:08:51 +08:00
dependencies : [ ] ,
includeDependencies : [ ] ,
2020-02-05 04:35:01 +08:00
options : {
name : undefined ,
... options
}
} ;
2020-05-23 22:08:51 +08:00
entryData [ target ] . push ( entry ) ;
2024-03-18 01:15:44 +08:00
this . entries . set (
/** @type {NonNullable<EntryOptions["name"]>} */ ( name ) ,
entryData
) ;
2020-02-05 04:35:01 +08:00
} else {
2020-05-23 22:08:51 +08:00
entryData [ target ] . push ( entry ) ;
2020-02-05 04:35:01 +08:00
for ( const key of Object . keys ( options ) ) {
2020-06-04 08:06:57 +08:00
if ( options [ key ] === undefined ) continue ;
2020-02-05 04:35:01 +08:00
if ( entryData . options [ key ] === options [ key ] ) continue ;
2020-10-06 23:42:03 +08:00
if (
Array . isArray ( entryData . options [ key ] ) &&
Array . isArray ( options [ key ] ) &&
2020-10-06 23:48:13 +08:00
arrayEquals ( entryData . options [ key ] , options [ key ] )
2020-10-06 23:42:03 +08:00
) {
continue ;
}
2020-02-05 04:35:01 +08:00
if ( entryData . options [ key ] === undefined ) {
entryData . options [ key ] = options [ key ] ;
} else {
return callback (
new WebpackError (
` Conflicting entry option ${ key } = ${ entryData . options [ key ] } vs ${ options [ key ] } `
)
) ;
}
}
2018-05-04 00:57:02 +08:00
}
2020-02-05 04:35:01 +08:00
this . hooks . addEntry . call ( entry , options ) ;
2018-05-04 00:57:02 +08:00
2020-12-22 21:51:09 +08:00
this . addModuleTree (
{
context ,
dependency : entry ,
contextInfo : entryData . options . layer
? { issuerLayer : entryData . options . layer }
: undefined
} ,
( err , module ) => {
if ( err ) {
this . hooks . failedEntry . call ( entry , options , err ) ;
return callback ( err ) ;
}
2024-03-14 23:15:13 +08:00
this . hooks . succeedEntry . call (
entry ,
options ,
/** @type {Module} */ ( module )
) ;
2020-12-22 21:51:09 +08:00
return callback ( null , module ) ;
2015-05-11 00:43:47 +08:00
}
2020-12-22 21:51:09 +08:00
) ;
2017-01-06 01:00:36 +08:00
}
2018-05-07 05:01:47 +08:00
/ * *
* @ param { Module } module module to be rebuilt
2018-09-12 00:47:55 +08:00
* @ param { ModuleCallback } callback callback when module finishes rebuilding
2018-05-07 05:01:47 +08:00
* @ returns { void }
* /
2018-09-12 00:47:55 +08:00
rebuildModule ( module , callback ) {
this . rebuildQueue . add ( module , callback ) ;
}
2017-11-06 20:02:35 +08:00
2018-09-12 00:47:55 +08:00
/ * *
* @ param { Module } module module to be rebuilt
* @ param { ModuleCallback } callback callback when module finishes rebuilding
* @ returns { void }
* /
_rebuildModule ( module , callback ) {
2017-12-07 00:39:42 +08:00
this . hooks . rebuildModule . call ( module ) ;
2017-11-06 20:02:35 +08:00
const oldDependencies = module . dependencies . slice ( ) ;
const oldBlocks = module . blocks . slice ( ) ;
2018-09-12 00:47:55 +08:00
module . invalidateBuild ( ) ;
this . buildQueue . invalidate ( module ) ;
2018-09-07 20:11:48 +08:00
this . buildModule ( module , err => {
2018-02-25 09:00:20 +08:00
if ( err ) {
2018-12-30 21:54:47 +08:00
return this . hooks . finishRebuildingModule . callAsync ( module , err2 => {
2019-05-10 17:06:25 +08:00
if ( err2 ) {
callback (
makeWebpackError ( err2 , "Compilation.hooks.finishRebuildingModule" )
) ;
return ;
}
callback ( err ) ;
2018-12-30 21:54:47 +08:00
} ) ;
2017-12-07 00:39:42 +08:00
}
2013-05-13 19:34:00 +08:00
2021-02-03 05:40:20 +08:00
this . processDependenciesQueue . invalidate ( module ) ;
2021-04-13 23:33:05 +08:00
this . moduleGraph . unfreeze ( ) ;
2018-02-25 09:00:20 +08:00
this . processModuleDependencies ( module , err => {
if ( err ) return callback ( err ) ;
2017-11-06 20:02:35 +08:00
this . removeReasonsOfDependencyBlock ( module , {
dependencies : oldDependencies ,
blocks : oldBlocks
2017-01-06 01:00:36 +08:00
} ) ;
2019-05-10 17:06:25 +08:00
this . hooks . finishRebuildingModule . callAsync ( module , err2 => {
if ( err2 ) {
callback (
makeWebpackError ( err2 , "Compilation.hooks.finishRebuildingModule" )
) ;
return ;
}
callback ( null , module ) ;
} ) ;
2017-01-06 01:00:36 +08:00
} ) ;
} ) ;
}
2013-05-13 19:34:00 +08:00
2024-02-22 22:20:17 +08:00
/ * *
* @ private
2024-02-22 22:36:36 +08:00
* @ param { Set < Module > } modules modules
2024-02-22 22:20:17 +08:00
* /
2021-09-24 17:35:28 +08:00
_computeAffectedModules ( modules ) {
const moduleMemCacheCache = this . compiler . moduleMemCaches ;
if ( ! moduleMemCacheCache ) return ;
2021-09-27 23:21:09 +08:00
if ( ! this . moduleMemCaches ) {
2021-10-05 19:08:21 +08:00
this . moduleMemCaches = new Map ( ) ;
2021-09-27 23:21:09 +08:00
this . moduleGraph . setModuleMemCaches ( this . moduleMemCaches ) ;
}
2021-09-27 22:41:26 +08:00
const { moduleGraph , moduleMemCaches } = this ;
2021-09-24 17:35:28 +08:00
const affectedModules = new Set ( ) ;
const infectedModules = new Set ( ) ;
let statNew = 0 ;
let statChanged = 0 ;
let statUnchanged = 0 ;
2021-09-29 15:09:42 +08:00
let statReferencesChanged = 0 ;
2021-10-05 20:52:44 +08:00
let statWithoutBuild = 0 ;
2021-09-29 15:09:42 +08:00
2024-02-22 22:20:17 +08:00
/ * *
* @ param { Module } module module
* @ returns { References | undefined } references
* /
2021-09-29 15:09:42 +08:00
const computeReferences = module => {
2024-02-22 22:20:17 +08:00
/** @type {References | undefined} */
2021-09-29 15:09:42 +08:00
let references = undefined ;
for ( const connection of moduleGraph . getOutgoingConnections ( module ) ) {
const d = connection . dependency ;
const m = connection . module ;
if ( ! d || ! m || unsafeCacheDependencies . has ( d ) ) continue ;
if ( references === undefined ) references = new WeakMap ( ) ;
references . set ( d , m ) ;
}
return references ;
} ;
/ * *
* @ param { Module } module the module
2024-02-22 22:20:17 +08:00
* @ param { References | undefined } references references
2021-09-29 15:09:42 +08:00
* @ returns { boolean } true , when the references differ
* /
const compareReferences = ( module , references ) => {
if ( references === undefined ) return true ;
for ( const connection of moduleGraph . getOutgoingConnections ( module ) ) {
const d = connection . dependency ;
if ( ! d ) continue ;
const entry = references . get ( d ) ;
if ( entry === undefined ) continue ;
if ( entry !== connection . module ) return false ;
}
return true ;
} ;
2021-10-05 19:08:21 +08:00
const modulesWithoutCache = new Set ( modules ) ;
for ( const [ module , cachedMemCache ] of moduleMemCacheCache ) {
if ( modulesWithoutCache . has ( module ) ) {
2021-10-05 20:52:44 +08:00
const buildInfo = module . buildInfo ;
if ( buildInfo ) {
if ( cachedMemCache . buildInfo !== buildInfo ) {
2021-10-05 19:08:21 +08:00
// use a new one
const memCache = new WeakTupleMap ( ) ;
moduleMemCaches . set ( module , memCache ) ;
affectedModules . add ( module ) ;
2021-10-05 20:52:44 +08:00
cachedMemCache . buildInfo = buildInfo ;
2021-10-05 19:08:21 +08:00
cachedMemCache . references = computeReferences ( module ) ;
cachedMemCache . memCache = memCache ;
statChanged ++ ;
} else if ( ! compareReferences ( module , cachedMemCache . references ) ) {
// use a new one
const memCache = new WeakTupleMap ( ) ;
moduleMemCaches . set ( module , memCache ) ;
affectedModules . add ( module ) ;
cachedMemCache . references = computeReferences ( module ) ;
cachedMemCache . memCache = memCache ;
statReferencesChanged ++ ;
} else {
// keep the old mem cache
moduleMemCaches . set ( module , cachedMemCache . memCache ) ;
statUnchanged ++ ;
}
2021-09-29 15:09:42 +08:00
} else {
2021-10-05 19:08:21 +08:00
infectedModules . add ( module ) ;
moduleMemCacheCache . delete ( module ) ;
2021-10-05 20:52:44 +08:00
statWithoutBuild ++ ;
2021-09-24 17:35:28 +08:00
}
2021-10-05 19:08:21 +08:00
modulesWithoutCache . delete ( module ) ;
} else {
moduleMemCacheCache . delete ( module ) ;
}
}
for ( const module of modulesWithoutCache ) {
2021-10-06 02:14:21 +08:00
const buildInfo = module . buildInfo ;
2021-10-05 20:52:44 +08:00
if ( buildInfo ) {
2021-10-05 19:08:21 +08:00
// create a new entry
const memCache = new WeakTupleMap ( ) ;
moduleMemCacheCache . set ( module , {
2021-10-05 20:52:44 +08:00
buildInfo ,
2021-10-05 19:08:21 +08:00
references : computeReferences ( module ) ,
memCache
} ) ;
moduleMemCaches . set ( module , memCache ) ;
affectedModules . add ( module ) ;
statNew ++ ;
2021-09-24 17:35:28 +08:00
} else {
infectedModules . add ( module ) ;
2021-10-05 20:52:44 +08:00
statWithoutBuild ++ ;
2021-09-24 17:35:28 +08:00
}
}
2021-10-05 19:08:21 +08:00
2024-02-22 22:20:17 +08:00
/ * *
* @ param { readonly ModuleGraphConnection [ ] } connections connections
* @ returns { symbol | boolean } result
* /
2021-09-27 22:43:34 +08:00
const reduceAffectType = connections => {
let affected = false ;
for ( const { dependency } of connections ) {
if ( ! dependency ) continue ;
const type = dependency . couldAffectReferencingModule ( ) ;
if ( type === Dependency . TRANSITIVE ) return Dependency . TRANSITIVE ;
if ( type === false ) continue ;
affected = true ;
}
return affected ;
} ;
const directOnlyInfectedModules = new Set ( ) ;
2021-09-24 17:35:28 +08:00
for ( const module of infectedModules ) {
2021-09-27 22:43:34 +08:00
for ( const [
referencingModule ,
connections
] of moduleGraph . getIncomingConnectionsByOriginModule ( module ) ) {
if ( ! referencingModule ) continue ;
2021-09-24 17:35:28 +08:00
if ( infectedModules . has ( referencingModule ) ) continue ;
2021-09-27 22:43:34 +08:00
const type = reduceAffectType ( connections ) ;
if ( ! type ) continue ;
if ( type === true ) {
directOnlyInfectedModules . add ( referencingModule ) ;
} else {
infectedModules . add ( referencingModule ) ;
}
2021-09-24 17:35:28 +08:00
}
}
2021-09-27 22:43:34 +08:00
for ( const module of directOnlyInfectedModules ) infectedModules . add ( module ) ;
const directOnlyAffectModules = new Set ( ) ;
2021-09-24 17:35:28 +08:00
for ( const module of affectedModules ) {
2021-09-27 22:43:34 +08:00
for ( const [
referencingModule ,
connections
] of moduleGraph . getIncomingConnectionsByOriginModule ( module ) ) {
2021-09-24 17:35:28 +08:00
if ( ! referencingModule ) continue ;
if ( infectedModules . has ( referencingModule ) ) continue ;
if ( affectedModules . has ( referencingModule ) ) continue ;
2021-09-27 22:43:34 +08:00
const type = reduceAffectType ( connections ) ;
if ( ! type ) continue ;
if ( type === true ) {
directOnlyAffectModules . add ( referencingModule ) ;
} else {
affectedModules . add ( referencingModule ) ;
}
2021-09-27 22:41:26 +08:00
const memCache = new WeakTupleMap ( ) ;
2021-09-29 05:52:25 +08:00
const cache = moduleMemCacheCache . get ( referencingModule ) ;
2021-09-27 22:41:26 +08:00
cache . memCache = memCache ;
2021-09-24 17:35:28 +08:00
moduleMemCaches . set ( referencingModule , memCache ) ;
}
}
2021-09-27 22:43:34 +08:00
for ( const module of directOnlyAffectModules ) affectedModules . add ( module ) ;
2021-09-24 17:35:28 +08:00
this . logger . log (
` ${ Math . round (
( 100 * ( affectedModules . size + infectedModules . size ) ) /
this . modules . size
) } % ( $ { affectedModules . size } affected + $ {
infectedModules . size
} infected of $ {
this . modules . size
2021-10-05 20:52:44 +08:00
} ) modules flagged as affected ( $ { statNew } new modules , $ { statChanged } changed , $ { statReferencesChanged } references changed , $ { statUnchanged } unchanged , $ { statWithoutBuild } were not built ) `
2021-09-24 17:35:28 +08:00
) ;
}
2021-10-06 15:44:26 +08:00
_computeAffectedModulesWithChunkGraph ( ) {
2021-10-05 19:08:21 +08:00
const { moduleMemCaches } = this ;
if ( ! moduleMemCaches ) return ;
const moduleMemCaches2 = ( this . moduleMemCaches2 = new Map ( ) ) ;
const { moduleGraph , chunkGraph } = this ;
const key = "memCache2" ;
2021-10-06 02:14:21 +08:00
let statUnchanged = 0 ;
let statChanged = 0 ;
let statNew = 0 ;
2021-10-05 19:08:21 +08:00
/ * *
* @ param { Module } module module
2024-03-14 23:15:13 +08:00
* @ returns { { id : string | number , modules ? : Map < Module , string | number | undefined > , blocks ? : ( string | number | null ) [ ] } } references
2021-10-05 19:08:21 +08:00
* /
const computeReferences = module => {
2021-11-09 17:42:40 +08:00
const id = chunkGraph . getModuleId ( module ) ;
2024-03-14 23:15:13 +08:00
/** @type {Map<Module, string | number | undefined> | undefined} */
2021-10-05 19:08:21 +08:00
let modules = undefined ;
2024-03-14 23:15:13 +08:00
/** @type {(string | number | null)[] | undefined} */
2021-10-05 19:08:21 +08:00
let blocks = undefined ;
const outgoing = moduleGraph . getOutgoingConnectionsByModule ( module ) ;
if ( outgoing !== undefined ) {
for ( const m of outgoing . keys ( ) ) {
if ( ! m ) continue ;
if ( modules === undefined ) modules = new Map ( ) ;
2021-10-06 02:14:21 +08:00
modules . set ( m , chunkGraph . getModuleId ( m ) ) ;
2021-10-05 19:08:21 +08:00
}
}
if ( module . blocks . length > 0 ) {
blocks = [ ] ;
const queue = Array . from ( module . blocks ) ;
for ( const block of queue ) {
const chunkGroup = chunkGraph . getBlockChunkGroup ( block ) ;
if ( chunkGroup ) {
for ( const chunk of chunkGroup . chunks ) {
blocks . push ( chunk . id ) ;
}
} else {
blocks . push ( null ) ;
}
queue . push . apply ( queue , block . blocks ) ;
}
}
2021-11-09 17:42:40 +08:00
return { id , modules , blocks } ;
2021-10-05 19:08:21 +08:00
} ;
/ * *
* @ param { Module } module module
2024-06-11 21:09:50 +08:00
* @ param { object } references references
2021-11-09 17:42:40 +08:00
* @ param { string | number } references . id id
2024-03-14 23:15:13 +08:00
* @ param { Map < Module , string | number | undefined >= } references . modules modules
* @ param { ( string | number | null ) [ ] = } references . blocks blocks
2021-10-05 19:08:21 +08:00
* @ returns { boolean } ok ?
* /
2021-11-09 17:42:40 +08:00
const compareReferences = ( module , { id , modules , blocks } ) => {
if ( id !== chunkGraph . getModuleId ( module ) ) return false ;
2021-10-05 19:08:21 +08:00
if ( modules !== undefined ) {
for ( const [ module , id ] of modules ) {
if ( chunkGraph . getModuleId ( module ) !== id ) return false ;
}
}
if ( blocks !== undefined ) {
const queue = Array . from ( module . blocks ) ;
let i = 0 ;
for ( const block of queue ) {
const chunkGroup = chunkGraph . getBlockChunkGroup ( block ) ;
if ( chunkGroup ) {
for ( const chunk of chunkGroup . chunks ) {
if ( i >= blocks . length || blocks [ i ++ ] !== chunk . id ) return false ;
}
} else {
if ( i >= blocks . length || blocks [ i ++ ] !== null ) return false ;
}
queue . push . apply ( queue , block . blocks ) ;
}
if ( i !== blocks . length ) return false ;
}
return true ;
} ;
for ( const [ module , memCache ] of moduleMemCaches ) {
2024-03-14 23:15:13 +08:00
/** @type {{ references: { id: string | number, modules?: Map<Module, string | number | undefined>, blocks?: (string | number | null)[]}, memCache: WeakTupleMap<any[], any> }} */
2021-10-05 19:08:21 +08:00
const cache = memCache . get ( key ) ;
if ( cache === undefined ) {
const memCache2 = new WeakTupleMap ( ) ;
memCache . set ( key , {
references : computeReferences ( module ) ,
memCache : memCache2
} ) ;
moduleMemCaches2 . set ( module , memCache2 ) ;
2021-10-06 02:14:21 +08:00
statNew ++ ;
2021-10-05 19:08:21 +08:00
} else if ( ! compareReferences ( module , cache . references ) ) {
const memCache = new WeakTupleMap ( ) ;
cache . references = computeReferences ( module ) ;
cache . memCache = memCache ;
moduleMemCaches2 . set ( module , memCache ) ;
2021-10-06 02:14:21 +08:00
statChanged ++ ;
2021-10-05 19:08:21 +08:00
} else {
moduleMemCaches2 . set ( module , cache . memCache ) ;
2021-10-06 02:14:21 +08:00
statUnchanged ++ ;
2021-10-05 19:08:21 +08:00
}
}
2021-10-06 02:14:21 +08:00
this . logger . log (
` ${ Math . round (
( 100 * statChanged ) / ( statNew + statChanged + statUnchanged )
) } % modules flagged as affected by chunk graph ( $ { statNew } new modules , $ { statChanged } changed , $ { statUnchanged } unchanged ) `
) ;
2021-10-05 19:08:21 +08:00
}
2024-02-21 22:05:29 +08:00
/ * *
* @ param { Callback } callback callback
* /
2018-12-30 21:54:47 +08:00
finish ( callback ) {
2021-06-17 16:09:48 +08:00
this . factorizeQueue . clear ( ) ;
2021-02-02 08:22:19 +08:00
if ( this . profile ) {
this . logger . time ( "finish module profiles" ) ;
const ParallelismFactorCalculator = require ( "./util/ParallelismFactorCalculator" ) ;
const p = new ParallelismFactorCalculator ( ) ;
const moduleGraph = this . moduleGraph ;
2024-03-18 01:15:44 +08:00
/** @type {Map<Module, ModuleProfile>} */
2021-02-02 08:22:19 +08:00
const modulesWithProfiles = new Map ( ) ;
for ( const module of this . modules ) {
const profile = moduleGraph . getProfile ( module ) ;
if ( ! profile ) continue ;
modulesWithProfiles . set ( module , profile ) ;
p . range (
profile . buildingStartTime ,
profile . buildingEndTime ,
f => ( profile . buildingParallelismFactor = f )
) ;
p . range (
profile . factoryStartTime ,
profile . factoryEndTime ,
f => ( profile . factoryParallelismFactor = f )
) ;
p . range (
profile . integrationStartTime ,
profile . integrationEndTime ,
f => ( profile . integrationParallelismFactor = f )
) ;
p . range (
profile . storingStartTime ,
profile . storingEndTime ,
f => ( profile . storingParallelismFactor = f )
) ;
p . range (
profile . restoringStartTime ,
profile . restoringEndTime ,
f => ( profile . restoringParallelismFactor = f )
) ;
if ( profile . additionalFactoryTimes ) {
for ( const { start , end } of profile . additionalFactoryTimes ) {
const influence = ( end - start ) / profile . additionalFactories ;
p . range (
start ,
end ,
f =>
( profile . additionalFactoriesParallelismFactor += f * influence )
) ;
}
}
}
p . calculate ( ) ;
const logger = this . getLogger ( "webpack.Compilation.ModuleProfile" ) ;
2023-05-01 04:06:02 +08:00
// Avoid coverage problems due indirect changes
/* istanbul ignore next */
2021-02-02 08:22:19 +08:00
const logByValue = ( value , msg ) => {
if ( value > 1000 ) {
logger . error ( msg ) ;
} else if ( value > 500 ) {
logger . warn ( msg ) ;
} else if ( value > 200 ) {
logger . info ( msg ) ;
} else if ( value > 30 ) {
logger . log ( msg ) ;
} else {
logger . debug ( msg ) ;
}
} ;
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } category a category
* @ param { ( profile : ModuleProfile ) => number } getDuration get duration callback
* @ param { ( profile : ModuleProfile ) => number } getParallelism get parallelism callback
* /
2021-02-02 08:22:19 +08:00
const logNormalSummary = ( category , getDuration , getParallelism ) => {
let sum = 0 ;
let max = 0 ;
for ( const [ module , profile ] of modulesWithProfiles ) {
const p = getParallelism ( profile ) ;
const d = getDuration ( profile ) ;
if ( d === 0 || p === 0 ) continue ;
const t = d / p ;
sum += t ;
if ( t <= 10 ) continue ;
logByValue (
t ,
` | ${ Math . round ( t ) } ms ${
p >= 1.1 ? ` (parallelism ${ Math . round ( p * 10 ) / 10 } ) ` : ""
} $ { category } > $ { module . readableIdentifier ( this . requestShortener ) } `
) ;
max = Math . max ( max , t ) ;
}
if ( sum <= 10 ) return ;
logByValue (
Math . max ( sum / 10 , max ) ,
` ${ Math . round ( sum ) } ms ${ category } `
) ;
} ;
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } category a category
* @ param { ( profile : ModuleProfile ) => number } getDuration get duration callback
* @ param { ( profile : ModuleProfile ) => number } getParallelism get parallelism callback
* /
2021-02-02 08:22:19 +08:00
const logByLoadersSummary = ( category , getDuration , getParallelism ) => {
const map = new Map ( ) ;
for ( const [ module , profile ] of modulesWithProfiles ) {
2023-04-26 04:45:43 +08:00
const list = getOrInsert (
2021-02-02 08:22:19 +08:00
map ,
module . type + "!" + module . identifier ( ) . replace ( /(!|^)[^!]*$/ , "" ) ,
( ) => [ ]
) ;
list . push ( { module , profile } ) ;
}
let sum = 0 ;
let max = 0 ;
for ( const [ key , modules ] of map ) {
let innerSum = 0 ;
let innerMax = 0 ;
for ( const { module , profile } of modules ) {
const p = getParallelism ( profile ) ;
const d = getDuration ( profile ) ;
if ( d === 0 || p === 0 ) continue ;
const t = d / p ;
innerSum += t ;
if ( t <= 10 ) continue ;
logByValue (
t ,
` | | ${ Math . round ( t ) } ms ${
p >= 1.1 ? ` (parallelism ${ Math . round ( p * 10 ) / 10 } ) ` : ""
} $ { category } > $ { module . readableIdentifier (
this . requestShortener
) } `
) ;
innerMax = Math . max ( innerMax , t ) ;
}
sum += innerSum ;
if ( innerSum <= 10 ) continue ;
const idx = key . indexOf ( "!" ) ;
const loaders = key . slice ( idx + 1 ) ;
const moduleType = key . slice ( 0 , idx ) ;
const t = Math . max ( innerSum / 10 , innerMax ) ;
logByValue (
t ,
` | ${ Math . round ( innerSum ) } ms ${ category } > ${
loaders
? ` ${
modules . length
2024-01-14 09:41:34 +08:00
} x $ { moduleType } with $ { this . requestShortener . shorten (
2021-02-02 08:22:19 +08:00
loaders
2024-01-14 09:41:34 +08:00
) } `
2021-02-02 08:22:19 +08:00
: ` ${ modules . length } x ${ moduleType } `
} `
) ;
max = Math . max ( max , t ) ;
}
if ( sum <= 10 ) return ;
logByValue (
Math . max ( sum / 10 , max ) ,
` ${ Math . round ( sum ) } ms ${ category } `
) ;
} ;
logNormalSummary (
"resolve to new modules" ,
p => p . factory ,
p => p . factoryParallelismFactor
) ;
logNormalSummary (
"resolve to existing modules" ,
p => p . additionalFactories ,
p => p . additionalFactoriesParallelismFactor
) ;
logNormalSummary (
"integrate modules" ,
p => p . restoring ,
p => p . restoringParallelismFactor
) ;
logByLoadersSummary (
"build modules" ,
p => p . building ,
p => p . buildingParallelismFactor
) ;
logNormalSummary (
"store modules" ,
p => p . storing ,
p => p . storingParallelismFactor
) ;
logNormalSummary (
"restore modules" ,
p => p . restoring ,
p => p . restoringParallelismFactor
) ;
this . logger . timeEnd ( "finish module profiles" ) ;
}
2021-09-24 17:35:28 +08:00
this . logger . time ( "compute affected modules" ) ;
this . _computeAffectedModules ( this . modules ) ;
this . logger . timeEnd ( "compute affected modules" ) ;
2020-01-30 18:34:33 +08:00
this . logger . time ( "finish modules" ) ;
2021-09-24 17:35:28 +08:00
const { modules , moduleMemCaches } = this ;
2018-12-30 21:54:47 +08:00
this . hooks . finishModules . callAsync ( modules , err => {
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "finish modules" ) ;
2024-02-21 22:55:02 +08:00
if ( err ) return callback ( /** @type {WebpackError} */ ( err ) ) ;
2018-12-30 21:54:47 +08:00
// extract warnings and errors from modules
2021-09-27 23:21:09 +08:00
this . moduleGraph . freeze ( "dependency errors" ) ;
2021-09-24 17:35:28 +08:00
// TODO keep a cacheToken (= {}) for each module in the graph
// create a new one per compilation and flag all updated files
// and parents with it
this . logger . time ( "report dependency errors and warnings" ) ;
2018-12-30 21:54:47 +08:00
for ( const module of modules ) {
2021-09-24 17:35:28 +08:00
// TODO only run for modules with changed cacheToken
// global WeakMap<CacheToken, WeakSet<Module>> to keep modules without errors/warnings
const memCache = moduleMemCaches && moduleMemCaches . get ( module ) ;
2021-09-27 22:41:26 +08:00
if ( memCache && memCache . get ( "noWarningsOrErrors" ) ) continue ;
2021-09-24 17:35:28 +08:00
let hasProblems = this . reportDependencyErrorsAndWarnings ( module , [
module
] ) ;
2019-11-08 19:43:05 +08:00
const errors = module . getErrors ( ) ;
if ( errors !== undefined ) {
2020-08-15 01:54:21 +08:00
for ( const error of errors ) {
if ( ! error . module ) {
error . module = module ;
2018-12-30 21:54:47 +08:00
}
2020-08-15 01:54:21 +08:00
this . errors . push ( error ) ;
2021-09-24 17:35:28 +08:00
hasProblems = true ;
2018-09-07 20:11:48 +08:00
}
}
2019-11-08 19:43:05 +08:00
const warnings = module . getWarnings ( ) ;
if ( warnings !== undefined ) {
for ( const warning of warnings ) {
if ( ! warning . module ) {
warning . module = module ;
}
this . warnings . push ( warning ) ;
2021-09-24 17:35:28 +08:00
hasProblems = true ;
2018-12-30 21:54:47 +08:00
}
2018-09-07 20:11:48 +08:00
}
2021-09-27 22:41:26 +08:00
if ( ! hasProblems && memCache ) memCache . set ( "noWarningsOrErrors" , true ) ;
2018-09-07 20:11:48 +08:00
}
2021-04-13 23:33:05 +08:00
this . moduleGraph . unfreeze ( ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "report dependency errors and warnings" ) ;
2018-12-30 21:54:47 +08:00
callback ( ) ;
} ) ;
2017-01-06 01:00:36 +08:00
}
2013-05-13 19:34:00 +08:00
2017-01-06 01:00:36 +08:00
unseal ( ) {
2017-11-27 22:27:30 +08:00
this . hooks . unseal . call ( ) ;
2018-09-06 22:59:11 +08:00
this . chunks . clear ( ) ;
2018-01-20 00:06:59 +08:00
this . chunkGroups . length = 0 ;
this . namedChunks . clear ( ) ;
this . namedChunkGroups . clear ( ) ;
2018-09-05 20:22:10 +08:00
this . entrypoints . clear ( ) ;
2017-01-06 01:00:36 +08:00
this . additionalChunkAssets . length = 0 ;
this . assets = { } ;
2019-09-11 17:13:46 +08:00
this . assetsInfo . clear ( ) ;
2018-08-21 22:12:00 +08:00
this . moduleGraph . removeAllModuleAttributes ( ) ;
2021-04-13 23:33:05 +08:00
this . moduleGraph . unfreeze ( ) ;
2021-10-05 19:08:21 +08:00
this . moduleMemCaches2 = undefined ;
2014-07-29 06:13:25 +08:00
}
2015-07-08 20:15:21 +08:00
2018-05-04 00:57:02 +08:00
/ * *
2018-12-10 18:34:59 +08:00
* @ param { Callback } callback signals when the call finishes
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2017-01-06 01:00:36 +08:00
seal ( callback ) {
2021-06-17 16:09:48 +08:00
const finalCallback = err => {
this . factorizeQueue . clear ( ) ;
this . buildQueue . clear ( ) ;
this . rebuildQueue . clear ( ) ;
this . processDependenciesQueue . clear ( ) ;
this . addModuleQueue . clear ( ) ;
return callback ( err ) ;
} ;
2021-09-22 18:12:46 +08:00
const chunkGraph = new ChunkGraph (
this . moduleGraph ,
this . outputOptions . hashFunction
) ;
2018-08-14 17:18:22 +08:00
this . chunkGraph = chunkGraph ;
2021-11-05 16:53:32 +08:00
if ( this . _backCompat ) {
for ( const module of this . modules ) {
ChunkGraph . setChunkGraphForModule ( module , chunkGraph ) ;
}
2018-08-21 22:15:48 +08:00
}
2017-11-27 22:27:30 +08:00
this . hooks . seal . call ( ) ;
2017-08-08 15:40:17 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "optimize dependencies" ) ;
2018-07-31 04:30:27 +08:00
while ( this . hooks . optimizeDependencies . call ( this . modules ) ) {
2018-02-25 09:00:20 +08:00
/* empty */
}
2017-11-27 22:27:30 +08:00
this . hooks . afterOptimizeDependencies . call ( this . modules ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "optimize dependencies" ) ;
2017-08-08 15:40:17 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "create chunks" ) ;
2018-07-02 22:18:49 +08:00
this . hooks . beforeChunks . call ( ) ;
2021-09-27 23:21:09 +08:00
this . moduleGraph . freeze ( "seal" ) ;
2021-03-09 03:18:49 +08:00
/** @type {Map<Entrypoint, Module[]>} */
2020-05-23 22:08:51 +08:00
const chunkGraphInit = new Map ( ) ;
for ( const [ name , { dependencies , includeDependencies , options } ] of this
. entries ) {
2018-01-20 00:06:59 +08:00
const chunk = this . addChunk ( name ) ;
2020-02-07 18:00:25 +08:00
if ( options . filename ) {
chunk . filenameTemplate = options . filename ;
}
2020-09-08 00:02:14 +08:00
const entrypoint = new Entrypoint ( options ) ;
2020-07-21 16:22:10 +08:00
if ( ! options . dependOn && ! options . runtime ) {
entrypoint . setRuntimeChunk ( chunk ) ;
}
entrypoint . setEntrypointChunk ( chunk ) ;
2018-01-20 00:06:59 +08:00
this . namedChunkGroups . set ( name , entrypoint ) ;
this . entrypoints . set ( name , entrypoint ) ;
this . chunkGroups . push ( entrypoint ) ;
2018-07-27 04:43:20 +08:00
connectChunkGroupAndChunk ( entrypoint , chunk ) ;
2018-01-20 00:06:59 +08:00
2021-10-07 22:13:42 +08:00
const entryModules = new Set ( ) ;
2020-05-23 22:08:51 +08:00
for ( const dep of [ ... this . globalEntry . dependencies , ... dependencies ] ) {
2020-05-05 16:43:18 +08:00
entrypoint . addOrigin ( null , { name } , /** @type {any} */ ( dep ) . request ) ;
2018-01-20 00:06:59 +08:00
2018-08-14 22:40:37 +08:00
const module = this . moduleGraph . getModule ( dep ) ;
if ( module ) {
chunkGraph . connectChunkAndEntryModule ( chunk , module , entrypoint ) ;
2021-10-07 22:13:42 +08:00
entryModules . add ( module ) ;
2020-05-23 22:08:51 +08:00
const modulesList = chunkGraphInit . get ( entrypoint ) ;
if ( modulesList === undefined ) {
chunkGraphInit . set ( entrypoint , [ module ] ) ;
} else {
modulesList . push ( module ) ;
}
}
}
2021-10-07 22:13:42 +08:00
this . assignDepths ( entryModules ) ;
2020-07-02 19:13:13 +08:00
const mapAndSort = deps =>
deps
. map ( dep => this . moduleGraph . getModule ( dep ) )
. filter ( Boolean )
. sort ( compareModulesByIdentifier ) ;
const includedModules = [
... mapAndSort ( this . globalEntry . includeDependencies ) ,
... mapAndSort ( includeDependencies )
] ;
2021-02-10 22:40:11 +08:00
let modulesList = chunkGraphInit . get ( entrypoint ) ;
if ( modulesList === undefined ) {
chunkGraphInit . set ( entrypoint , ( modulesList = [ ] ) ) ;
}
2020-07-02 19:13:13 +08:00
for ( const module of includedModules ) {
this . assignDepth ( module ) ;
2021-02-10 22:40:11 +08:00
modulesList . push ( module ) ;
2018-08-14 22:40:37 +08:00
}
2018-01-22 20:52:43 +08:00
}
2020-07-31 21:14:49 +08:00
const runtimeChunks = new Set ( ) ;
outer : for ( const [
2020-02-07 17:05:51 +08:00
name ,
{
2020-07-21 16:22:10 +08:00
options : { dependOn , runtime }
2020-02-07 17:05:51 +08:00
}
] of this . entries ) {
2020-07-31 21:14:49 +08:00
if ( dependOn && runtime ) {
2021-05-11 15:31:46 +08:00
const err =
new WebpackError ( ` Entrypoint ' ${ name } ' has 'dependOn' and 'runtime' specified. This is not valid.
2020-07-31 21:14:49 +08:00
Entrypoints that depend on other entrypoints do not have their own runtime .
They will use the runtime ( s ) from referenced entrypoints instead .
Remove the 'runtime' option from the entrypoint . ` );
2024-02-22 22:20:17 +08:00
const entry = /** @type {Entrypoint} */ ( this . entrypoints . get ( name ) ) ;
2020-07-31 21:14:49 +08:00
err . chunk = entry . getEntrypointChunk ( ) ;
this . errors . push ( err ) ;
}
2020-02-07 17:05:51 +08:00
if ( dependOn ) {
2024-02-22 22:20:17 +08:00
const entry = /** @type {Entrypoint} */ ( this . entrypoints . get ( name ) ) ;
2020-07-31 21:14:49 +08:00
const referencedChunks = entry
. getEntrypointChunk ( )
. getAllReferencedChunks ( ) ;
const dependOnEntries = [ ] ;
2020-02-07 17:05:51 +08:00
for ( const dep of dependOn ) {
const dependency = this . entrypoints . get ( dep ) ;
if ( ! dependency ) {
throw new Error (
` Entry ${ name } depends on ${ dep } , but this entry was not found `
) ;
}
2020-07-31 21:14:49 +08:00
if ( referencedChunks . has ( dependency . getEntrypointChunk ( ) ) ) {
const err = new WebpackError (
` Entrypoints ' ${ name } ' and ' ${ dep } ' use 'dependOn' to depend on each other in a circular way. `
) ;
const entryChunk = entry . getEntrypointChunk ( ) ;
err . chunk = entryChunk ;
this . errors . push ( err ) ;
entry . setRuntimeChunk ( entryChunk ) ;
continue outer ;
}
dependOnEntries . push ( dependency ) ;
}
for ( const dependency of dependOnEntries ) {
2020-02-07 17:05:51 +08:00
connectChunkGroupParentAndChild ( dependency , entry ) ;
}
2020-07-21 16:22:10 +08:00
} else if ( runtime ) {
2024-02-22 22:20:17 +08:00
const entry = /** @type {Entrypoint} */ ( this . entrypoints . get ( name ) ) ;
2020-07-31 21:14:49 +08:00
let chunk = this . namedChunks . get ( runtime ) ;
if ( chunk ) {
if ( ! runtimeChunks . has ( chunk ) ) {
2021-05-11 15:31:46 +08:00
const err =
new WebpackError ( ` Entrypoint ' ${ name } ' has a 'runtime' option which points to another entrypoint named ' ${ runtime } '.
2020-07-31 21:14:49 +08:00
It ' s not valid to use other entrypoints as runtime chunk .
Did you mean to use ' dependOn : $ { JSON . stringify (
2021-05-11 15:31:46 +08:00
runtime
) } ' instead to allow using entrypoint ' $ { name } ' within the runtime of entrypoint ' $ { runtime } '? For this ' $ { runtime } ' must always be loaded when ' $ { name } ' is used .
2020-07-31 21:14:49 +08:00
Or do you want to use the entrypoints '${name}' and '${runtime}' independently on the same page with a shared runtime ? In this case give them both the same value for the 'runtime' option . It must be a name not already used by an entrypoint . ` );
2024-02-22 22:20:17 +08:00
const entryChunk =
/** @type {Chunk} */
( entry . getEntrypointChunk ( ) ) ;
2020-07-31 21:14:49 +08:00
err . chunk = entryChunk ;
this . errors . push ( err ) ;
entry . setRuntimeChunk ( entryChunk ) ;
continue ;
}
} else {
chunk = this . addChunk ( runtime ) ;
chunk . preventIntegration = true ;
runtimeChunks . add ( chunk ) ;
}
2020-07-21 16:22:10 +08:00
entry . unshiftChunk ( chunk ) ;
chunk . addGroup ( entry ) ;
entry . setRuntimeChunk ( chunk ) ;
2020-02-07 17:05:51 +08:00
}
}
2020-05-23 22:08:51 +08:00
buildChunkGraph ( this , chunkGraphInit ) ;
2018-07-02 22:18:49 +08:00
this . hooks . afterChunks . call ( this . chunks ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "create chunks" ) ;
2018-07-02 22:18:49 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "optimize" ) ;
2017-11-27 22:27:30 +08:00
this . hooks . optimize . call ( ) ;
2014-07-19 20:32:48 +08:00
2018-07-31 04:30:27 +08:00
while ( this . hooks . optimizeModules . call ( this . modules ) ) {
2018-02-25 09:00:20 +08:00
/* empty */
}
2017-11-27 22:27:30 +08:00
this . hooks . afterOptimizeModules . call ( this . modules ) ;
2014-01-29 17:13:28 +08:00
2018-07-31 04:30:27 +08:00
while ( this . hooks . optimizeChunks . call ( this . chunks , this . chunkGroups ) ) {
2018-02-25 09:00:20 +08:00
/* empty */
}
2018-01-20 00:06:59 +08:00
this . hooks . afterOptimizeChunks . call ( this . chunks , this . chunkGroups ) ;
2015-04-21 01:39:02 +08:00
2017-11-27 22:27:30 +08:00
this . hooks . optimizeTree . callAsync ( this . chunks , this . modules , err => {
2018-02-25 09:00:20 +08:00
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback (
2019-05-11 03:37:35 +08:00
makeWebpackError ( err , "Compilation.hooks.optimizeTree" )
) ;
2017-01-06 01:00:36 +08:00
}
2014-09-03 20:16:17 +08:00
2017-11-27 22:27:30 +08:00
this . hooks . afterOptimizeTree . call ( this . chunks , this . modules ) ;
2016-07-13 17:03:14 +08:00
2019-12-11 05:58:26 +08:00
this . hooks . optimizeChunkModules . callAsync (
this . chunks ,
this . modules ,
err => {
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback (
2019-12-11 05:58:26 +08:00
makeWebpackError ( err , "Compilation.hooks.optimizeChunkModules" )
) ;
}
2017-05-10 19:15:14 +08:00
2019-12-11 05:58:26 +08:00
this . hooks . afterOptimizeChunkModules . call ( this . chunks , this . modules ) ;
2016-07-13 17:03:14 +08:00
2019-12-11 05:58:26 +08:00
const shouldRecord = this . hooks . shouldRecord . call ( ) !== false ;
2016-07-13 17:03:14 +08:00
2019-12-11 05:58:26 +08:00
this . hooks . reviveModules . call ( this . modules , this . records ) ;
this . hooks . beforeModuleIds . call ( this . modules ) ;
this . hooks . moduleIds . call ( this . modules ) ;
this . hooks . optimizeModuleIds . call ( this . modules ) ;
this . hooks . afterOptimizeModuleIds . call ( this . modules ) ;
2014-01-29 17:13:28 +08:00
2019-12-11 05:58:26 +08:00
this . hooks . reviveChunks . call ( this . chunks , this . records ) ;
this . hooks . beforeChunkIds . call ( this . chunks ) ;
this . hooks . chunkIds . call ( this . chunks ) ;
this . hooks . optimizeChunkIds . call ( this . chunks ) ;
this . hooks . afterOptimizeChunkIds . call ( this . chunks ) ;
2016-07-13 17:03:14 +08:00
2020-10-23 20:52:23 +08:00
this . assignRuntimeIds ( ) ;
2021-10-06 15:44:26 +08:00
this . logger . time ( "compute affected modules with chunk graph" ) ;
this . _computeAffectedModulesWithChunkGraph ( ) ;
this . logger . timeEnd ( "compute affected modules with chunk graph" ) ;
2021-10-05 19:08:21 +08:00
2019-12-11 05:58:26 +08:00
this . sortItemsWithChunkIds ( ) ;
2016-07-13 17:03:14 +08:00
2019-12-11 05:58:26 +08:00
if ( shouldRecord ) {
this . hooks . recordModules . call ( this . modules , this . records ) ;
this . hooks . recordChunks . call ( this . chunks , this . records ) ;
}
2019-01-28 17:40:32 +08:00
2019-12-11 05:58:26 +08:00
this . hooks . optimizeCodeGeneration . call ( this . modules ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "optimize" ) ;
2018-11-15 00:31:32 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "module hashing" ) ;
2019-12-11 05:58:26 +08:00
this . hooks . beforeModuleHash . call ( ) ;
this . createModuleHashes ( ) ;
this . hooks . afterModuleHash . call ( ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "module hashing" ) ;
2019-10-09 04:29:46 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "code generation" ) ;
2019-12-11 05:58:26 +08:00
this . hooks . beforeCodeGeneration . call ( ) ;
2020-07-28 00:09:48 +08:00
this . codeGeneration ( err => {
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback ( err ) ;
2020-07-28 00:09:48 +08:00
}
this . hooks . afterCodeGeneration . call ( ) ;
this . logger . timeEnd ( "code generation" ) ;
this . logger . time ( "runtime requirements" ) ;
this . hooks . beforeRuntimeRequirements . call ( ) ;
2020-09-08 00:02:14 +08:00
this . processRuntimeRequirements ( ) ;
2020-07-28 00:09:48 +08:00
this . hooks . afterRuntimeRequirements . call ( ) ;
this . logger . timeEnd ( "runtime requirements" ) ;
this . logger . time ( "hashing" ) ;
this . hooks . beforeHash . call ( ) ;
2021-01-26 07:48:37 +08:00
const codeGenerationJobs = this . createHash ( ) ;
2020-07-28 00:09:48 +08:00
this . hooks . afterHash . call ( ) ;
this . logger . timeEnd ( "hashing" ) ;
2021-01-26 07:48:37 +08:00
this . _runCodeGenerationJobs ( codeGenerationJobs , err => {
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback ( err ) ;
2021-01-26 07:48:37 +08:00
}
2019-07-17 23:30:25 +08:00
2021-01-26 07:48:37 +08:00
if ( shouldRecord ) {
this . logger . time ( "record hash" ) ;
this . hooks . recordHash . call ( this . records ) ;
this . logger . timeEnd ( "record hash" ) ;
}
2017-01-06 01:00:36 +08:00
2021-01-26 07:48:37 +08:00
this . logger . time ( "module assets" ) ;
this . clearAssets ( ) ;
2018-09-27 13:22:19 +08:00
2021-01-26 07:48:37 +08:00
this . hooks . beforeModuleAssets . call ( ) ;
this . createModuleAssets ( ) ;
this . logger . timeEnd ( "module assets" ) ;
2020-05-12 18:16:51 +08:00
2021-01-26 07:48:37 +08:00
const cont = ( ) => {
this . logger . time ( "process assets" ) ;
this . hooks . processAssets . callAsync ( this . assets , err => {
2020-08-25 00:32:34 +08:00
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback (
2021-01-26 07:48:37 +08:00
makeWebpackError ( err , "Compilation.hooks.processAssets" )
2020-08-25 00:32:34 +08:00
) ;
}
2021-01-26 07:48:37 +08:00
this . hooks . afterProcessAssets . call ( this . assets ) ;
this . logger . timeEnd ( "process assets" ) ;
2024-03-14 23:15:13 +08:00
this . assets = /** @type {CompilationAssets} */ (
this . _backCompat
? soonFrozenObjectDeprecation (
this . assets ,
"Compilation.assets" ,
"DEP_WEBPACK_COMPILATION_ASSETS" ,
` BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
2021-01-26 07:48:37 +08:00
Do changes to assets earlier , e . g . in Compilation . hooks . processAssets .
Make sure to select an appropriate stage from Compilation . PROCESS _ASSETS _STAGE _ * . `
2024-03-14 23:15:13 +08:00
)
: Object . freeze ( this . assets )
) ;
2021-01-26 07:48:37 +08:00
this . summarizeDependencies ( ) ;
if ( shouldRecord ) {
this . hooks . record . call ( this , this . records ) ;
}
if ( this . hooks . needAdditionalSeal . call ( ) ) {
this . unseal ( ) ;
return this . seal ( callback ) ;
}
return this . hooks . afterSeal . callAsync ( err => {
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback (
2021-01-26 07:48:37 +08:00
makeWebpackError ( err , "Compilation.hooks.afterSeal" )
) ;
}
this . fileSystemInfo . logStatistics ( ) ;
2021-06-17 16:09:48 +08:00
finalCallback ( ) ;
2021-01-26 07:48:37 +08:00
} ) ;
2020-08-21 03:57:44 +08:00
} ) ;
2021-01-26 07:48:37 +08:00
} ;
2018-09-27 13:22:19 +08:00
2021-01-26 07:48:37 +08:00
this . logger . time ( "create chunk assets" ) ;
if ( this . hooks . shouldGenerateChunkAssets . call ( ) !== false ) {
this . hooks . beforeChunkAssets . call ( ) ;
this . createChunkAssets ( err => {
this . logger . timeEnd ( "create chunk assets" ) ;
if ( err ) {
2021-06-17 16:09:48 +08:00
return finalCallback ( err ) ;
2021-01-26 07:48:37 +08:00
}
cont ( ) ;
} ) ;
} else {
2020-07-28 00:09:48 +08:00
this . logger . timeEnd ( "create chunk assets" ) ;
cont ( ) ;
2021-01-26 07:48:37 +08:00
}
} ) ;
2020-07-28 00:09:48 +08:00
} ) ;
2019-12-11 05:58:26 +08:00
}
) ;
2016-10-18 02:26:22 +08:00
} ) ;
2017-01-06 01:00:36 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
2020-03-13 00:51:26 +08:00
* @ param { Module } module module to report from
2018-05-04 00:57:02 +08:00
* @ param { DependenciesBlock [ ] } blocks blocks to report from
2021-09-24 17:35:28 +08:00
* @ returns { boolean } true , when it has warnings or errors
2018-05-04 00:57:02 +08:00
* /
2017-01-10 00:11:34 +08:00
reportDependencyErrorsAndWarnings ( module , blocks ) {
2021-09-24 17:35:28 +08:00
let hasProblems = false ;
2018-02-25 09:00:20 +08:00
for ( let indexBlock = 0 ; indexBlock < blocks . length ; indexBlock ++ ) {
2017-03-02 22:09:09 +08:00
const block = blocks [ indexBlock ] ;
const dependencies = block . dependencies ;
2017-01-24 02:52:20 +08:00
2018-02-25 09:00:20 +08:00
for ( let indexDep = 0 ; indexDep < dependencies . length ; indexDep ++ ) {
2017-03-02 22:09:09 +08:00
const d = dependencies [ indexDep ] ;
2017-01-24 02:52:20 +08:00
2018-07-24 23:35:36 +08:00
const warnings = d . getWarnings ( this . moduleGraph ) ;
2018-02-25 09:00:20 +08:00
if ( warnings ) {
for ( let indexWar = 0 ; indexWar < warnings . length ; indexWar ++ ) {
2017-03-02 22:09:09 +08:00
const w = warnings [ indexWar ] ;
2017-01-24 02:52:20 +08:00
2017-03-02 22:09:09 +08:00
const warning = new ModuleDependencyWarning ( module , w , d . loc ) ;
2017-01-06 01:00:36 +08:00
this . warnings . push ( warning ) ;
2021-09-24 17:35:28 +08:00
hasProblems = true ;
2017-01-24 02:52:20 +08:00
}
2017-01-06 01:00:36 +08:00
}
2018-07-24 23:35:36 +08:00
const errors = d . getErrors ( this . moduleGraph ) ;
2018-02-25 09:00:20 +08:00
if ( errors ) {
for ( let indexErr = 0 ; indexErr < errors . length ; indexErr ++ ) {
2017-03-02 22:09:09 +08:00
const e = errors [ indexErr ] ;
2017-01-24 02:52:20 +08:00
2017-03-02 22:09:09 +08:00
const error = new ModuleDependencyError ( module , e , d . loc ) ;
2017-01-24 02:52:20 +08:00
this . errors . push ( error ) ;
2021-09-24 17:35:28 +08:00
hasProblems = true ;
2017-01-24 02:52:20 +08:00
}
2017-01-10 00:11:34 +08:00
}
2017-01-24 02:52:20 +08:00
}
2021-09-24 17:35:28 +08:00
if ( this . reportDependencyErrorsAndWarnings ( module , block . blocks ) )
hasProblems = true ;
2017-01-24 02:52:20 +08:00
}
2021-09-24 17:35:28 +08:00
return hasProblems ;
2017-01-06 01:00:36 +08:00
}
2024-03-14 02:23:33 +08:00
/ * *
* @ param { Callback } callback callback
* /
2020-07-28 00:09:48 +08:00
codeGeneration ( callback ) {
2021-01-26 07:48:37 +08:00
const { chunkGraph } = this ;
2021-09-22 18:12:46 +08:00
this . codeGenerationResults = new CodeGenerationResults (
this . outputOptions . hashFunction
) ;
2024-03-14 02:23:33 +08:00
/** @type {CodeGenerationJobs} */
2020-07-28 00:09:48 +08:00
const jobs = [ ] ;
2019-10-09 04:29:46 +08:00
for ( const module of this . modules ) {
2020-07-28 00:09:48 +08:00
const runtimes = chunkGraph . getModuleRuntimes ( module ) ;
if ( runtimes . size === 1 ) {
for ( const runtime of runtimes ) {
const hash = chunkGraph . getModuleHash ( module , runtime ) ;
jobs . push ( { module , hash , runtime , runtimes : [ runtime ] } ) ;
}
} else if ( runtimes . size > 1 ) {
2020-07-29 04:05:13 +08:00
/** @type {Map<string, { runtimes: RuntimeSpec[] }>} */
2020-07-28 00:09:48 +08:00
const map = new Map ( ) ;
for ( const runtime of runtimes ) {
const hash = chunkGraph . getModuleHash ( module , runtime ) ;
2020-07-29 04:05:13 +08:00
const job = map . get ( hash ) ;
if ( job === undefined ) {
const newJob = { module , hash , runtime , runtimes : [ runtime ] } ;
jobs . push ( newJob ) ;
map . set ( hash , newJob ) ;
2020-07-28 00:09:48 +08:00
} else {
2020-07-29 04:05:13 +08:00
job . runtimes . push ( runtime ) ;
2020-07-28 00:09:48 +08:00
}
}
2019-10-09 04:29:46 +08:00
}
}
2020-07-28 00:09:48 +08:00
2021-01-26 07:48:37 +08:00
this . _runCodeGenerationJobs ( jobs , callback ) ;
}
2024-03-14 02:23:33 +08:00
/ * *
* @ private
* @ param { CodeGenerationJobs } jobs code generation jobs
* @ param { Callback } callback callback
* @ returns { void }
* /
2021-01-26 07:48:37 +08:00
_runCodeGenerationJobs ( jobs , callback ) {
2022-08-25 00:24:28 +08:00
if ( jobs . length === 0 ) {
return callback ( ) ;
}
2021-01-26 07:48:37 +08:00
let statModulesFromCache = 0 ;
let statModulesGenerated = 0 ;
2021-05-11 15:31:46 +08:00
const { chunkGraph , moduleGraph , dependencyTemplates , runtimeTemplate } =
this ;
2021-01-26 07:48:37 +08:00
const results = this . codeGenerationResults ;
2023-06-17 01:13:03 +08:00
/** @type {WebpackError[]} */
2021-01-26 07:48:37 +08:00
const errors = [ ] ;
2024-03-14 23:15:13 +08:00
/** @type {NotCodeGeneratedModules | undefined} */
2021-11-30 20:46:42 +08:00
let notCodeGeneratedModules = undefined ;
2021-11-30 19:55:51 +08:00
const runIteration = ( ) => {
2024-03-14 02:23:33 +08:00
/** @type {CodeGenerationJobs} */
2021-11-30 20:46:42 +08:00
let delayedJobs = [ ] ;
let delayedModules = new Set ( ) ;
2021-11-30 19:55:51 +08:00
asyncLib . eachLimit (
jobs ,
this . options . parallelism ,
( job , callback ) => {
const { module } = job ;
const { codeGenerationDependencies } = module ;
if ( codeGenerationDependencies !== undefined ) {
if (
notCodeGeneratedModules === undefined ||
codeGenerationDependencies . some ( dep => {
2024-03-14 02:23:33 +08:00
const referencedModule = /** @type {Module} */ (
moduleGraph . getModule ( dep )
) ;
2024-03-14 23:15:13 +08:00
return /** @type {NotCodeGeneratedModules} */ (
notCodeGeneratedModules
) . has ( referencedModule ) ;
2021-11-30 19:55:51 +08:00
} )
) {
delayedJobs . push ( job ) ;
delayedModules . add ( module ) ;
return callback ( ) ;
}
2020-07-28 00:09:48 +08:00
}
2021-11-30 19:55:51 +08:00
const { hash , runtime , runtimes } = job ;
this . _codeGenerationModule (
module ,
runtime ,
runtimes ,
hash ,
dependencyTemplates ,
chunkGraph ,
moduleGraph ,
runtimeTemplate ,
errors ,
results ,
( err , codeGenerated ) => {
if ( codeGenerated ) statModulesGenerated ++ ;
else statModulesFromCache ++ ;
callback ( err ) ;
}
2020-07-28 00:09:48 +08:00
) ;
2021-11-30 19:55:51 +08:00
} ,
err => {
if ( err ) return callback ( err ) ;
if ( delayedJobs . length > 0 ) {
if ( delayedJobs . length === jobs . length ) {
return callback (
2024-03-14 02:23:33 +08:00
/** @type {WebpackError} */ (
new Error (
` Unable to make progress during code generation because of circular code generation dependency: ${ Array . from (
delayedModules ,
m => m . identifier ( )
) . join ( ", " ) } `
)
2021-11-30 19:55:51 +08:00
)
) ;
}
jobs = delayedJobs ;
2021-11-30 20:46:42 +08:00
delayedJobs = [ ] ;
notCodeGeneratedModules = delayedModules ;
delayedModules = new Set ( ) ;
2021-11-30 19:55:51 +08:00
return runIteration ( ) ;
}
if ( errors . length > 0 ) {
errors . sort (
compareSelect ( err => err . module , compareModulesByIdentifier )
) ;
for ( const error of errors ) {
this . errors . push ( error ) ;
}
2020-07-28 00:09:48 +08:00
}
2021-11-30 19:55:51 +08:00
this . logger . log (
` ${ Math . round (
( 100 * statModulesGenerated ) /
( statModulesGenerated + statModulesFromCache )
) } % code generated ( $ { statModulesGenerated } generated , $ { statModulesFromCache } from cache ) `
) ;
callback ( ) ;
2020-07-28 00:09:48 +08:00
}
2021-11-30 19:55:51 +08:00
) ;
} ;
runIteration ( ) ;
2019-10-09 04:29:46 +08:00
}
2021-01-26 07:48:37 +08:00
/ * *
* @ param { Module } module module
* @ param { RuntimeSpec } runtime runtime
* @ param { RuntimeSpec [ ] } runtimes runtimes
* @ param { string } hash hash
* @ param { DependencyTemplates } dependencyTemplates dependencyTemplates
* @ param { ChunkGraph } chunkGraph chunkGraph
* @ param { ModuleGraph } moduleGraph moduleGraph
* @ param { RuntimeTemplate } runtimeTemplate runtimeTemplate
* @ param { WebpackError [ ] } errors errors
* @ param { CodeGenerationResults } results results
2023-06-17 01:13:03 +08:00
* @ param { function ( ( WebpackError | null ) = , boolean = ) : void } callback callback
2021-01-26 07:48:37 +08:00
* /
_codeGenerationModule (
module ,
runtime ,
runtimes ,
hash ,
dependencyTemplates ,
chunkGraph ,
moduleGraph ,
runtimeTemplate ,
errors ,
results ,
callback
) {
let codeGenerated = false ;
const cache = new MultiItemCache (
runtimes . map ( runtime =>
this . _codeGenerationCache . getItemCache (
` ${ module . identifier ( ) } | ${ getRuntimeKey ( runtime ) } ` ,
` ${ hash } | ${ dependencyTemplates . getHash ( ) } `
)
)
) ;
cache . get ( ( err , cachedResult ) => {
2024-03-18 23:28:40 +08:00
if ( err ) return callback ( /** @type {WebpackError} */ ( err ) ) ;
2021-01-26 07:48:37 +08:00
let result ;
if ( ! cachedResult ) {
try {
codeGenerated = true ;
this . codeGeneratedModules . add ( module ) ;
result = module . codeGeneration ( {
chunkGraph ,
moduleGraph ,
dependencyTemplates ,
runtimeTemplate ,
2021-11-30 19:55:51 +08:00
runtime ,
2022-02-18 01:08:27 +08:00
codeGenerationResults : results ,
compilation : this
2021-01-26 07:48:37 +08:00
} ) ;
} catch ( err ) {
2024-03-14 23:15:13 +08:00
errors . push (
new CodeGenerationError ( module , /** @type {Error} */ ( err ) )
) ;
2021-01-26 07:48:37 +08:00
result = cachedResult = {
sources : new Map ( ) ,
runtimeRequirements : null
} ;
}
} else {
result = cachedResult ;
}
for ( const runtime of runtimes ) {
results . add ( module , runtime , result ) ;
}
if ( ! cachedResult ) {
2024-03-18 23:28:40 +08:00
cache . store ( result , err =>
callback ( /** @type {WebpackError} */ ( err ) , codeGenerated )
) ;
2021-01-26 07:48:37 +08:00
} else {
callback ( null , codeGenerated ) ;
}
} ) ;
}
2021-04-09 21:50:25 +08:00
_getChunkGraphEntries ( ) {
/** @type {Set<Chunk>} */
const treeEntries = new Set ( ) ;
for ( const ep of this . entrypoints . values ( ) ) {
const chunk = ep . getRuntimeChunk ( ) ;
if ( chunk ) treeEntries . add ( chunk ) ;
}
for ( const ep of this . asyncEntrypoints ) {
const chunk = ep . getRuntimeChunk ( ) ;
if ( chunk ) treeEntries . add ( chunk ) ;
}
return treeEntries ;
}
2018-11-06 02:03:12 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ param { object } options options
2021-04-09 21:50:25 +08:00
* @ param { ChunkGraph = } options . chunkGraph the chunk graph
* @ param { Iterable < Module >= } options . modules modules
* @ param { Iterable < Chunk >= } options . chunks chunks
* @ param { CodeGenerationResults = } options . codeGenerationResults codeGenerationResults
* @ param { Iterable < Chunk >= } options . chunkGraphEntries chunkGraphEntries
2018-11-06 02:03:12 +08:00
* @ returns { void }
* /
2021-04-09 21:50:25 +08:00
processRuntimeRequirements ( {
chunkGraph = this . chunkGraph ,
modules = this . modules ,
chunks = this . chunks ,
codeGenerationResults = this . codeGenerationResults ,
chunkGraphEntries = this . _getChunkGraphEntries ( )
} = { } ) {
const context = { chunkGraph , codeGenerationResults } ;
2021-10-05 19:08:21 +08:00
const { moduleMemCaches2 } = this ;
2021-09-24 17:35:28 +08:00
this . logger . time ( "runtime requirements.modules" ) ;
2021-05-11 15:31:46 +08:00
const additionalModuleRuntimeRequirements =
this . hooks . additionalModuleRuntimeRequirements ;
2018-11-17 01:18:44 +08:00
const runtimeRequirementInModule = this . hooks . runtimeRequirementInModule ;
2021-04-09 21:50:25 +08:00
for ( const module of modules ) {
2018-11-15 00:31:32 +08:00
if ( chunkGraph . getNumberOfModuleChunks ( module ) > 0 ) {
2021-10-05 19:08:21 +08:00
const memCache = moduleMemCaches2 && moduleMemCaches2 . get ( module ) ;
2020-07-28 00:09:48 +08:00
for ( const runtime of chunkGraph . getModuleRuntimes ( module ) ) {
2021-09-29 06:06:44 +08:00
if ( memCache ) {
const cached = memCache . get (
` moduleRuntimeRequirements- ${ getRuntimeKey ( runtime ) } `
) ;
2021-09-24 17:35:28 +08:00
if ( cached !== undefined ) {
if ( cached !== null ) {
chunkGraph . addModuleRuntimeRequirements (
module ,
runtime ,
cached ,
false
) ;
}
continue ;
}
}
2020-07-28 00:09:48 +08:00
let set ;
2021-05-11 15:31:46 +08:00
const runtimeRequirements =
codeGenerationResults . getRuntimeRequirements ( module , runtime ) ;
2020-07-28 00:09:48 +08:00
if ( runtimeRequirements && runtimeRequirements . size > 0 ) {
set = new Set ( runtimeRequirements ) ;
} else if ( additionalModuleRuntimeRequirements . isUsed ( ) ) {
set = new Set ( ) ;
} else {
2021-09-29 06:06:44 +08:00
if ( memCache ) {
memCache . set (
` moduleRuntimeRequirements- ${ getRuntimeKey ( runtime ) } ` ,
null
) ;
2021-09-24 17:35:28 +08:00
}
2020-07-28 00:09:48 +08:00
continue ;
}
2021-04-09 21:50:25 +08:00
additionalModuleRuntimeRequirements . call ( module , set , context ) ;
2018-11-17 01:18:44 +08:00
2020-07-28 00:09:48 +08:00
for ( const r of set ) {
const hook = runtimeRequirementInModule . get ( r ) ;
2021-04-09 21:50:25 +08:00
if ( hook !== undefined ) hook . call ( module , set , context ) ;
2020-07-28 00:09:48 +08:00
}
2021-09-24 17:35:28 +08:00
if ( set . size === 0 ) {
2021-09-29 06:06:44 +08:00
if ( memCache ) {
memCache . set (
` moduleRuntimeRequirements- ${ getRuntimeKey ( runtime ) } ` ,
null
) ;
2021-09-24 17:35:28 +08:00
}
} else {
2021-09-29 06:06:44 +08:00
if ( memCache ) {
memCache . set (
` moduleRuntimeRequirements- ${ getRuntimeKey ( runtime ) } ` ,
set
) ;
2021-09-24 17:35:28 +08:00
chunkGraph . addModuleRuntimeRequirements (
module ,
runtime ,
set ,
false
) ;
} else {
chunkGraph . addModuleRuntimeRequirements ( module , runtime , set ) ;
}
}
2018-11-17 01:18:44 +08:00
}
2018-11-06 02:03:12 +08:00
}
}
2021-09-24 17:35:28 +08:00
this . logger . timeEnd ( "runtime requirements.modules" ) ;
2018-11-06 02:03:12 +08:00
2021-09-24 17:35:28 +08:00
this . logger . time ( "runtime requirements.chunks" ) ;
2021-04-09 21:50:25 +08:00
for ( const chunk of chunks ) {
2018-11-06 02:03:12 +08:00
const set = new Set ( ) ;
2018-11-15 00:31:32 +08:00
for ( const module of chunkGraph . getChunkModulesIterable ( chunk ) ) {
2018-11-17 01:11:51 +08:00
const runtimeRequirements = chunkGraph . getModuleRuntimeRequirements (
2020-07-28 00:09:48 +08:00
module ,
chunk . runtime
2018-11-17 01:11:51 +08:00
) ;
2018-11-17 01:18:44 +08:00
for ( const r of runtimeRequirements ) set . add ( r ) ;
2018-11-06 02:03:12 +08:00
}
2021-04-09 21:50:25 +08:00
this . hooks . additionalChunkRuntimeRequirements . call ( chunk , set , context ) ;
2018-11-06 02:03:12 +08:00
for ( const r of set ) {
2021-04-09 21:50:25 +08:00
this . hooks . runtimeRequirementInChunk . for ( r ) . call ( chunk , set , context ) ;
2018-11-06 02:03:12 +08:00
}
2018-11-17 01:11:51 +08:00
chunkGraph . addChunkRuntimeRequirements ( chunk , set ) ;
2018-11-06 02:03:12 +08:00
}
2021-09-24 17:35:28 +08:00
this . logger . timeEnd ( "runtime requirements.chunks" ) ;
2018-11-06 02:03:12 +08:00
2021-09-24 17:35:28 +08:00
this . logger . time ( "runtime requirements.entries" ) ;
2021-04-09 21:50:25 +08:00
for ( const treeEntry of chunkGraphEntries ) {
2018-11-06 02:03:12 +08:00
const set = new Set ( ) ;
2020-07-28 00:09:48 +08:00
for ( const chunk of treeEntry . getAllReferencedChunks ( ) ) {
2021-05-11 15:31:46 +08:00
const runtimeRequirements =
chunkGraph . getChunkRuntimeRequirements ( chunk ) ;
2018-11-06 02:03:12 +08:00
for ( const r of runtimeRequirements ) set . add ( r ) ;
}
2021-04-09 21:50:25 +08:00
this . hooks . additionalTreeRuntimeRequirements . call (
treeEntry ,
set ,
context
) ;
2018-11-06 02:03:12 +08:00
for ( const r of set ) {
2021-04-09 21:50:25 +08:00
this . hooks . runtimeRequirementInTree
. for ( r )
. call ( treeEntry , set , context ) ;
2018-11-06 02:03:12 +08:00
}
2018-11-23 16:37:33 +08:00
2020-07-28 00:09:48 +08:00
chunkGraph . addTreeRuntimeRequirements ( treeEntry , set ) ;
2018-11-06 02:03:12 +08:00
}
2021-09-24 17:35:28 +08:00
this . logger . timeEnd ( "runtime requirements.entries" ) ;
2018-11-06 02:03:12 +08:00
}
2021-04-09 21:50:25 +08:00
// TODO webpack 6 make chunkGraph argument non-optional
2018-11-06 02:03:12 +08:00
/ * *
* @ param { Chunk } chunk target chunk
* @ param { RuntimeModule } module runtime module
2021-04-09 21:50:25 +08:00
* @ param { ChunkGraph } chunkGraph the chunk graph
2018-11-06 02:03:12 +08:00
* @ returns { void }
* /
2021-04-09 21:50:25 +08:00
addRuntimeModule ( chunk , module , chunkGraph = this . chunkGraph ) {
2018-11-15 00:31:32 +08:00
// Deprecated ModuleGraph association
2021-11-05 16:53:32 +08:00
if ( this . _backCompat )
ModuleGraph . setModuleGraphForModule ( module , this . moduleGraph ) ;
2018-11-15 00:31:32 +08:00
// add it to the list
2018-11-06 02:03:12 +08:00
this . modules . add ( module ) ;
2018-11-23 17:02:47 +08:00
this . _modules . set ( module . identifier ( ) , module ) ;
2018-11-15 00:31:32 +08:00
// connect to the chunk graph
2021-04-09 21:50:25 +08:00
chunkGraph . connectChunkAndModule ( chunk , module ) ;
chunkGraph . connectChunkAndRuntimeModule ( chunk , module ) ;
2020-09-02 00:09:28 +08:00
if ( module . fullHash ) {
2021-04-09 21:50:25 +08:00
chunkGraph . addFullHashModuleToChunk ( chunk , module ) ;
2021-09-02 16:00:24 +08:00
} else if ( module . dependentHash ) {
chunkGraph . addDependentHashModuleToChunk ( chunk , module ) ;
2020-09-02 00:09:28 +08:00
}
2018-11-15 00:31:32 +08:00
2019-08-27 02:21:07 +08:00
// attach runtime module
2021-04-13 02:53:25 +08:00
module . attach ( this , chunk , chunkGraph ) ;
2019-08-27 02:21:07 +08:00
2018-11-15 00:31:32 +08:00
// Setup internals
2019-02-06 22:37:11 +08:00
const exportsInfo = this . moduleGraph . getExportsInfo ( module ) ;
exportsInfo . setHasProvideInfo ( ) ;
2020-07-28 00:09:48 +08:00
if ( typeof chunk . runtime === "string" ) {
exportsInfo . setUsedForSideEffectsOnly ( chunk . runtime ) ;
} else if ( chunk . runtime === undefined ) {
exportsInfo . setUsedForSideEffectsOnly ( undefined ) ;
} else {
for ( const runtime of chunk . runtime ) {
exportsInfo . setUsedForSideEffectsOnly ( runtime ) ;
}
}
2021-04-09 21:50:25 +08:00
chunkGraph . addModuleRuntimeRequirements (
2020-01-29 17:28:33 +08:00
module ,
2020-07-28 00:09:48 +08:00
chunk . runtime ,
2020-01-29 17:28:33 +08:00
new Set ( [ RuntimeGlobals . requireScope ] )
) ;
2018-11-15 00:31:32 +08:00
2018-11-29 21:13:02 +08:00
// runtime modules don't need ids
2021-04-09 21:50:25 +08:00
chunkGraph . setModuleId ( module , "" ) ;
2018-11-29 21:13:02 +08:00
2018-11-15 00:31:32 +08:00
// Call hook
this . hooks . runtimeModule . call ( module , chunk ) ;
2018-11-06 02:03:12 +08:00
}
2018-05-12 00:12:30 +08:00
/ * *
2022-01-19 07:44:17 +08:00
* If ` module ` is passed , ` loc ` and ` request ` must also be passed .
2020-09-08 00:02:14 +08:00
* @ param { string | ChunkGroupOptions } groupOptions options for the chunk group
2022-01-19 07:44:17 +08:00
* @ param { Module = } module the module the references the chunk group
* @ param { DependencyLocation = } loc the location from with the chunk group is referenced ( inside of module )
* @ param { string = } request the request from which the the chunk group is referenced
2018-05-12 00:12:30 +08:00
* @ returns { ChunkGroup } the new or existing chunk group
* /
2018-04-16 16:27:22 +08:00
addChunkInGroup ( groupOptions , module , loc , request ) {
if ( typeof groupOptions === "string" ) {
groupOptions = { name : groupOptions } ;
}
const name = groupOptions . name ;
2020-09-08 00:02:14 +08:00
2018-02-25 09:00:20 +08:00
if ( name ) {
2018-01-20 00:06:59 +08:00
const chunkGroup = this . namedChunkGroups . get ( name ) ;
2018-02-25 09:00:20 +08:00
if ( chunkGroup !== undefined ) {
2018-04-16 16:27:22 +08:00
chunkGroup . addOptions ( groupOptions ) ;
2018-02-25 09:00:20 +08:00
if ( module ) {
2018-01-20 00:06:59 +08:00
chunkGroup . addOrigin ( module , loc , request ) ;
2017-01-06 01:00:36 +08:00
}
2018-01-20 00:06:59 +08:00
return chunkGroup ;
}
}
2018-04-16 16:27:22 +08:00
const chunkGroup = new ChunkGroup ( groupOptions ) ;
2018-02-25 09:00:20 +08:00
if ( module ) chunkGroup . addOrigin ( module , loc , request ) ;
2018-01-20 00:06:59 +08:00
const chunk = this . addChunk ( name ) ;
2018-07-27 04:43:20 +08:00
connectChunkGroupAndChunk ( chunkGroup , chunk ) ;
2018-01-20 00:06:59 +08:00
this . chunkGroups . push ( chunkGroup ) ;
2018-02-25 09:00:20 +08:00
if ( name ) {
2018-01-20 00:06:59 +08:00
this . namedChunkGroups . set ( name , chunkGroup ) ;
}
return chunkGroup ;
}
2020-09-08 00:02:14 +08:00
/ * *
* @ param { EntryOptions } options options for the entrypoint
* @ param { Module } module the module the references the chunk group
* @ param { DependencyLocation } loc the location from with the chunk group is referenced ( inside of module )
* @ param { string } request the request from which the the chunk group is referenced
* @ returns { Entrypoint } the new or existing entrypoint
* /
addAsyncEntrypoint ( options , module , loc , request ) {
const name = options . name ;
if ( name ) {
const entrypoint = this . namedChunkGroups . get ( name ) ;
if ( entrypoint instanceof Entrypoint ) {
if ( entrypoint !== undefined ) {
if ( module ) {
entrypoint . addOrigin ( module , loc , request ) ;
}
return entrypoint ;
}
} else if ( entrypoint ) {
throw new Error (
` Cannot add an async entrypoint with the name ' ${ name } ', because there is already an chunk group with this name `
) ;
}
}
const chunk = this . addChunk ( name ) ;
if ( options . filename ) {
chunk . filenameTemplate = options . filename ;
}
const entrypoint = new Entrypoint ( options , false ) ;
entrypoint . setRuntimeChunk ( chunk ) ;
entrypoint . setEntrypointChunk ( chunk ) ;
if ( name ) {
this . namedChunkGroups . set ( name , entrypoint ) ;
}
this . chunkGroups . push ( entrypoint ) ;
this . asyncEntrypoints . push ( entrypoint ) ;
connectChunkGroupAndChunk ( entrypoint , chunk ) ;
if ( module ) {
entrypoint . addOrigin ( module , loc , request ) ;
}
return entrypoint ;
}
2018-05-04 00:57:02 +08:00
/ * *
* This method first looks to see if a name is provided for a new chunk ,
* and first looks to see if any named chunks already exist and reuse that chunk instead .
*
* @ param { string = } name optional chunk name to be provided
* @ returns { Chunk } create a chunk ( invoked during seal event )
* /
2018-01-20 00:06:59 +08:00
addChunk ( name ) {
2018-02-25 09:00:20 +08:00
if ( name ) {
2018-01-20 00:06:59 +08:00
const chunk = this . namedChunks . get ( name ) ;
2018-02-25 09:00:20 +08:00
if ( chunk !== undefined ) {
2017-01-06 01:00:36 +08:00
return chunk ;
2014-06-04 03:03:21 +08:00
}
2014-01-24 20:32:58 +08:00
}
2021-11-05 16:53:32 +08:00
const chunk = new Chunk ( name , this . _backCompat ) ;
2018-09-06 22:59:11 +08:00
this . chunks . add ( chunk ) ;
2021-11-05 16:53:32 +08:00
if ( this . _backCompat )
ChunkGraph . setChunkGraphForChunk ( chunk , this . chunkGraph ) ;
2018-02-25 09:00:20 +08:00
if ( name ) {
2018-01-20 00:06:59 +08:00
this . namedChunks . set ( name , chunk ) ;
2017-01-06 01:00:36 +08:00
}
return chunk ;
2013-01-31 01:49:25 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
2021-10-07 22:13:42 +08:00
* @ deprecated
2018-05-04 00:57:02 +08:00
* @ param { Module } module module to assign depth
* @ returns { void }
* /
2017-01-06 01:00:36 +08:00
assignDepth ( module ) {
2018-08-22 01:16:02 +08:00
const moduleGraph = this . moduleGraph ;
2018-02-24 21:31:18 +08:00
const queue = new Set ( [ module ] ) ;
let depth ;
2018-08-22 01:16:02 +08:00
moduleGraph . setDepth ( module , 0 ) ;
2017-01-06 01:00:36 +08:00
2018-05-04 00:57:02 +08:00
/ * *
2020-03-13 00:51:26 +08:00
* @ param { Module } module module for processing
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2019-10-28 21:02:23 +08:00
const processModule = module => {
2018-08-22 01:16:02 +08:00
if ( ! moduleGraph . setDepthIfLower ( module , depth ) ) return ;
2018-02-24 21:31:18 +08:00
queue . add ( module ) ;
2017-11-08 18:32:05 +08:00
} ;
2016-12-05 06:47:19 +08:00
2018-02-25 09:00:20 +08:00
for ( module of queue ) {
2018-02-24 21:31:18 +08:00
queue . delete ( module ) ;
2018-08-22 01:16:02 +08:00
depth = moduleGraph . getDepth ( module ) + 1 ;
2017-11-08 18:32:05 +08:00
2019-10-28 21:02:23 +08:00
for ( const connection of moduleGraph . getOutgoingConnections ( module ) ) {
const refModule = connection . module ;
if ( refModule ) {
processModule ( refModule ) ;
}
}
2016-12-14 19:03:24 +08:00
}
}
2021-10-07 22:13:42 +08:00
/ * *
* @ param { Set < Module > } modules module to assign depth
* @ returns { void }
* /
assignDepths ( modules ) {
const moduleGraph = this . moduleGraph ;
/** @type {Set<Module | number>} */
const queue = new Set ( modules ) ;
queue . add ( 1 ) ;
let depth = 0 ;
let i = 0 ;
for ( const module of queue ) {
i ++ ;
if ( typeof module === "number" ) {
depth = module ;
if ( queue . size === i ) return ;
queue . add ( depth + 1 ) ;
} else {
moduleGraph . setDepth ( module , depth ) ;
for ( const { module : refModule } of moduleGraph . getOutgoingConnections (
module
) ) {
if ( refModule ) {
queue . add ( refModule ) ;
}
}
}
}
}
2018-06-08 16:34:38 +08:00
/ * *
* @ param { Dependency } dependency the dependency
2020-07-28 00:09:48 +08:00
* @ param { RuntimeSpec } runtime the runtime
2020-05-28 02:34:55 +08:00
* @ returns { ( string [ ] | ReferencedExport ) [ ] } referenced exports
2018-06-08 16:34:38 +08:00
* /
2020-07-28 00:09:48 +08:00
getDependencyReferencedExports ( dependency , runtime ) {
const referencedExports = dependency . getReferencedExports (
this . moduleGraph ,
runtime
) ;
2019-10-30 05:28:42 +08:00
return this . hooks . dependencyReferencedExports . call (
referencedExports ,
2020-07-28 00:09:48 +08:00
dependency ,
runtime
2019-10-30 05:28:42 +08:00
) ;
2018-06-08 16:34:38 +08:00
}
2018-05-04 00:57:02 +08:00
/ * *
* @ param { Module } module module relationship for removal
2018-05-07 05:01:47 +08:00
* @ param { DependenciesBlockLike } block //TODO: good description
2018-05-04 00:57:02 +08:00
* @ returns { void }
* /
2017-11-06 20:02:35 +08:00
removeReasonsOfDependencyBlock ( module , block ) {
2018-02-25 09:00:20 +08:00
if ( block . blocks ) {
2019-07-10 02:49:10 +08:00
for ( const b of block . blocks ) {
this . removeReasonsOfDependencyBlock ( module , b ) ;
}
2017-11-06 20:02:35 +08:00
}
2018-02-25 09:00:20 +08:00
if ( block . dependencies ) {
2020-09-06 16:32:46 +08:00
for ( const dep of block . dependencies ) {
const originalModule = this . moduleGraph . getModule ( dep ) ;
if ( originalModule ) {
this . moduleGraph . removeConnection ( dep ) ;
2020-09-06 17:05:45 +08:00
if ( this . chunkGraph ) {
2021-10-08 21:08:48 +08:00
for ( const chunk of this . chunkGraph . getModuleChunks (
2020-09-06 17:05:45 +08:00
originalModule
) ) {
this . patchChunksAfterReasonRemoval ( originalModule , chunk ) ;
}
}
2020-09-06 16:32:46 +08:00
}
}
2017-11-06 20:02:35 +08:00
}
}
2018-05-04 00:57:02 +08:00
/ * *
* @ param { Module } module module to patch tie
* @ param { Chunk } chunk chunk to patch tie
* @ returns { void }
* /
2017-11-06 20:02:35 +08:00
patchChunksAfterReasonRemoval ( module , chunk ) {
2020-07-28 00:09:48 +08:00
if ( ! module . hasReasons ( this . moduleGraph , chunk . runtime ) ) {
2017-11-06 20:02:35 +08:00
this . removeReasonsOfDependencyBlock ( module , module ) ;
}
2018-08-14 17:18:22 +08:00
if ( ! module . hasReasonForChunk ( chunk , this . moduleGraph , this . chunkGraph ) ) {
if ( this . chunkGraph . isModuleInChunk ( module , chunk ) ) {
this . chunkGraph . disconnectChunkAndModule ( chunk , module ) ;
2017-11-06 20:02:35 +08:00
this . removeChunkFromDependencies ( module , chunk ) ;
}
}
}
2018-05-04 00:57:02 +08:00
/ * *
* @ param { DependenciesBlock } block block tie for Chunk
* @ param { Chunk } chunk chunk to remove from dep
* @ returns { void }
* /
2017-11-06 20:02:35 +08:00
removeChunkFromDependencies ( block , chunk ) {
2020-09-06 16:32:46 +08:00
/ * *
2020-09-06 16:59:36 +08:00
* @ param { Dependency } d dependency to ( maybe ) patch up
2020-09-06 16:32:46 +08:00
* /
2017-11-06 20:02:35 +08:00
const iteratorDependency = d => {
2020-09-06 16:32:46 +08:00
const depModule = this . moduleGraph . getModule ( d ) ;
if ( ! depModule ) {
2017-11-06 20:02:35 +08:00
return ;
2017-01-06 01:00:36 +08:00
}
2020-09-06 16:32:46 +08:00
this . patchChunksAfterReasonRemoval ( depModule , chunk ) ;
2017-01-24 02:52:20 +08:00
} ;
2017-03-02 22:09:09 +08:00
const blocks = block . blocks ;
2018-02-25 09:00:20 +08:00
for ( let indexBlock = 0 ; indexBlock < blocks . length ; indexBlock ++ ) {
2018-05-15 18:20:17 +08:00
const asyncBlock = blocks [ indexBlock ] ;
2024-03-18 23:28:40 +08:00
const chunkGroup =
/** @type {ChunkGroup} */
( this . chunkGraph . getBlockChunkGroup ( asyncBlock ) ) ;
2018-05-04 00:57:02 +08:00
// Grab all chunks from the first Block's AsyncDepBlock
2018-08-23 02:17:49 +08:00
const chunks = chunkGroup . chunks ;
2018-05-04 00:57:02 +08:00
// For each chunk in chunkGroup
2018-02-25 09:00:20 +08:00
for ( let indexChunk = 0 ; indexChunk < chunks . length ; indexChunk ++ ) {
2018-05-04 00:57:02 +08:00
const iteratedChunk = chunks [ indexChunk ] ;
2018-08-23 02:17:49 +08:00
chunkGroup . removeChunk ( iteratedChunk ) ;
2018-05-04 00:57:02 +08:00
// Recurse
this . removeChunkFromDependencies ( block , iteratedChunk ) ;
2017-01-24 02:52:20 +08:00
}
}
2018-02-25 09:00:20 +08:00
if ( block . dependencies ) {
2019-07-10 02:49:10 +08:00
for ( const dep of block . dependencies ) iteratorDependency ( dep ) ;
2017-01-24 02:52:20 +08:00
}
2014-11-02 19:17:05 +08:00
}
2015-07-08 20:15:21 +08:00
2020-10-23 20:52:23 +08:00
assignRuntimeIds ( ) {
const { chunkGraph } = this ;
const processEntrypoint = ep => {
const runtime = ep . options . runtime || ep . name ;
const chunk = ep . getRuntimeChunk ( ) ;
chunkGraph . setRuntimeId ( runtime , chunk . id ) ;
} ;
for ( const ep of this . entrypoints . values ( ) ) {
processEntrypoint ( ep ) ;
}
for ( const ep of this . asyncEntrypoints ) {
processEntrypoint ( ep ) ;
}
}
2017-01-06 01:00:36 +08:00
sortItemsWithChunkIds ( ) {
2018-02-25 09:00:20 +08:00
for ( const chunkGroup of this . chunkGroups ) {
2018-01-20 00:06:59 +08:00
chunkGroup . sortItems ( ) ;
}
2018-09-07 20:11:48 +08:00
this . errors . sort ( compareErrors ) ;
this . warnings . sort ( compareErrors ) ;
2018-04-03 23:23:41 +08:00
this . children . sort ( byNameOrHash ) ;
2017-01-06 01:00:36 +08:00
}
summarizeDependencies ( ) {
2018-02-25 09:00:20 +08:00
for (
let indexChildren = 0 ;
indexChildren < this . children . length ;
indexChildren ++
) {
2017-12-28 21:38:03 +08:00
const child = this . children [ indexChildren ] ;
2017-01-24 02:52:20 +08:00
2019-08-07 15:54:43 +08:00
this . fileDependencies . addAll ( child . fileDependencies ) ;
this . contextDependencies . addAll ( child . contextDependencies ) ;
this . missingDependencies . addAll ( child . missingDependencies ) ;
2019-08-09 20:46:42 +08:00
this . buildDependencies . addAll ( child . buildDependencies ) ;
2017-01-24 02:52:20 +08:00
}
2018-09-05 22:12:48 +08:00
for ( const module of this . modules ) {
2020-08-23 03:54:34 +08:00
module . addCacheDependencies (
this . fileDependencies ,
this . contextDependencies ,
this . missingDependencies ,
this . buildDependencies
) ;
2017-01-24 02:52:20 +08:00
}
2017-01-06 01:00:36 +08:00
}
2018-11-15 00:31:32 +08:00
createModuleHashes ( ) {
2020-08-14 12:29:10 +08:00
let statModulesHashed = 0 ;
2021-09-24 17:35:28 +08:00
let statModulesFromCache = 0 ;
2021-10-05 19:08:21 +08:00
const { chunkGraph , runtimeTemplate , moduleMemCaches2 } = this ;
2018-11-15 00:31:32 +08:00
const { hashFunction , hashDigest , hashDigestLength } = this . outputOptions ;
2024-03-18 01:15:44 +08:00
/** @type {WebpackError[]} */
2022-02-22 19:23:24 +08:00
const errors = [ ] ;
2018-11-15 00:31:32 +08:00
for ( const module of this . modules ) {
2021-10-05 19:08:21 +08:00
const memCache = moduleMemCaches2 && moduleMemCaches2 . get ( module ) ;
2020-07-28 00:09:48 +08:00
for ( const runtime of chunkGraph . getModuleRuntimes ( module ) ) {
2021-09-29 06:06:44 +08:00
if ( memCache ) {
const digest = memCache . get ( ` moduleHash- ${ getRuntimeKey ( runtime ) } ` ) ;
2021-09-24 17:35:28 +08:00
if ( digest !== undefined ) {
chunkGraph . setModuleHashes (
module ,
runtime ,
digest ,
2022-03-14 05:54:18 +08:00
digest . slice ( 0 , hashDigestLength )
2021-09-24 17:35:28 +08:00
) ;
statModulesFromCache ++ ;
continue ;
}
}
2020-08-14 12:29:10 +08:00
statModulesHashed ++ ;
2021-09-24 17:35:28 +08:00
const digest = this . _createModuleHash (
2020-07-28 00:09:48 +08:00
module ,
2021-01-26 07:48:37 +08:00
chunkGraph ,
2020-07-28 00:09:48 +08:00
runtime ,
2021-01-26 07:48:37 +08:00
hashFunction ,
runtimeTemplate ,
hashDigest ,
2022-02-22 19:23:24 +08:00
hashDigestLength ,
errors
2020-07-28 00:09:48 +08:00
) ;
2021-09-29 06:06:44 +08:00
if ( memCache ) {
memCache . set ( ` moduleHash- ${ getRuntimeKey ( runtime ) } ` , digest ) ;
2021-09-24 17:35:28 +08:00
}
2020-07-28 00:09:48 +08:00
}
2018-11-15 00:31:32 +08:00
}
2022-02-22 19:23:24 +08:00
if ( errors . length > 0 ) {
errors . sort ( compareSelect ( err => err . module , compareModulesByIdentifier ) ) ;
for ( const error of errors ) {
this . errors . push ( error ) ;
}
}
2020-08-14 12:29:10 +08:00
this . logger . log (
2021-09-24 17:35:28 +08:00
` ${ statModulesHashed } modules hashed, ${ statModulesFromCache } from cache ( ${
Math . round (
( 100 * ( statModulesHashed + statModulesFromCache ) ) / this . modules . size
) / 100
2020-08-14 12:29:10 +08:00
} variants per module in average ) `
) ;
2018-11-15 00:31:32 +08:00
}
2024-03-18 01:15:44 +08:00
/ * *
* @ private
* @ param { Module } module module
* @ param { ChunkGraph } chunkGraph the chunk graph
* @ param { RuntimeSpec } runtime runtime
* @ param { OutputOptions [ "hashFunction" ] } hashFunction hash function
* @ param { RuntimeTemplate } runtimeTemplate runtime template
* @ param { OutputOptions [ "hashDigest" ] } hashDigest hash digest
* @ param { OutputOptions [ "hashDigestLength" ] } hashDigestLength hash digest length
* @ param { WebpackError [ ] } errors errors
* @ returns { string } module hash digest
* /
2021-01-26 07:48:37 +08:00
_createModuleHash (
module ,
chunkGraph ,
runtime ,
hashFunction ,
runtimeTemplate ,
hashDigest ,
2022-02-22 19:23:24 +08:00
hashDigestLength ,
errors
2021-01-26 07:48:37 +08:00
) {
2022-02-22 19:23:24 +08:00
let moduleHashDigest ;
try {
const moduleHash = createHash ( hashFunction ) ;
module . updateHash ( moduleHash , {
chunkGraph ,
runtime ,
runtimeTemplate
} ) ;
moduleHashDigest = /** @type {string} */ ( moduleHash . digest ( hashDigest ) ) ;
} catch ( err ) {
2024-03-18 01:15:44 +08:00
errors . push ( new ModuleHashingError ( module , /** @type {Error} */ ( err ) ) ) ;
2022-02-22 19:23:24 +08:00
moduleHashDigest = "XXXXXX" ;
}
2021-01-26 07:48:37 +08:00
chunkGraph . setModuleHashes (
module ,
runtime ,
moduleHashDigest ,
2022-03-14 05:54:18 +08:00
moduleHashDigest . slice ( 0 , hashDigestLength )
2021-01-26 07:48:37 +08:00
) ;
return moduleHashDigest ;
}
2017-01-06 01:00:36 +08:00
createHash ( ) {
2020-01-30 18:34:33 +08:00
this . logger . time ( "hashing: initialize hash" ) ;
2024-03-18 01:15:44 +08:00
const chunkGraph = /** @type {ChunkGraph} */ ( this . chunkGraph ) ;
2020-10-26 21:00:11 +08:00
const runtimeTemplate = this . runtimeTemplate ;
2017-01-06 01:00:36 +08:00
const outputOptions = this . outputOptions ;
const hashFunction = outputOptions . hashFunction ;
const hashDigest = outputOptions . hashDigest ;
const hashDigestLength = outputOptions . hashDigestLength ;
2017-11-23 17:59:29 +08:00
const hash = createHash ( hashFunction ) ;
2018-05-29 20:50:40 +08:00
if ( outputOptions . hashSalt ) {
hash . update ( outputOptions . hashSalt ) ;
}
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "hashing: initialize hash" ) ;
if ( this . children . length > 0 ) {
this . logger . time ( "hashing: hash child compilations" ) ;
for ( const child of this . children ) {
hash . update ( child . hash ) ;
}
this . logger . timeEnd ( "hashing: hash child compilations" ) ;
2018-05-29 20:50:40 +08:00
}
2020-01-30 18:34:33 +08:00
if ( this . warnings . length > 0 ) {
this . logger . time ( "hashing: hash warnings" ) ;
for ( const warning of this . warnings ) {
hash . update ( ` ${ warning . message } ` ) ;
}
this . logger . timeEnd ( "hashing: hash warnings" ) ;
2018-05-29 20:50:40 +08:00
}
2020-01-30 18:34:33 +08:00
if ( this . errors . length > 0 ) {
this . logger . time ( "hashing: hash errors" ) ;
for ( const error of this . errors ) {
hash . update ( ` ${ error . message } ` ) ;
}
this . logger . timeEnd ( "hashing: hash errors" ) ;
2018-05-29 20:50:40 +08:00
}
2018-11-15 00:31:32 +08:00
2020-01-30 18:34:33 +08:00
this . logger . time ( "hashing: sort chunks" ) ;
2021-02-15 04:21:16 +08:00
/ *
* all non - runtime chunks need to be hashes first ,
* since runtime chunk might use their hashes .
* runtime chunks need to be hashed in the correct order
* since they may depend on each other ( for async entrypoints ) .
* So we put all non - runtime chunks first and hash them in any order .
* And order runtime chunks according to referenced between each other .
* Chunks need to be in deterministic order since we add hashes to full chunk
* during these hashing .
2017-01-10 20:20:54 +08:00
* /
2021-02-15 04:21:16 +08:00
/** @type {Chunk[]} */
const unorderedRuntimeChunks = [ ] ;
/** @type {Chunk[]} */
2020-10-14 20:27:52 +08:00
const otherChunks = [ ] ;
2021-02-15 04:21:16 +08:00
for ( const c of this . chunks ) {
2020-10-14 20:27:52 +08:00
if ( c . hasRuntime ( ) ) {
2021-02-15 04:21:16 +08:00
unorderedRuntimeChunks . push ( c ) ;
2020-10-14 20:27:52 +08:00
} else {
otherChunks . push ( c ) ;
}
}
2021-02-15 04:21:16 +08:00
unorderedRuntimeChunks . sort ( byId ) ;
2020-10-14 20:27:52 +08:00
otherChunks . sort ( byId ) ;
2021-02-15 04:21:16 +08:00
/** @typedef {{ chunk: Chunk, referencedBy: RuntimeChunkInfo[], remaining: number }} RuntimeChunkInfo */
/** @type {Map<Chunk, RuntimeChunkInfo>} */
const runtimeChunksMap = new Map ( ) ;
for ( const chunk of unorderedRuntimeChunks ) {
runtimeChunksMap . set ( chunk , {
chunk ,
referencedBy : [ ] ,
remaining : 0
} ) ;
}
let remaining = 0 ;
for ( const info of runtimeChunksMap . values ( ) ) {
for ( const other of new Set (
Array . from ( info . chunk . getAllReferencedAsyncEntrypoints ( ) ) . map (
e => e . chunks [ e . chunks . length - 1 ]
)
) ) {
const otherInfo = runtimeChunksMap . get ( other ) ;
otherInfo . referencedBy . push ( info ) ;
info . remaining ++ ;
remaining ++ ;
2020-10-14 20:27:52 +08:00
}
2021-02-15 04:21:16 +08:00
}
/** @type {Chunk[]} */
const runtimeChunks = [ ] ;
for ( const info of runtimeChunksMap . values ( ) ) {
if ( info . remaining === 0 ) {
runtimeChunks . push ( info . chunk ) ;
}
}
// If there are any references between chunks
// make sure to follow these chains
if ( remaining > 0 ) {
const readyChunks = [ ] ;
for ( const chunk of runtimeChunks ) {
2021-09-02 16:00:24 +08:00
const hasFullHashModules =
chunkGraph . getNumberOfChunkFullHashModules ( chunk ) !== 0 ;
2024-03-18 01:15:44 +08:00
const info =
/** @type {RuntimeChunkInfo} */
( runtimeChunksMap . get ( chunk ) ) ;
2021-02-15 04:21:16 +08:00
for ( const otherInfo of info . referencedBy ) {
2021-09-02 16:00:24 +08:00
if ( hasFullHashModules ) {
chunkGraph . upgradeDependentToFullHashModules ( otherInfo . chunk ) ;
}
2021-02-15 04:21:16 +08:00
remaining -- ;
if ( -- otherInfo . remaining === 0 ) {
readyChunks . push ( otherInfo . chunk ) ;
}
}
if ( readyChunks . length > 0 ) {
// This ensures deterministic ordering, since referencedBy is non-deterministic
readyChunks . sort ( byId ) ;
for ( const c of readyChunks ) runtimeChunks . push ( c ) ;
readyChunks . length = 0 ;
}
}
}
// If there are still remaining references we have cycles and want to create a warning
if ( remaining > 0 ) {
let circularRuntimeChunkInfo = [ ] ;
for ( const info of runtimeChunksMap . values ( ) ) {
if ( info . remaining !== 0 ) {
circularRuntimeChunkInfo . push ( info ) ;
}
}
circularRuntimeChunkInfo . sort ( compareSelect ( i => i . chunk , byId ) ) ;
2021-05-11 15:31:46 +08:00
const err =
new WebpackError ( ` Circular dependency between chunks with runtime ( ${ Array . from (
circularRuntimeChunkInfo ,
c => c . chunk . name || c . chunk . id
) . join ( ", " ) } )
2021-02-15 04:21:16 +08:00
This prevents using hashes of each other and should be avoided . ` );
err . chunk = circularRuntimeChunkInfo [ 0 ] . chunk ;
this . warnings . push ( err ) ;
for ( const i of circularRuntimeChunkInfo ) runtimeChunks . push ( i . chunk ) ;
}
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "hashing: sort chunks" ) ;
2021-02-15 04:21:16 +08:00
2020-04-30 23:52:27 +08:00
const fullHashChunks = new Set ( ) ;
2021-01-26 07:48:37 +08:00
/** @type {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} */
const codeGenerationJobs = [ ] ;
/** @type {Map<string, Map<Module, {module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}>>} */
const codeGenerationJobsMap = new Map ( ) ;
2024-03-18 01:15:44 +08:00
/** @type {WebpackError[]} */
2022-02-22 19:23:24 +08:00
const errors = [ ] ;
2021-02-15 04:21:16 +08:00
2024-03-18 01:15:44 +08:00
/ * *
* @ param { Chunk } chunk chunk
* /
2020-10-14 20:27:52 +08:00
const processChunk = chunk => {
2018-11-20 19:55:17 +08:00
// Last minute module hash generation for modules that depend on chunk hashes
2020-01-30 18:34:33 +08:00
this . logger . time ( "hashing: hash runtime modules" ) ;
2021-01-26 07:48:37 +08:00
const runtime = chunk . runtime ;
2018-11-20 19:55:17 +08:00
for ( const module of chunkGraph . getChunkModulesIterable ( chunk ) ) {
2021-01-26 07:48:37 +08:00
if ( ! chunkGraph . hasModuleHashes ( module , runtime ) ) {
const hash = this . _createModuleHash (
2018-11-20 19:55:17 +08:00
module ,
2021-01-26 07:48:37 +08:00
chunkGraph ,
runtime ,
hashFunction ,
runtimeTemplate ,
hashDigest ,
2022-02-22 19:23:24 +08:00
hashDigestLength ,
errors
2018-11-20 19:55:17 +08:00
) ;
2021-01-26 07:48:37 +08:00
let hashMap = codeGenerationJobsMap . get ( hash ) ;
if ( hashMap ) {
const moduleJob = hashMap . get ( module ) ;
if ( moduleJob ) {
moduleJob . runtimes . push ( runtime ) ;
continue ;
}
} else {
hashMap = new Map ( ) ;
codeGenerationJobsMap . set ( hash , hashMap ) ;
}
const job = {
module ,
hash ,
runtime ,
runtimes : [ runtime ]
} ;
hashMap . set ( module , job ) ;
codeGenerationJobs . push ( job ) ;
2018-11-20 19:55:17 +08:00
}
}
2022-02-22 19:27:50 +08:00
this . logger . timeAggregate ( "hashing: hash runtime modules" ) ;
2018-09-21 23:39:15 +08:00
try {
2022-02-22 19:23:24 +08:00
this . logger . time ( "hashing: hash chunks" ) ;
const chunkHash = createHash ( hashFunction ) ;
2018-09-21 23:39:15 +08:00
if ( outputOptions . hashSalt ) {
chunkHash . update ( outputOptions . hashSalt ) ;
}
2018-09-25 22:07:42 +08:00
chunk . updateHash ( chunkHash , chunkGraph ) ;
2019-10-02 14:54:21 +08:00
this . hooks . chunkHash . call ( chunk , chunkHash , {
2018-09-25 22:07:42 +08:00
chunkGraph ,
2022-02-11 22:59:35 +08:00
codeGenerationResults : this . codeGenerationResults ,
2018-09-25 22:07:42 +08:00
moduleGraph : this . moduleGraph ,
runtimeTemplate : this . runtimeTemplate
} ) ;
2021-05-11 15:31:46 +08:00
const chunkHashDigest = /** @type {string} */ (
chunkHash . digest ( hashDigest )
) ;
2020-04-30 23:52:27 +08:00
hash . update ( chunkHashDigest ) ;
chunk . hash = chunkHashDigest ;
2022-03-14 05:54:18 +08:00
chunk . renderedHash = chunk . hash . slice ( 0 , hashDigestLength ) ;
2021-05-11 15:31:46 +08:00
const fullHashModules =
chunkGraph . getChunkFullHashModulesIterable ( chunk ) ;
2020-04-30 23:52:27 +08:00
if ( fullHashModules ) {
fullHashChunks . add ( chunk ) ;
} else {
this . hooks . contentHash . call ( chunk ) ;
}
2018-09-21 23:39:15 +08:00
} catch ( err ) {
this . errors . push ( new ChunkRenderError ( chunk , "" , err ) ) ;
2018-05-29 20:50:40 +08:00
}
2020-01-30 18:34:33 +08:00
this . logger . timeAggregate ( "hashing: hash chunks" ) ;
2020-10-14 20:27:52 +08:00
} ;
otherChunks . forEach ( processChunk ) ;
2021-02-15 04:21:16 +08:00
for ( const chunk of runtimeChunks ) processChunk ( chunk ) ;
2022-02-22 19:23:24 +08:00
if ( errors . length > 0 ) {
errors . sort ( compareSelect ( err => err . module , compareModulesByIdentifier ) ) ;
for ( const error of errors ) {
this . errors . push ( error ) ;
}
}
2020-10-14 20:27:52 +08:00
2020-01-30 18:34:33 +08:00
this . logger . timeAggregateEnd ( "hashing: hash runtime modules" ) ;
this . logger . timeAggregateEnd ( "hashing: hash chunks" ) ;
this . logger . time ( "hashing: hash digest" ) ;
2020-07-08 23:20:14 +08:00
this . hooks . fullHash . call ( hash ) ;
2019-07-10 17:42:34 +08:00
this . fullHash = /** @type {string} */ ( hash . digest ( hashDigest ) ) ;
2022-03-14 05:54:18 +08:00
this . hash = this . fullHash . slice ( 0 , hashDigestLength ) ;
2020-01-30 18:34:33 +08:00
this . logger . timeEnd ( "hashing: hash digest" ) ;
2020-04-30 23:52:27 +08:00
this . logger . time ( "hashing: process full hash modules" ) ;
for ( const chunk of fullHashChunks ) {
2024-03-18 01:15:44 +08:00
for ( const module of /** @type {Iterable<RuntimeModule>} */ (
chunkGraph . getChunkFullHashModulesIterable ( chunk )
) ) {
2020-04-30 23:52:27 +08:00
const moduleHash = createHash ( hashFunction ) ;
2020-07-28 00:09:48 +08:00
module . updateHash ( moduleHash , {
chunkGraph ,
2020-10-26 21:00:11 +08:00
runtime : chunk . runtime ,
runtimeTemplate
2020-07-28 00:09:48 +08:00
} ) ;
2021-05-11 15:31:46 +08:00
const moduleHashDigest = /** @type {string} */ (
moduleHash . digest ( hashDigest )
) ;
2021-01-26 07:48:37 +08:00
const oldHash = chunkGraph . getModuleHash ( module , chunk . runtime ) ;
2020-04-30 23:52:27 +08:00
chunkGraph . setModuleHashes (
module ,
2020-07-28 00:09:48 +08:00
chunk . runtime ,
2020-04-30 23:52:27 +08:00
moduleHashDigest ,
2022-03-14 05:54:18 +08:00
moduleHashDigest . slice ( 0 , hashDigestLength )
2020-04-30 23:52:27 +08:00
) ;
2021-01-26 07:48:37 +08:00
codeGenerationJobsMap . get ( oldHash ) . get ( module ) . hash = moduleHashDigest ;
2020-04-30 23:52:27 +08:00
}
const chunkHash = createHash ( hashFunction ) ;
chunkHash . update ( chunk . hash ) ;
chunkHash . update ( this . hash ) ;
2021-05-11 15:31:46 +08:00
const chunkHashDigest = /** @type {string} */ (
chunkHash . digest ( hashDigest )
) ;
2020-04-30 23:52:27 +08:00
chunk . hash = chunkHashDigest ;
2022-03-14 05:54:18 +08:00
chunk . renderedHash = chunk . hash . slice ( 0 , hashDigestLength ) ;
2020-04-30 23:52:27 +08:00
this . hooks . contentHash . call ( chunk ) ;
}
this . logger . timeEnd ( "hashing: process full hash modules" ) ;
2021-01-26 07:48:37 +08:00
return codeGenerationJobs ;
2013-02-13 20:00:01 +08:00
}
2017-01-06 01:00:36 +08:00
2019-09-11 17:13:46 +08:00
/ * *
* @ param { string } file file name
* @ param { Source } source asset source
* @ param { AssetInfo } assetInfo extra asset information
* @ returns { void }
* /
emitAsset ( file , source , assetInfo = { } ) {
if ( this . assets [ file ] ) {
2019-09-13 14:42:36 +08:00
if ( ! isSourceEqual ( this . assets [ file ] , source ) ) {
2019-11-14 22:01:25 +08:00
this . errors . push (
2019-09-13 14:42:36 +08:00
new WebpackError (
2022-06-01 15:23:47 +08:00
` Conflict: Multiple assets emit different content to the same filename ${ file } ${
assetInfo . sourceFilename
? ` . Original source ${ assetInfo . sourceFilename } `
: ""
} `
2019-09-13 14:42:36 +08:00
)
2019-09-11 17:13:46 +08:00
) ;
2019-09-13 14:42:36 +08:00
this . assets [ file ] = source ;
2020-08-19 03:14:43 +08:00
this . _setAssetInfo ( file , assetInfo ) ;
2019-09-13 14:42:36 +08:00
return ;
2019-09-11 17:13:46 +08:00
}
const oldInfo = this . assetsInfo . get ( file ) ;
2020-08-19 03:14:43 +08:00
const newInfo = Object . assign ( { } , oldInfo , assetInfo ) ;
this . _setAssetInfo ( file , newInfo , oldInfo ) ;
2019-09-11 17:13:46 +08:00
return ;
}
this . assets [ file ] = source ;
2020-08-19 03:14:43 +08:00
this . _setAssetInfo ( file , assetInfo , undefined ) ;
}
_setAssetInfo ( file , newInfo , oldInfo = this . assetsInfo . get ( file ) ) {
if ( newInfo === undefined ) {
this . assetsInfo . delete ( file ) ;
} else {
this . assetsInfo . set ( file , newInfo ) ;
}
const oldRelated = oldInfo && oldInfo . related ;
const newRelated = newInfo && newInfo . related ;
if ( oldRelated ) {
for ( const key of Object . keys ( oldRelated ) ) {
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } name name
* /
2020-08-19 03:14:43 +08:00
const remove = name => {
const relatedIn = this . _assetsRelatedIn . get ( name ) ;
if ( relatedIn === undefined ) return ;
const entry = relatedIn . get ( key ) ;
if ( entry === undefined ) return ;
entry . delete ( file ) ;
if ( entry . size !== 0 ) return ;
relatedIn . delete ( key ) ;
if ( relatedIn . size === 0 ) this . _assetsRelatedIn . delete ( name ) ;
} ;
const entry = oldRelated [ key ] ;
if ( Array . isArray ( entry ) ) {
entry . forEach ( remove ) ;
} else if ( entry ) {
remove ( entry ) ;
}
}
}
if ( newRelated ) {
for ( const key of Object . keys ( newRelated ) ) {
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } name name
* /
2020-08-19 03:14:43 +08:00
const add = name => {
let relatedIn = this . _assetsRelatedIn . get ( name ) ;
if ( relatedIn === undefined ) {
this . _assetsRelatedIn . set ( name , ( relatedIn = new Map ( ) ) ) ;
}
let entry = relatedIn . get ( key ) ;
if ( entry === undefined ) {
relatedIn . set ( key , ( entry = new Set ( ) ) ) ;
}
entry . add ( file ) ;
} ;
const entry = newRelated [ key ] ;
if ( Array . isArray ( entry ) ) {
entry . forEach ( add ) ;
} else if ( entry ) {
add ( entry ) ;
}
}
}
2019-09-11 17:13:46 +08:00
}
/ * *
* @ param { string } file file name
* @ param { Source | function ( Source ) : Source } newSourceOrFunction new asset source or function converting old to new
2024-03-18 01:15:44 +08:00
* @ param { ( AssetInfo | function ( AssetInfo | undefined ) : AssetInfo ) | undefined } assetInfoUpdateOrFunction new asset info or function converting old to new
2019-09-11 17:13:46 +08:00
* /
updateAsset (
file ,
newSourceOrFunction ,
assetInfoUpdateOrFunction = undefined
) {
if ( ! this . assets [ file ] ) {
throw new Error (
` Called Compilation.updateAsset for not existing filename ${ file } `
) ;
}
if ( typeof newSourceOrFunction === "function" ) {
this . assets [ file ] = newSourceOrFunction ( this . assets [ file ] ) ;
} else {
this . assets [ file ] = newSourceOrFunction ;
}
if ( assetInfoUpdateOrFunction !== undefined ) {
2020-08-01 04:03:14 +08:00
const oldInfo = this . assetsInfo . get ( file ) || EMPTY _ASSET _INFO ;
2019-09-11 17:13:46 +08:00
if ( typeof assetInfoUpdateOrFunction === "function" ) {
2020-08-19 03:14:43 +08:00
this . _setAssetInfo ( file , assetInfoUpdateOrFunction ( oldInfo ) , oldInfo ) ;
2019-09-11 17:13:46 +08:00
} else {
2020-08-19 03:14:43 +08:00
this . _setAssetInfo (
2019-09-11 17:13:46 +08:00
file ,
2020-08-19 03:14:43 +08:00
cachedCleverMerge ( oldInfo , assetInfoUpdateOrFunction ) ,
oldInfo
) ;
}
}
}
2024-03-18 01:15:44 +08:00
/ * *
* @ param { string } file file name
* @ param { string } newFile the new name of file
* /
2020-08-19 03:14:43 +08:00
renameAsset ( file , newFile ) {
const source = this . assets [ file ] ;
if ( ! source ) {
throw new Error (
` Called Compilation.renameAsset for not existing filename ${ file } `
) ;
}
if ( this . assets [ newFile ] ) {
if ( ! isSourceEqual ( this . assets [ file ] , source ) ) {
this . errors . push (
new WebpackError (
` Conflict: Called Compilation.renameAsset for already existing filename ${ newFile } with different content `
)
2019-09-11 17:13:46 +08:00
) ;
}
}
2020-08-19 03:14:43 +08:00
const assetInfo = this . assetsInfo . get ( file ) ;
// Update related in all other assets
const relatedInInfo = this . _assetsRelatedIn . get ( file ) ;
if ( relatedInInfo ) {
for ( const [ key , assets ] of relatedInInfo ) {
for ( const name of assets ) {
const info = this . assetsInfo . get ( name ) ;
if ( ! info ) continue ;
const related = info . related ;
if ( ! related ) continue ;
const entry = related [ key ] ;
let newEntry ;
if ( Array . isArray ( entry ) ) {
newEntry = entry . map ( x => ( x === file ? newFile : x ) ) ;
} else if ( entry === file ) {
newEntry = newFile ;
} else continue ;
this . assetsInfo . set ( name , {
... info ,
related : {
... related ,
[ key ] : newEntry
}
} ) ;
}
}
}
this . _setAssetInfo ( file , undefined , assetInfo ) ;
this . _setAssetInfo ( newFile , assetInfo ) ;
delete this . assets [ file ] ;
this . assets [ newFile ] = source ;
for ( const chunk of this . chunks ) {
2020-09-03 17:39:15 +08:00
{
const size = chunk . files . size ;
chunk . files . delete ( file ) ;
if ( size !== chunk . files . size ) {
chunk . files . add ( newFile ) ;
}
}
{
const size = chunk . auxiliaryFiles . size ;
chunk . auxiliaryFiles . delete ( file ) ;
if ( size !== chunk . auxiliaryFiles . size ) {
chunk . auxiliaryFiles . add ( newFile ) ;
}
2020-08-19 03:14:43 +08:00
}
}
2019-09-11 17:13:46 +08:00
}
2020-08-06 15:55:18 +08:00
/ * *
* @ param { string } file file name
* /
deleteAsset ( file ) {
if ( ! this . assets [ file ] ) {
return ;
}
delete this . assets [ file ] ;
const assetInfo = this . assetsInfo . get ( file ) ;
2020-08-19 03:14:43 +08:00
this . _setAssetInfo ( file , undefined , assetInfo ) ;
2020-08-06 15:55:18 +08:00
const related = assetInfo && assetInfo . related ;
if ( related ) {
for ( const key of Object . keys ( related ) ) {
2020-08-07 21:24:49 +08:00
const checkUsedAndDelete = file => {
2020-08-19 03:14:43 +08:00
if ( ! this . _assetsRelatedIn . has ( file ) ) {
this . deleteAsset ( file ) ;
2020-08-07 21:24:49 +08:00
}
} ;
2020-08-06 15:55:18 +08:00
const items = related [ key ] ;
if ( Array . isArray ( items ) ) {
2020-08-19 03:14:43 +08:00
items . forEach ( checkUsedAndDelete ) ;
} else if ( items ) {
2020-08-07 21:24:49 +08:00
checkUsedAndDelete ( items ) ;
2020-08-06 15:55:18 +08:00
}
}
}
2020-10-15 20:27:23 +08:00
// TODO If this becomes a performance problem
// store a reverse mapping from asset to chunk
for ( const chunk of this . chunks ) {
chunk . files . delete ( file ) ;
chunk . auxiliaryFiles . delete ( file ) ;
}
2020-08-06 15:55:18 +08:00
}
2019-09-11 17:13:46 +08:00
getAssets ( ) {
2020-05-12 18:16:51 +08:00
/** @type {Readonly<Asset>[]} */
2019-09-11 17:13:46 +08:00
const array = [ ] ;
for ( const assetName of Object . keys ( this . assets ) ) {
if ( Object . prototype . hasOwnProperty . call ( this . assets , assetName ) ) {
array . push ( {
name : assetName ,
source : this . assets [ assetName ] ,
2020-08-01 04:03:14 +08:00
info : this . assetsInfo . get ( assetName ) || EMPTY _ASSET _INFO
2019-09-11 17:13:46 +08:00
} ) ;
}
}
return array ;
}
/ * *
* @ param { string } name the name of the asset
2020-05-12 18:16:51 +08:00
* @ returns { Readonly < Asset > | undefined } the asset or undefined when not found
2019-09-11 17:13:46 +08:00
* /
getAsset ( name ) {
if ( ! Object . prototype . hasOwnProperty . call ( this . assets , name ) )
return undefined ;
return {
name ,
source : this . assets [ name ] ,
2020-08-01 04:03:14 +08:00
info : this . assetsInfo . get ( name ) || EMPTY _ASSET _INFO
2019-09-11 17:13:46 +08:00
} ;
}
2019-07-17 23:30:25 +08:00
clearAssets ( ) {
for ( const chunk of this . chunks ) {
chunk . files . clear ( ) ;
chunk . auxiliaryFiles . clear ( ) ;
}
}
2017-01-06 01:00:36 +08:00
createModuleAssets ( ) {
2019-07-17 23:30:25 +08:00
const { chunkGraph } = this ;
2018-09-05 22:12:48 +08:00
for ( const module of this . modules ) {
2024-03-18 01:15:44 +08:00
const buildInfo = /** @type {BuildInfo} */ ( module . buildInfo ) ;
if ( buildInfo . assets ) {
const assetsInfo = buildInfo . assetsInfo ;
for ( const assetName of Object . keys ( buildInfo . assets ) ) {
2018-08-23 01:23:48 +08:00
const fileName = this . getPath ( assetName , {
chunkGraph : this . chunkGraph ,
module
} ) ;
2019-07-17 23:30:25 +08:00
for ( const chunk of chunkGraph . getModuleChunksIterable ( module ) ) {
chunk . auxiliaryFiles . add ( fileName ) ;
}
2019-09-11 17:13:46 +08:00
this . emitAsset (
fileName ,
2024-03-18 01:15:44 +08:00
buildInfo . assets [ assetName ] ,
2019-09-11 17:13:46 +08:00
assetsInfo ? assetsInfo . get ( assetName ) : undefined
) ;
2017-11-27 22:27:30 +08:00
this . hooks . moduleAsset . call ( module , fileName ) ;
2018-01-22 20:52:43 +08:00
}
2017-01-06 01:00:36 +08:00
}
2013-01-31 01:49:25 +08:00
}
}
2017-01-06 01:00:36 +08:00
2019-10-02 14:54:21 +08:00
/ * *
* @ param { RenderManifestOptions } options options object
* @ returns { RenderManifestEntry [ ] } manifest entries
* /
getRenderManifest ( options ) {
return this . hooks . renderManifest . call ( [ ] , options ) ;
}
2018-12-10 18:34:59 +08:00
/ * *
* @ param { Callback } callback signals when the call finishes
* @ returns { void }
* /
2018-09-27 13:22:19 +08:00
createChunkAssets ( callback ) {
2017-01-06 01:00:36 +08:00
const outputOptions = this . outputOptions ;
2018-09-27 13:22:19 +08:00
const cachedSourceMap = new WeakMap ( ) ;
2018-06-29 16:03:21 +08:00
/** @type {Map<string, {hash: string, source: Source, chunk: Chunk}>} */
const alreadyWrittenFiles = new Map ( ) ;
2018-09-27 13:22:19 +08:00
2021-08-05 16:57:53 +08:00
asyncLib . forEachLimit (
2018-09-27 13:22:19 +08:00
this . chunks ,
2021-08-05 16:57:53 +08:00
15 ,
2019-06-14 16:45:56 +08:00
( chunk , callback ) => {
2018-09-27 13:22:19 +08:00
/** @type {RenderManifestEntry[]} */
let manifest ;
try {
2019-10-02 14:54:21 +08:00
manifest = this . getRenderManifest ( {
2018-09-27 13:22:19 +08:00
chunk ,
hash : this . hash ,
fullHash : this . fullHash ,
outputOptions ,
2019-10-09 04:29:46 +08:00
codeGenerationResults : this . codeGenerationResults ,
2018-09-27 13:22:19 +08:00
moduleTemplates : this . moduleTemplates ,
dependencyTemplates : this . dependencyTemplates ,
chunkGraph : this . chunkGraph ,
moduleGraph : this . moduleGraph ,
runtimeTemplate : this . runtimeTemplate
2019-10-02 14:54:21 +08:00
} ) ;
2018-09-27 13:22:19 +08:00
} catch ( err ) {
2024-03-18 01:15:44 +08:00
this . errors . push (
new ChunkRenderError ( chunk , "" , /** @type {Error} */ ( err ) )
) ;
2018-09-27 13:22:19 +08:00
return callback ( ) ;
}
asyncLib . forEach (
manifest ,
2019-06-14 16:45:56 +08:00
( fileManifest , callback ) => {
2018-10-11 16:46:48 +08:00
const ident = fileManifest . identifier ;
2018-09-27 13:22:19 +08:00
const usedHash = fileManifest . hash ;
2020-07-15 17:14:28 +08:00
const assetCacheItem = this . _assetsCache . getItemCache (
ident ,
usedHash
) ;
assetCacheItem . get ( ( err , sourceFromCache ) => {
2019-09-13 17:12:26 +08:00
/** @type {string | function(PathData, AssetInfo=): string} */
2019-07-23 14:45:14 +08:00
let filenameTemplate ;
/** @type {string} */
let file ;
2020-07-17 20:57:11 +08:00
/** @type {AssetInfo} */
let assetInfo ;
2019-07-23 14:45:14 +08:00
let inTry = true ;
2024-02-22 22:20:17 +08:00
/ * *
* @ param { Error } err error
* @ returns { void }
* /
2019-07-23 14:45:14 +08:00
const errorAndCallback = err => {
const filename =
file ||
2020-07-17 20:57:11 +08:00
( typeof file === "string"
? file
: typeof filenameTemplate === "string"
2024-01-14 09:41:34 +08:00
? filenameTemplate
: "" ) ;
2019-07-23 14:45:14 +08:00
this . errors . push ( new ChunkRenderError ( chunk , filename , err ) ) ;
inTry = false ;
return callback ( ) ;
} ;
2018-09-27 13:22:19 +08:00
try {
2020-07-17 20:57:11 +08:00
if ( "filename" in fileManifest ) {
file = fileManifest . filename ;
assetInfo = fileManifest . info ;
} else {
filenameTemplate = fileManifest . filenameTemplate ;
const pathAndInfo = this . getPathWithInfo (
filenameTemplate ,
fileManifest . pathOptions
) ;
file = pathAndInfo . path ;
2020-10-22 15:35:14 +08:00
assetInfo = fileManifest . info
? {
... pathAndInfo . info ,
... fileManifest . info
2024-01-14 09:41:34 +08:00
}
2020-10-22 15:35:14 +08:00
: pathAndInfo . info ;
2020-07-17 20:57:11 +08:00
}
2019-07-19 06:08:50 +08:00
2018-09-27 13:22:19 +08:00
if ( err ) {
2019-07-23 14:45:14 +08:00
return errorAndCallback ( err ) ;
2018-09-27 13:22:19 +08:00
}
let source = sourceFromCache ;
// check if the same filename was already written by another chunk
const alreadyWritten = alreadyWrittenFiles . get ( file ) ;
if ( alreadyWritten !== undefined ) {
if ( alreadyWritten . hash !== usedHash ) {
2019-07-23 14:45:14 +08:00
inTry = false ;
2018-09-27 13:22:19 +08:00
return callback (
2019-06-14 16:45:56 +08:00
new WebpackError (
2018-09-27 13:22:19 +08:00
` Conflict: Multiple chunks emit assets to the same filename ${ file } ` +
` (chunks ${ alreadyWritten . chunk . id } and ${ chunk . id } ) `
)
) ;
} else {
source = alreadyWritten . source ;
}
} else if ( ! source ) {
// render the asset
source = fileManifest . render ( ) ;
// Ensure that source is a cached source to avoid additional cost because of repeated access
if ( ! ( source instanceof CachedSource ) ) {
const cacheEntry = cachedSourceMap . get ( source ) ;
if ( cacheEntry ) {
source = cacheEntry ;
} else {
const cachedSource = new CachedSource ( source ) ;
cachedSourceMap . set ( source , cachedSource ) ;
source = cachedSource ;
}
}
}
2019-09-13 17:12:26 +08:00
this . emitAsset ( file , source , assetInfo ) ;
2019-07-17 23:30:25 +08:00
if ( fileManifest . auxiliary ) {
chunk . auxiliaryFiles . add ( file ) ;
} else {
chunk . files . add ( file ) ;
}
2018-09-27 13:22:19 +08:00
this . hooks . chunkAsset . call ( chunk , file ) ;
alreadyWrittenFiles . set ( file , {
2018-06-29 16:03:21 +08:00
hash : usedHash ,
2018-09-27 13:22:19 +08:00
source ,
chunk
} ) ;
2018-10-09 20:30:59 +08:00
if ( source !== sourceFromCache ) {
2020-07-15 17:14:28 +08:00
assetCacheItem . store ( source , err => {
2019-07-23 14:45:14 +08:00
if ( err ) return errorAndCallback ( err ) ;
2019-11-08 00:31:47 +08:00
inTry = false ;
2019-07-23 14:45:14 +08:00
return callback ( ) ;
} ) ;
2018-10-09 20:30:59 +08:00
} else {
2019-07-23 14:45:14 +08:00
inTry = false ;
2018-10-09 20:30:59 +08:00
callback ( ) ;
}
2018-09-27 13:22:19 +08:00
} catch ( err ) {
2019-07-23 14:45:14 +08:00
if ( ! inTry ) throw err ;
errorAndCallback ( err ) ;
2017-12-01 17:43:14 +08:00
}
2018-09-27 13:22:19 +08:00
} ) ;
} ,
callback
2018-02-25 09:00:20 +08:00
) ;
2018-09-27 13:22:19 +08:00
} ,
callback
) ;
2013-01-31 01:49:25 +08:00
}
2017-01-06 01:00:36 +08:00
2018-05-04 00:57:02 +08:00
/ * *
2019-09-13 17:12:26 +08:00
* @ param { string | function ( PathData , AssetInfo = ) : string } filename used to get asset path with hash
2018-08-23 01:23:48 +08:00
* @ param { PathData } data context data
2018-05-15 18:20:17 +08:00
* @ returns { string } interpolated path
2018-05-04 00:57:02 +08:00
* /
2019-10-02 14:54:21 +08:00
getPath ( filename , data = { } ) {
if ( ! data . hash ) {
data = {
hash : this . hash ,
... data
} ;
}
return this . getAssetPath ( filename , data ) ;
}
/ * *
* @ param { string | function ( PathData , AssetInfo = ) : string } filename used to get asset path with hash
* @ param { PathData } data context data
* @ returns { { path : string , info : AssetInfo } } interpolated path and asset info
* /
getPathWithInfo ( filename , data = { } ) {
2018-10-30 19:02:39 +08:00
if ( ! data . hash ) {
2019-06-19 19:16:05 +08:00
data = {
hash : this . hash ,
... data
} ;
2018-10-30 19:02:39 +08:00
}
2019-10-02 14:54:21 +08:00
return this . getAssetPathWithInfo ( filename , data ) ;
}
/ * *
* @ param { string | function ( PathData , AssetInfo = ) : string } filename used to get asset path with hash
* @ param { PathData } data context data
* @ returns { string } interpolated path
* /
getAssetPath ( filename , data ) {
return this . hooks . assetPath . call (
typeof filename === "function" ? filename ( data ) : filename ,
data ,
undefined
) ;
2017-01-06 01:00:36 +08:00
}
2019-09-11 17:13:46 +08:00
/ * *
2019-09-13 17:12:26 +08:00
* @ param { string | function ( PathData , AssetInfo = ) : string } filename used to get asset path with hash
* @ param { PathData } data context data
2019-09-11 17:13:46 +08:00
* @ returns { { path : string , info : AssetInfo } } interpolated path and asset info
* /
2019-10-02 14:54:21 +08:00
getAssetPathWithInfo ( filename , data ) {
const assetInfo = { } ;
// TODO webpack 5: refactor assetPath hook to receive { path, info } object
const newPath = this . hooks . assetPath . call (
typeof filename === "function" ? filename ( data , assetInfo ) : filename ,
data ,
assetInfo
) ;
return { path : newPath , info : assetInfo } ;
2019-09-11 17:13:46 +08:00
}
2020-09-21 03:24:15 +08:00
getWarnings ( ) {
return this . hooks . processWarnings . call ( this . warnings ) ;
}
getErrors ( ) {
return this . hooks . processErrors . call ( this . errors ) ;
}
2018-05-04 00:57:02 +08:00
/ * *
* This function allows you to run another instance of webpack inside of webpack however as
* a child with different settings and configurations ( if desired ) applied . It copies all hooks , plugins
* from parent ( or top level compiler ) and creates a child Compilation
*
* @ param { string } name name of the child compiler
2021-04-23 03:43:43 +08:00
* @ param { OutputOptions = } outputOptions // Need to convert config schema to types for this
* @ param { Array < WebpackPluginInstance | WebpackPluginFunction >= } plugins webpack plugins that will be applied
2018-05-04 00:57:02 +08:00
* @ returns { Compiler } creates a child Compiler instance
* /
2017-04-13 19:43:51 +08:00
createChildCompiler ( name , outputOptions , plugins ) {
2018-02-25 09:00:20 +08:00
const idx = this . childrenCounters [ name ] || 0 ;
2017-04-13 19:43:51 +08:00
this . childrenCounters [ name ] = idx + 1 ;
2018-02-25 09:00:20 +08:00
return this . compiler . createChildCompiler (
this ,
name ,
idx ,
outputOptions ,
plugins
) ;
2017-01-06 01:00:36 +08:00
}
2021-04-09 21:50:25 +08:00
/ * *
* @ param { Module } module the module
2021-04-12 15:17:43 +08:00
* @ param { ExecuteModuleOptions } options options
* @ param { ExecuteModuleCallback } callback callback
2021-04-09 21:50:25 +08:00
* /
2021-04-12 15:17:43 +08:00
executeModule ( module , options , callback ) {
2021-04-09 21:50:25 +08:00
// Aggregate all referenced modules and ensure they are ready
const modules = new Set ( [ module ] ) ;
processAsyncTree (
modules ,
10 ,
2021-04-12 15:17:43 +08:00
/ * *
* @ param { Module } module the module
* @ param { function ( Module ) : void } push push more jobs
* @ param { Callback } callback callback
* @ returns { void }
* /
2021-04-09 21:50:25 +08:00
( module , push , callback ) => {
2021-10-18 18:42:20 +08:00
this . buildQueue . waitFor ( module , err => {
2021-04-09 21:50:25 +08:00
if ( err ) return callback ( err ) ;
2021-10-18 18:42:20 +08:00
this . processDependenciesQueue . waitFor ( module , err => {
2021-04-09 21:50:25 +08:00
if ( err ) return callback ( err ) ;
2021-10-18 18:42:20 +08:00
for ( const { module : m } of this . moduleGraph . getOutgoingConnections (
module
) ) {
const size = modules . size ;
modules . add ( m ) ;
if ( modules . size !== size ) push ( m ) ;
}
callback ( ) ;
2021-04-09 21:50:25 +08:00
} ) ;
} ) ;
} ,
err => {
2024-03-18 01:15:44 +08:00
if ( err ) return callback ( /** @type {WebpackError} */ ( err ) ) ;
2021-04-09 21:50:25 +08:00
// Create new chunk graph, chunk and entrypoint for the build time execution
2021-09-22 18:12:46 +08:00
const chunkGraph = new ChunkGraph (
this . moduleGraph ,
this . outputOptions . hashFunction
) ;
2021-04-09 21:50:25 +08:00
const runtime = "build time" ;
2021-05-11 15:31:46 +08:00
const { hashFunction , hashDigest , hashDigestLength } =
this . outputOptions ;
2021-04-09 21:50:25 +08:00
const runtimeTemplate = this . runtimeTemplate ;
2021-11-05 16:53:32 +08:00
const chunk = new Chunk ( "build time chunk" , this . _backCompat ) ;
2021-04-09 21:50:25 +08:00
chunk . id = chunk . name ;
chunk . ids = [ chunk . id ] ;
chunk . runtime = runtime ;
const entrypoint = new Entrypoint ( {
runtime ,
2021-04-15 02:21:17 +08:00
chunkLoading : false ,
2021-04-09 21:50:25 +08:00
... options . entryOptions
} ) ;
chunkGraph . connectChunkAndEntryModule ( chunk , module , entrypoint ) ;
connectChunkGroupAndChunk ( entrypoint , chunk ) ;
entrypoint . setRuntimeChunk ( chunk ) ;
entrypoint . setEntrypointChunk ( chunk ) ;
const chunks = new Set ( [ chunk ] ) ;
// Assign ids to modules and modules to the chunk
for ( const module of modules ) {
const id = module . identifier ( ) ;
chunkGraph . setModuleId ( module , id ) ;
chunkGraph . connectChunkAndModule ( chunk , module ) ;
}
2022-02-22 19:23:24 +08:00
/** @type {WebpackError[]} */
const errors = [ ] ;
2021-04-09 21:50:25 +08:00
// Hash modules
for ( const module of modules ) {
this . _createModuleHash (
module ,
chunkGraph ,
runtime ,
hashFunction ,
runtimeTemplate ,
hashDigest ,
2022-02-22 19:23:24 +08:00
hashDigestLength ,
errors
2021-04-09 21:50:25 +08:00
) ;
}
2021-09-22 18:12:46 +08:00
const codeGenerationResults = new CodeGenerationResults (
this . outputOptions . hashFunction
) ;
2021-04-12 15:17:43 +08:00
/ * *
* @ param { Module } module the module
* @ param { Callback } callback callback
* @ returns { void }
* /
2021-04-09 21:50:25 +08:00
const codeGen = ( module , callback ) => {
this . _codeGenerationModule (
module ,
runtime ,
[ runtime ] ,
chunkGraph . getModuleHash ( module , runtime ) ,
this . dependencyTemplates ,
chunkGraph ,
this . moduleGraph ,
runtimeTemplate ,
errors ,
codeGenerationResults ,
( err , codeGenerated ) => {
callback ( err ) ;
}
) ;
} ;
2021-04-12 15:17:43 +08:00
const reportErrors = ( ) => {
if ( errors . length > 0 ) {
errors . sort (
compareSelect ( err => err . module , compareModulesByIdentifier )
) ;
for ( const error of errors ) {
this . errors . push ( error ) ;
}
errors . length = 0 ;
}
} ;
2021-04-09 21:50:25 +08:00
// Generate code for all aggregated modules
asyncLib . eachLimit ( modules , 10 , codeGen , err => {
2021-04-12 15:17:43 +08:00
if ( err ) return callback ( err ) ;
reportErrors ( ) ;
2021-04-09 21:50:25 +08:00
// for backward-compat temporary set the chunk graph
// TODO webpack 6
const old = this . chunkGraph ;
this . chunkGraph = chunkGraph ;
this . processRuntimeRequirements ( {
chunkGraph ,
modules ,
chunks ,
codeGenerationResults ,
chunkGraphEntries : chunks
} ) ;
this . chunkGraph = old ;
2021-05-11 15:31:46 +08:00
const runtimeModules =
chunkGraph . getChunkRuntimeModulesIterable ( chunk ) ;
2021-04-09 21:50:25 +08:00
// Hash runtime modules
for ( const module of runtimeModules ) {
2021-04-14 20:37:11 +08:00
modules . add ( module ) ;
2021-04-09 21:50:25 +08:00
this . _createModuleHash (
module ,
chunkGraph ,
runtime ,
hashFunction ,
runtimeTemplate ,
hashDigest ,
2023-08-28 16:05:57 +08:00
hashDigestLength ,
errors
2021-04-09 21:50:25 +08:00
) ;
}
// Generate code for all runtime modules
asyncLib . eachLimit ( runtimeModules , 10 , codeGen , err => {
2021-04-12 15:17:43 +08:00
if ( err ) return callback ( err ) ;
reportErrors ( ) ;
2021-04-09 21:50:25 +08:00
2021-04-14 20:37:11 +08:00
/** @type {Map<Module, ExecuteModuleArgument>} */
const moduleArgumentsMap = new Map ( ) ;
/** @type {Map<string, ExecuteModuleArgument>} */
const moduleArgumentsById = new Map ( ) ;
2021-04-12 15:17:43 +08:00
/** @type {ExecuteModuleResult["fileDependencies"]} */
2021-04-10 02:45:59 +08:00
const fileDependencies = new LazySet ( ) ;
2021-04-12 15:17:43 +08:00
/** @type {ExecuteModuleResult["contextDependencies"]} */
2021-04-10 02:45:59 +08:00
const contextDependencies = new LazySet ( ) ;
2021-04-12 15:17:43 +08:00
/** @type {ExecuteModuleResult["missingDependencies"]} */
2021-04-10 02:45:59 +08:00
const missingDependencies = new LazySet ( ) ;
2021-04-12 15:17:43 +08:00
/** @type {ExecuteModuleResult["buildDependencies"]} */
2021-04-10 02:45:59 +08:00
const buildDependencies = new LazySet ( ) ;
2021-04-14 20:37:11 +08:00
2021-04-12 15:17:43 +08:00
/** @type {ExecuteModuleResult["assets"]} */
2021-04-10 02:45:59 +08:00
const assets = new Map ( ) ;
2021-04-14 20:37:11 +08:00
let cacheable = true ;
/** @type {ExecuteModuleContext} */
const context = {
assets ,
_ _webpack _require _ _ : undefined ,
chunk ,
chunkGraph
} ;
// Prepare execution
asyncLib . eachLimit (
modules ,
10 ,
( module , callback ) => {
const codeGenerationResult = codeGenerationResults . get (
module ,
runtime
2021-04-14 20:37:00 +08:00
) ;
2021-04-14 20:37:11 +08:00
/** @type {ExecuteModuleArgument} */
const moduleArgument = {
module ,
codeGenerationResult ,
preparedInfo : undefined ,
moduleObject : undefined
2021-04-09 21:50:25 +08:00
} ;
2021-04-14 20:37:11 +08:00
moduleArgumentsMap . set ( module , moduleArgument ) ;
moduleArgumentsById . set ( module . identifier ( ) , moduleArgument ) ;
2021-04-10 02:45:59 +08:00
module . addCacheDependencies (
fileDependencies ,
contextDependencies ,
missingDependencies ,
buildDependencies
) ;
2024-03-18 01:15:44 +08:00
if (
/** @type {BuildInfo} */ ( module . buildInfo ) . cacheable ===
false
) {
2021-04-14 20:37:11 +08:00
cacheable = false ;
}
2021-04-12 18:42:25 +08:00
if ( module . buildInfo && module . buildInfo . assets ) {
const { assets : moduleAssets , assetsInfo } = module . buildInfo ;
for ( const assetName of Object . keys ( moduleAssets ) ) {
assets . set ( assetName , {
source : moduleAssets [ assetName ] ,
info : assetsInfo ? assetsInfo . get ( assetName ) : undefined
} ) ;
}
}
2021-04-14 20:37:11 +08:00
this . hooks . prepareModuleExecution . callAsync (
moduleArgument ,
context ,
callback
) ;
} ,
err => {
if ( err ) return callback ( err ) ;
let exports ;
2021-04-09 21:50:25 +08:00
try {
2021-04-14 20:37:11 +08:00
const {
strictModuleErrorHandling ,
strictModuleExceptionHandling
} = this . outputOptions ;
const _ _webpack _require _ _ = id => {
const cached = moduleCache [ id ] ;
if ( cached !== undefined ) {
if ( cached . error ) throw cached . error ;
return cached . exports ;
}
const moduleArgument = moduleArgumentsById . get ( id ) ;
return _ _webpack _require _module _ _ ( moduleArgument , id ) ;
} ;
const interceptModuleExecution = ( _ _webpack _require _ _ [
RuntimeGlobals . interceptModuleExecution . replace (
2023-05-20 00:00:54 +08:00
` ${ RuntimeGlobals . require } . ` ,
2021-04-14 20:37:11 +08:00
""
)
] = [ ] ) ;
const moduleCache = ( _ _webpack _require _ _ [
RuntimeGlobals . moduleCache . replace (
2023-05-20 00:00:54 +08:00
` ${ RuntimeGlobals . require } . ` ,
2021-04-14 20:37:11 +08:00
""
)
] = { } ) ;
context . _ _webpack _require _ _ = _ _webpack _require _ _ ;
/ * *
* @ param { ExecuteModuleArgument } moduleArgument the module argument
* @ param { string = } id id
* @ returns { any } exports
* /
const _ _webpack _require _module _ _ = ( moduleArgument , id ) => {
var execOptions = {
id ,
module : {
id ,
exports : { } ,
loaded : false ,
error : undefined
} ,
require : _ _webpack _require _ _
} ;
interceptModuleExecution . forEach ( handler =>
handler ( execOptions )
) ;
const module = moduleArgument . module ;
this . buildTimeExecutedModules . add ( module ) ;
const moduleObject = execOptions . module ;
moduleArgument . moduleObject = moduleObject ;
try {
if ( id ) moduleCache [ id ] = moduleObject ;
tryRunOrWebpackError (
( ) =>
this . hooks . executeModule . call (
moduleArgument ,
context
) ,
"Compilation.hooks.executeModule"
) ;
moduleObject . loaded = true ;
return moduleObject . exports ;
} catch ( e ) {
if ( strictModuleExceptionHandling ) {
if ( id ) delete moduleCache [ id ] ;
} else if ( strictModuleErrorHandling ) {
moduleObject . error = e ;
}
if ( ! e . module ) e . module = module ;
throw e ;
}
} ;
for ( const runtimeModule of chunkGraph . getChunkRuntimeModulesInOrder (
chunk
) ) {
_ _webpack _require _module _ _ (
2024-02-22 22:20:17 +08:00
/** @type {ExecuteModuleArgument} */
( moduleArgumentsMap . get ( runtimeModule ) )
2021-04-14 20:37:11 +08:00
) ;
2021-04-09 21:50:25 +08:00
}
2021-04-14 20:37:11 +08:00
exports = _ _webpack _require _ _ ( module . identifier ( ) ) ;
} catch ( e ) {
const err = new WebpackError (
` Execution of module code from module graph ( ${ module . readableIdentifier (
this . requestShortener
) } ) failed : $ { e . message } `
) ;
err . stack = e . stack ;
err . module = e . module ;
return callback ( err ) ;
2021-04-09 21:50:25 +08:00
}
2021-04-14 20:37:11 +08:00
callback ( null , {
exports ,
assets ,
cacheable ,
fileDependencies ,
contextDependencies ,
missingDependencies ,
buildDependencies
} ) ;
2021-04-09 21:50:25 +08:00
}
2021-04-14 20:37:11 +08:00
) ;
2021-04-09 21:50:25 +08:00
} ) ;
} ) ;
}
) ;
}
2017-01-06 01:00:36 +08:00
checkConstraints ( ) {
2018-08-14 22:40:37 +08:00
const chunkGraph = this . chunkGraph ;
2018-05-04 00:57:02 +08:00
/** @type {Set<number|string>} */
2018-01-05 14:41:09 +08:00
const usedIds = new Set ( ) ;
2017-01-24 02:52:20 +08:00
2018-09-05 22:12:48 +08:00
for ( const module of this . modules ) {
2023-05-05 07:19:11 +08:00
if ( module . type === WEBPACK _MODULE _TYPE _RUNTIME ) continue ;
2018-09-05 22:12:48 +08:00
const moduleId = chunkGraph . getModuleId ( module ) ;
2018-02-25 09:00:20 +08:00
if ( moduleId === null ) continue ;
2018-05-29 20:50:40 +08:00
if ( usedIds . has ( moduleId ) ) {
2017-01-24 02:52:20 +08:00
throw new Error ( ` checkConstraints: duplicate module id ${ moduleId } ` ) ;
2018-05-29 20:50:40 +08:00
}
2018-01-05 14:41:09 +08:00
usedIds . add ( moduleId ) ;
2017-01-24 02:52:20 +08:00
}
2018-09-06 22:59:11 +08:00
for ( const chunk of this . chunks ) {
2018-08-14 22:40:37 +08:00
for ( const module of chunkGraph . getChunkModulesIterable ( chunk ) ) {
2018-09-05 22:12:48 +08:00
if ( ! this . modules . has ( module ) ) {
2018-08-14 22:40:37 +08:00
throw new Error (
"checkConstraints: module in chunk but not in compilation " +
` ${ chunk . debugId } ${ module . debugId } `
) ;
}
}
for ( const module of chunkGraph . getChunkEntryModulesIterable ( chunk ) ) {
2018-09-05 22:12:48 +08:00
if ( ! this . modules . has ( module ) ) {
2018-08-14 22:40:37 +08:00
throw new Error (
"checkConstraints: entry module in chunk but not in compilation " +
` ${ chunk . debugId } ${ module . debugId } `
) ;
}
}
2018-01-20 00:06:59 +08:00
}
2018-02-25 09:00:20 +08:00
for ( const chunkGroup of this . chunkGroups ) {
2018-01-20 00:06:59 +08:00
chunkGroup . checkConstraints ( ) ;
2017-01-24 02:52:20 +08:00
}
2017-01-06 01:00:36 +08:00
}
}
2021-09-28 01:03:55 +08:00
/ * *
2024-06-11 21:09:50 +08:00
* @ typedef { object } FactorizeModuleOptions
2021-09-28 01:03:55 +08:00
* @ property { ModuleProfile } currentProfile
* @ property { ModuleFactory } factory
* @ property { Dependency [ ] } dependencies
* @ property { boolean = } factoryResult return full ModuleFactoryResult instead of only module
* @ property { Module | null } originModule
* @ property { Partial < ModuleFactoryCreateDataContextInfo >= } contextInfo
* @ property { string = } context
* /
/ * *
* @ param { FactorizeModuleOptions } options options object
* @ param { ModuleCallback | ModuleFactoryResultCallback } callback callback
* @ returns { void }
* /
// Workaround for typescript as it doesn't support function overloading in jsdoc within a class
2024-06-11 20:32:02 +08:00
Compilation . prototype . factorizeModule = / * *
@ type { {
2021-09-28 01:03:55 +08:00
( options : FactorizeModuleOptions & { factoryResult ? : false } , callback : ModuleCallback ) : void ;
( options : FactorizeModuleOptions & { factoryResult : true } , callback : ModuleFactoryResultCallback ) : void ;
} } * / (
function ( options , callback ) {
this . factorizeQueue . add ( options , callback ) ;
}
) ;
2020-07-15 17:14:28 +08:00
// Hide from typescript
const compilationPrototype = Compilation . prototype ;
2020-07-08 23:20:14 +08:00
// TODO webpack 6 remove
2020-07-15 17:14:28 +08:00
Object . defineProperty ( compilationPrototype , "modifyHash" , {
2020-07-08 23:20:14 +08:00
writable : false ,
enumerable : false ,
configurable : false ,
value : ( ) => {
throw new Error (
"Compilation.modifyHash was removed in favor of Compilation.hooks.fullHash"
) ;
}
} ) ;
2020-07-15 17:14:28 +08:00
// TODO webpack 6 remove
Object . defineProperty ( compilationPrototype , "cache" , {
enumerable : false ,
configurable : false ,
get : util . deprecate (
/ * *
* @ this { Compilation } the compilation
* @ returns { Cache } the cache
* /
function ( ) {
return this . compiler . cache ;
} ,
"Compilation.cache was removed in favor of Compilation.getCache()" ,
"DEP_WEBPACK_COMPILATION_CACHE"
) ,
set : util . deprecate (
2024-03-18 01:15:44 +08:00
/ * *
* @ param { any } v value
* /
2020-07-15 17:14:28 +08:00
v => { } ,
"Compilation.cache was removed in favor of Compilation.getCache()" ,
"DEP_WEBPACK_COMPILATION_CACHE"
)
} ) ;
2020-05-12 18:16:51 +08:00
/ * *
* Add additional assets to the compilation .
* /
Compilation . PROCESS _ASSETS _STAGE _ADDITIONAL = - 2000 ;
/ * *
* Basic preprocessing of assets .
* /
Compilation . PROCESS _ASSETS _STAGE _PRE _PROCESS = - 1000 ;
/ * *
* Derive new assets from existing assets .
* Existing assets should not be treated as complete .
* /
Compilation . PROCESS _ASSETS _STAGE _DERIVED = - 200 ;
/ * *
* Add additional sections to existing assets , like a banner or initialization code .
* /
Compilation . PROCESS _ASSETS _STAGE _ADDITIONS = - 100 ;
/ * *
* Optimize existing assets in a general way .
* /
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE = 100 ;
/ * *
* Optimize the count of existing assets , e . g . by merging them .
2020-11-09 18:58:18 +08:00
* Only assets of the same type should be merged .
* For assets of different types see PROCESS _ASSETS _STAGE _OPTIMIZE _INLINE .
2020-05-12 18:16:51 +08:00
* /
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _COUNT = 200 ;
/ * *
* Optimize the compatibility of existing assets , e . g . add polyfills or vendor - prefixes .
* /
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _COMPATIBILITY = 300 ;
/ * *
* Optimize the size of existing assets , e . g . by minimizing or omitting whitespace .
* /
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _SIZE = 400 ;
/ * *
2020-11-09 18:58:18 +08:00
* Add development tooling to assets , e . g . by extracting a SourceMap .
2020-05-12 18:16:51 +08:00
* /
2020-11-09 18:58:18 +08:00
Compilation . PROCESS _ASSETS _STAGE _DEV _TOOLING = 500 ;
2020-05-12 18:16:51 +08:00
/ * *
2020-11-09 18:58:18 +08:00
* Optimize the count of existing assets , e . g . by inlining assets of into other assets .
* Only assets of different types should be inlined .
* For assets of the same type see PROCESS _ASSETS _STAGE _OPTIMIZE _COUNT .
2020-05-12 18:16:51 +08:00
* /
2020-11-09 18:58:18 +08:00
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _INLINE = 700 ;
/ * *
* Summarize the list of existing assets
* e . g . creating an assets manifest of Service Workers .
* /
Compilation . PROCESS _ASSETS _STAGE _SUMMARIZE = 1000 ;
2020-05-12 18:16:51 +08:00
/ * *
2020-10-16 20:29:35 +08:00
* Optimize the hashes of the assets , e . g . by generating real hashes of the asset content .
2020-05-12 18:16:51 +08:00
* /
2020-10-16 20:29:35 +08:00
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _HASH = 2500 ;
2020-05-12 18:16:51 +08:00
2020-08-19 03:14:43 +08:00
/ * *
2020-10-16 20:29:35 +08:00
* Optimize the transfer of existing assets , e . g . by preparing a compressed ( gzip ) file as separate asset .
2020-08-19 03:14:43 +08:00
* /
2020-10-16 20:29:35 +08:00
Compilation . PROCESS _ASSETS _STAGE _OPTIMIZE _TRANSFER = 3000 ;
2020-08-19 03:14:43 +08:00
2020-05-12 18:16:51 +08:00
/ * *
* Analyse existing assets .
* /
Compilation . PROCESS _ASSETS _STAGE _ANALYSE = 4000 ;
/ * *
* Creating assets for reporting purposes .
* /
Compilation . PROCESS _ASSETS _STAGE _REPORT = 5000 ;
2017-01-06 01:00:36 +08:00
module . exports = Compilation ;