这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。
如何写一个 webpack plugin
什么是 plugin
在webpack运行的声明周期中会广播许多事件,plugin可以监听这些事件,在特定的时刻调用webpack提供的API执行相应的操作。
plugin 和 loader 的区别
上一章简单介绍了什么是 loader 以及如何编写一个简单的 loader,那么 plugin 和 loader 有什么区别?
loader我们通常翻译为“加载器”,它提供了在webpack打包后对源码字符串的转译能力,尤其是对非 javascript 的文件。
plugin我们通常翻译为“插件”,插件可以让webpack的变得更加灵活。Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
如何写一个 plugin
1.创建文件 index.js
console.log('hello ouda')
里面仅仅一行代码,打印 hello ouda
2.执行 webpack 打包
$yarn init -y
$yarn add webpack webpack-cli
$npx webpack
执行打包结果:
3.写一个 plugin
plugin 是一个具有 apply 方法的 JavaScript 对象。apply 方法会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。
plugin 的基本架构:
class myPlugin {
constructor () {
}
apply (compiler) {
}
}
module.exports = myPlugin
可以看到,这里的插件本质是一个 class , 他有一个 构造方法 conctuctor 和 一个 apply方法, apply方法有一个入参 compiler
3.1为什么要写 apply?
apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法可以接收一个 webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。
3.2什么是 compiler?
Compiler 对象包含了 Webpack 环境所有的的配置信息,包含 options,loaders,plugins 这些信息,这个对象在 Webpack 启动时候被实例化,它是全局唯一的,可以简单地把它理解为 Webpack 实例
关于 compiler 的一些钩子: compiler api
3.3 获取 plugin 传递参数
在使用 plugin 时同时也是可以传递参数的,咱们 plugin 的本质是类,所以通过 new 的构造方法,可以在 plugin constructor 中被传递过来。
配置 webpack.config.js
const MyPlugin = require('./plugin/index')
module.exports = {
entry: './src/index',
plugins: [ // 使用自己写的 plugin
new MyPlugin({
name: 'ouda'
})
]
}
在 插件中获取并且打印传递的参数:
plugin/index.js:
class MyPlugin {
constructor(options) {
this.options = options
console.log('options: ' + JSON.stringify(this.options))
}
apply(compiler) {
console.log('apply options: ' + JSON.stringify(this.options))
}
}
module.exports = MyPlugin
$npx webpack
运行结果:
成功获得传递的参数。这些参数是可以在 apply 函数中被使用的。
3.4 写一个钩子
生命周期函数是由 compiler 暴露, 可以通过如下方式访问:
compiler.hooks.someHook.tap('MyPlugin', (params) => {
/* ... */
});
关于 compiler 的一些钩子: compiler api
尝试调用一个 beforeRun 钩子:
class MyPlugin {
constructor(options) {
this.options = options
console.log('options: ' + JSON.stringify(this.options))
}
apply(compiler) {
compiler.hooks.beforeRun.tap('MyPlugin', (params) => {
console.log('before run ', params)
});
}
}
module.exports = MyPlugin
打包后是能够看到打印结果的。
这样就完成了一个最简单的 plugin。