通过 Webpack 的 compiler 对象的 Hooks 学会编写 Webpack 插件的编写
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 如何让你的回调 Promise 化?
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论