Compilation
模块会被 Compiler
用来创建新的 compilation 对象(或新的 build 对象)。
compilation
实例能够访问所有的模块和它们的依赖(大部分是循环依赖)。
它会对应用程序的依赖图中所有模块,
进行字面上的编译(literal compilation)。
在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、
分块(chunk)、哈希(hash)和重新创建(restore)。
Compilation
类扩展(extend)自 Tapable
,并提供了以下生命周期钩子。
可以按照 compiler 钩子的相同方式来调用 tap:
compilation.hooks.someHook.tap(/* ... */);
和 compiler
用法相同,取决于不同的钩子类型,
所以也可以在某些钩子上访问 tapAsync
和 tapPromise
。
SyncHook
在模块构建开始之前触发,可以用来修改模块。
module
compilation.hooks.buildModule.tap(
'SourceMapDevToolModuleOptionsPlugin',
(module) => {
module.useSourceMap = true;
}
);
SyncHook
在重新构建一个模块之前触发。
module
SyncHook
模块构建失败时执行。
module
error
SyncHook
模块构建成功时执行。
module
AsyncSeriesHook
所有模块都完成构建并且没有错误时执行。
modules
SyncHook
一个模块完成重新构建时执行,在都成功或有错误的情况下。
module
SyncHook
compilation 对象停止接收新的模块时触发。
SyncHook
compilation 对象开始接收新模块时触发。
SyncBailHook
依赖优化开始时触发。
modules
SyncHook
依赖优化之后触发。
modules
SyncHook
优化阶段开始时触发。
SyncBailHook
在模块优化阶段开始时调用。插件可以 tap 此钩子对模块进行优化。
modules
SyncHook
在模块优化完成之后调用。
modules
SyncBailHook
在 chunk 优化阶段开始时调用。插件可以 tap 此钩子对 chunk 执行优化。
chunks
SyncHook
chunk 优化完成之后触发。
chunks
AsyncSeriesHook
在优化依赖树之前调用。插件可以 tap 此钩子执行依赖树优化。
chunks
modules
SyncHook
在依赖树优化成功完成之后调用。
chunks
modules
SyncBailHook
在树优化之后,chunk 模块优化开始时调用。插件可以 tap 此钩子来执行 chunk 模块的优化。
chunks
modules
SyncHook
在 chunk 模块优化成功完成之后调用。
chunks
modules
SyncBailHook
调用来决定是否存储 record。返回任何内容 !== false
将阻止执行所有其他 "record" 钩子(record
, recordModules
, recordChunks
和 recordHash
)。
SyncHook
从 record 中恢复模块信息。
modules
records
SyncHook
在为每个模块分配 id
之前执行。
modules
SyncHook
调用来每个模块分配一个 id
。
modules
SyncHook
在模块 id
优化开始时调用。
modules
SyncHook
在模块 id
优化完成时调用。
modules
SyncHook
从 record 中恢复 chunk 信息。
chunks
records
SyncHook
在为每个 chunk 分配 id
之前执行。
chunks
SyncHook
调用时,会为每个 chunk 分配一个 id
。
chunks
SyncHook
在 chunk id
优化阶段开始时调用。
chunks
SyncHook
chunk id
优化结束之后触发。
chunks
SyncHook
将模块信息存储到 record 中。shouldRecord
返回 truthy 值时触发。
modules
records
SyncHook
将 chunk 存储到 record 中。shouldRecord
返回 truthy 值时触发。
chunks
records
SyncHook
在创建模块哈希(hash)之前。
syncHook
在创建模块哈希(hash)之后。
SyncHook
在 compilation 添加哈希(hash)之前。
SyncHook
在 compilation 添加哈希(hash)之后。
SyncHook
将有关 record 的信息存储到 records
中。仅在 shouldRecord
返回 truthy 值时触发。
records
SyncHook
将 compilation
相关信息存储到 record
中。仅在 shouldRecord
返回 truthy 值时触发。
compilation
records
SyncHook
在创建模块 asset 之前执行。
SyncHook
为这些 chunk 创建其他 asset。
chunks
SyncBailHook
调用以确定是否生成 chunk asset。返回任何 !== false
将允许生成 chunk asset。
SyncHook
在创建 chunk asset 之前。
AsyncSeriesHook
为 compilation 创建额外 asset。 这个钩子可以用来下载图像,例如:
compilation.hooks.additionalAssets.tapAsync('MyPlugin', (callback) => {
download('https://img.shields.io/npm/v/webpack.svg', function (resp) {
if (resp.status === 200) {
compilation.assets['webpack-version.svg'] = toAsset(resp);
callback();
} else {
callback(
new Error('[webpack-example-plugin] Unable to download the image')
);
}
});
});
AsyncSeriesHook
优化所有 chunk asset。asset 存储在 compilation.assets
中。
每个 Chunk
都具有一个 files
属性,其指向由一个 chunk 创建的所有文件。
任何额外 chunk asset 都存储在 compilation.additionalChunkAssets
中。
chunks
Here's an example that adds a banner to each chunk.
compilation.hooks.optimizeChunkAssets.tapAsync(
'MyPlugin',
(chunks, callback) => {
chunks.forEach((chunk) => {
chunk.files.forEach((file) => {
compilation.assets[file] = new ConcatSource(
'/**Sweet Banner**/',
'\n',
compilation.assets[file]
);
});
});
callback();
}
);
SyncHook
chunk asset 已经被优化。
chunks
这里是一个来自 @boopathi 的示例插件,详细地输出每个 chunk 里有什么。
compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', (chunks) => {
chunks.forEach((chunk) => {
console.log({
id: chunk.id,
name: chunk.name,
includes: chunk.getModules().map((module) => module.request),
});
});
});
AsyncSeriesHook
优化存储在 compilation.assets
中的所有 asset。
assets
SyncHook
asset 已经优化。
assets
AsyncSeriesHook
asset 处理.
Hook 参数:
name: string
— 插件名称stage: Stage
— a stage to tap into (see the list of supported stages below)additionalAssets?: true | (assets, [callback]) => (void | Promise<void>)
— a callback for additional assets (see below)回调参数:
assets: { [pathname: string]: Source }
— 普通对象,其中 key 是 asset 的路径名,value 是 asset 的数据,具体的代表请参考 Source
。示例:
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS, // see below for more stages
},
(assets) => {
console.log('List of assets and their sizes:');
Object.entries(assets).forEach(([pathname, source]) => {
console.log(`— ${pathname}: ${source.size()} bytes`);
});
}
);
除了 name
和 stage
以外,你还可以传递 additionalAssets
5.8.0+ 选项,此选项可接受 true
或者一个带有 assets
的函数作为参数:
true
- 针对插件后续添加的 asset 执行回调。
在此模式下,回调将被多次调用:一次是在指定阶段之前添加资产时,另一次是后来由插件添加资产时。(在本阶段或下一阶段)。
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: true,
},
(assets) => {
// this function will be called multiple times with each bulk of assets
}
);
(assets, [callback]) => (void | Promise<void>)
- 针对插件后续添加的 asset 执行指定的回调(在本阶段或下一阶段)。回调必须遵循所使用的 tap 函数的类型(例如,当与 tapPromise()
一同使用时,它应该返回一个 Promise)。
compilation.hooks.processAssets.tap(
{
name: 'MyPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: (assets) => {
// this function potentially could be called multiple times for assets added on later stages
},
},
(assets) => {
// this function will be called once with assets added by plugins on prior stages
}
);
如下是我们可以使用的 stage 清单(按顺序处理):
PROCESS_ASSETS_STAGE_ADDITIONAL
— 在编译中添加额外的 asset。PROCESS_ASSETS_STAGE_PRE_PROCESS
— asset 进行了基础预处理。PROCESS_ASSETS_STAGE_DERIVED
— 从已有 asset 中获取新的 asset。PROCESS_ASSETS_STAGE_ADDITIONS
— 为现有的 asset 添加额外的内容,例如 banner 或初始代码。PROCESS_ASSETS_STAGE_OPTIMIZE
— 以通用的方式优化已有 asset。PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT
— 优化现有资产的数量,例如,进行合并操作。PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY
— 优化现有 asset 兼容性,例如添加 polyfills 或者 vendor prefixes。PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
— 优化现有 asset 大小,例如进行压缩或者删除空格。PROCESS_ASSETS_STAGE_DEV_TOOLING
— 为 asset 添加开发者工具,例如,提取 source map。PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE
5.8.0+ — 优化已有 asset 数量,例如,通过将 asset 内联到其他 asset 中。PROCESS_ASSETS_STAGE_SUMMARIZE
— 整理现有 asset 列表。PROCESS_ASSETS_STAGE_OPTIMIZE_HASH
— 优化 asset 的 hash 值,例如,生成 asset 内容的真实 hash 值。PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER
— 优化已有 asset 的转换操作,例如对 asset 进行压缩,并作为独立的 asset。PROCESS_ASSETS_STAGE_ANALYSE
— 分析已有 asset。PROCESS_ASSETS_STAGE_REPORT
— 创建用于上报的 asset。"asset info" 元数据不会自动提供给这个 hook。如果必须使用,你需要通过编译实例以及 asset 路径来手动获取这个元数据。这将在未来的 webpack 版本中得到改善。
Example:
compilation.hooks.processAssets.tap(
{
/** … */
},
(assets) => {
Object.entries(assets).forEach(([pathname, source]) => {
const assetInfo = compilation.assetsInfo.get(pathname);
// @todo: do something with "pathname", "source" and "assetInfo"
});
}
);
SyncHook
在 processAssets
hook 无错误执行后调用。
SyncBailHook
调用来决定 compilation 是否需要解除 seal 以引入其他文件。
AsyncSeriesHook
在 needAdditionalSeal
之后立即执行。
SyncHook
触发来为每个 chunk 生成 hash。
chunk
chunkHash
SyncHook
一个模块中的一个 asset 被添加到 compilation 时调用。
module
filename
SyncHook
一个 chunk 中的一个 asset 被添加到 compilation 时调用。
chunk
filename
SyncWaterfallHook
调用以决定 asset 的路径。
path
options
SyncBailHook
调用以决定 asset 在输出后是否需要进一步处理。
SyncHook
子 compiler 设置之后执行。
childCompiler
compilerName
compilerIndex
从 webpack v5 开始,normalModuleLoader
钩子已经删除。现在要访问 loader 请改用 NormalModule.getCompilationHooks(compilation).loader
。
Webpack 5 现已正式发布。请阅读我们的 发布公告。如还未准备升级,请阅读 webpack 4 文档。