webpack中的插件,同步插件、异步插件
本节来实现webpack的插件
- 同步插件,打包结束后,输出一个打包成功的提醒
- 异步插件,打包过程中,停顿一秒再继续打包
准备一个空项目
新建一个空项目 webpack-plugin
初始化package.json
shell
yarn init -y
安装webpack
shell
yarn add webpack@^4.32.2 webpack-cli@^3.3.2 -D
新建index.js
js
// webpack\webpack-plugin\src\index.js
console.log('xzz && cheny');
新建配置文件
js
// webpack\webpack-plugin\webpack.config.js
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
打包测试结果 npx webpack
分析一下源码,看看如何写插件
在使用 npx webpack 打包时
在执行编译时 会调用 compiler.js 文件,webpack\webpack-plugin\node_modules\webpack\lib\Compiler.js
会判断配置文件中有没有配置插件,如果有,就调用插件中的apply方法,并会把这个实例传过去。
这个实例上就有很多钩子。
实现一个同步钩子插件
打包结束后,输出一个打包成功的提醒
js
// webpack\webpack-plugin\plugins\DonePlugin.js
class DonePlugin {
apply(compiler) {
// done 钩子 在所有编译结束后执行
compiler.hooks.done.tap('DonePlugin', (stats) => {
console.log('编译完成');
})
}
}
module.exports = DonePlugin
修改配置文件
js
// webpack\webpack-plugin\webpack.config.js
let path = require('path')
let DonePlugin = require('./plugins/DonePlugin.js')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new DonePlugin(), // 引入自己写的插件
]
}
打包测试结果,最后输出结果,成功
实现一个异步钩子插件
打包过程中,停顿一秒再继续打包
js
// webpack\webpack-plugin\plugins\AsyncPlugin.js
class AsyncPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('AsyncPlugin', (compliation, cb) => {
setTimeout(() => {
console.log('文件发射出来了,在这里等一秒');
cb()
}, 1000)
})
compiler.hooks.emit.tapPromise('AsyncPlugin', (compliation) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('文件发射出来了,再等一秒');
resolve()
}, 1000)
})
})
}
}
module.exports = AsyncPlugin
修改配置文件
js
// webpack\webpack-plugin\webpack.config.js
let path = require('path')
let DonePlugin = require('./plugins/DonePlugin.js')
let AsyncPlugin = require('./plugins/AsyncPlugin.js')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new DonePlugin(), // 引入自己写的插件
new AsyncPlugin(), // 引入自己写的插件
]
}
打包测试结果,间隔了一秒才继续打包,成功
总结
webpack的插件机制,实际就是发布订阅,在new Compiler示例,构造方法执行时,就在实例上注册了几个钩子函数。
在编写插件的时候,从实例上获取到对应的钩子,注册任务,实际就是将这些任务先存储到一个数组中。
然后打包的过程中,执行到某一步时,就调用对应的任务。
webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来。
而实现这一切的核心就是Tapable。
Tapable有点类似于nodejs的events库,核心原理也是依赖发布订阅模式。
- 注册任务
- 同步注册 tap
- 异步注册 tapAsync、tapPromise
- 调用任务
- 同步调用 call
- 异步调用 callAsync、promise
在之前的章节中学习过。
参考
https://www.bilibili.com/video/BV1a4411e7Bz?p=47&spm_id_from=pageDriver
http://www.bnbiye.cn/#/articleDetail/48892d00-80dd-11ec-a014-a1cd819f9587