webpack 的 Hooks
Webpack 的 Compiler 对象主要有以下 Hooks:
- entryOption
webpack 处理完 entry 配置项后触发,这是一个同步串行的 SyncBailHook 钩子,只要监听函数有一个函数的返回值不为undefined,则直接跳过剩下逻辑
无参数
- afterPlugins
处理完初始化插件后触发,这是一个同步的 SyncHook 钩子,不关心返回值
参数是 compiler 对象
- afterResolvers
Resolve 安装完成后触发,这是一个同步的 SyncHook 钩子
参数是 compiler 对象
- environment
environment 准备好后触发,这是一个 SyncHook 钩子
无参数
- afterEnvironment
environment 安装完成后触发,这是一个 SyncHook 钩子
- beforeRun
compiler.run
函数之前触发,这是一个异步串行 AsyncSeriesHook 钩子
参数是 compiler
- run
开始读取 records 之前触发,这是一个异步串行 AsyncSeriesHook 钩子
参数是 compiler
- watchRun
监听模式下,一个新的编译开始之前触发,这是一个异步串行的 AsyncSeriesHook 钩子
参数是 compiler
- normalModuleFactory
normalModuleFactory
创建之后触发,这是一个同步 SyncHook 钩子
参数是 normalModuleFactory
- contextModuleFactory
contextModuleFactory
创建之后触发,
参数是 contextModuleFactory
- beforeCompile
编译参数创建之后触发,这是一个异步串行 AsyncSeriesHook 钩子
参数是 compilationParams
- compile
一个新的编译创建之后触发,这是一个同步 SyncHook 钩子
参数是 compilationParams
- thisCompilation
触发 compilation 之前触发,这个是一个同步 SyncHook 钩子
参数是 compilation
- compilation
编译创建之后执行,这是一个同步 SyncHook 钩子
参数是 compilation
- make
这是一个异步并发 AsyncParallelBailHook 钩子
参数是 compilation
- afterCompile
这是一个异步串行 AsyncSeriesHook 钩子
参数是 compilation
- shouldEmit
这是一个 SyncBailHook 钩子
参数是 compilation
- emit
生成资源到 output 目录之前触发,这是一个异步串行 AsyncSeriesHook 钩子
参数是 compilation
- afterEmit
生成资源到 output 目录之后,这是一个异步串行 AsyncSeriesHook 钩子
参数是 compilation
- done
编译完成后触发,这是一个异步串行 AsyncSeriesHook 钩子
参数是 stats
- failed
编译失败触发,这是一个同步 SyncHook 钩子
参数是 error
- invalid
监听模式下,编译无效时触发,这是一个同步 SyncHook 钩子
参数是 fileName,changeTime
+ watchClose
监听模式停止,一个同步 SyncHook 钩子
插件编写实例
webpack-clear-console
通过实例学习是最快的,让我们看一个最简单的例子,webpack-clear-console,这个插件是去除输出里的 console
调用,里面插件的写法是 webpack4 之前的写法,不过基本上是一致的,通过源码可以看到插件在 emit
这个钩子上(生成资源到output目录之前)触发,通过 compilation
对象的 assets
对象的 source
方法获取文件内容,然后进行正则匹配。
最后需要将 source
和 size 的变动归回原来的 compilation
对象中,否则这些变动是不会生效的
island-webpack-plugin
island-webpack-plugin 是一个在 bundle 中添加作者信息的插件,这个插件同样是在 emit
这个钩子上触发的,同样是获取 source
后对 source
添加作者信息的字符串。
emit
是一个异步的钩子,可以使用 promise 的 如下,可以使用 promise 对上面的插件进行简单改造,以 island-webpack-plugin 为例,改造如下:
class AuthorPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.emit.tap(author-plugin, (compilation) => {
const options = this.options
return new Promise((resolve, reject) => {
const assets = compilation.assets
Object.keys(assets).forEach(e => {
let source = assets[e].source()
let info = []
if (options.author) info.push(`@Author: ${options.author}`)
if (options.email) info.push(`@Email: ${options.email}`)
if (options.homepage) info.push(`@Homepage: ${options.homepage}`)
if (info.length) {
info.push(`@Date: ${new Date()}`)
source = `/*n ${info.join(nn )}n*/n${source}`
}
compilation.assets[e].source = () => source
compilation.assets[e].size = () => source.size
})
resolve()
})
})
}
}
module.exports = AuthorPlugin
请登录后查看评论内容