闽公网安备 35020302035485号
2.Plugin 插件
const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParalleHook,
AsyncParalleBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesLoopHook,
AsyncSeriesWaterfallHook
} = require("tapable");
tapable提供了上述十大Hook类以及三种实例方法:tap、tapAsync和tapPromise,为Webpack整个工作创建了观察 -> 触发插件的工作流。compiler = new Compiler(options.context);
compiler.options = options;
if (options.plugins && Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
if (typeof plugin === "function") {
plugin.call(compiler, compiler);
} else {
plugin.apply(compiler);
}
}
}
可以看到,如果在webpack.config.js中配置了plugins并且他是个数组,webpack会依次去执行每一个plugin,并且把compiler传给每一个plugin。class Compiler extends Tapable {}
class Compilation extends Tapable {}
其实就是继承于Tapable的子类,那么Tapable的观察者模式就可以对上了,Compiler基于观察者模式,设计出了一系列的生命周期钩子函数。基于tapable的支持,Webpack插件系统中提供了大量的生命周期钩子函数,让每一个插件都可以在需要的时候去执行。
class HelloPlugin {
constructor(options) {
console.log(options);
}
apply(compiler) {
compiler.hooks.done.tap('HelloPlugin', () => {
console.log('HelloPlugin');
}
}
}
并在webpack.config.js中定义:const HelloPlugin = require('./HelloPlugin.js');
module.exports = {
...
plugins: [
new HelloPlugin(),
],
...
}
执行npx webpack,可以看到打印结果。const fs = require('fs');
class CopyPlugin {
constructor(options) {
this.from = options.from;
this.to = options.to;
}
apply(compiler) {
const { from, to } = this;
const isDir = fs.statSync(from).isFile() ? false : true;
compiler.hooks.done.tap('CopyPlugin', () => {
fs.cp(from, to, { recursive: isDir }, (err) => {
if (err) {
throw err;
}
})
})
}
}
module.exports = CopyPlugin;
在webpack.config.js中配置:const path = require('path');
const CopyPlugin = require('./copyPlugin');
module.exports = {
...
plugins: [
new CopyPlugin({
from: path.resolve(__dirname, 'static'),
to: path.resolve(__dirname, 'dist', 'static')
})
],
...
}
这里我们选择将static文件夹复制到dist目录中,使用方式和原来的一样,执行npx webpack可以看到:
const fs = require('fs');
const path = require('path')
class CleanPlugin {
apply(compiler) {
compiler.hooks.make.tap('CleanPlugin', () => {
function clearDir(dirPath) {
let files = []
if (fs.existsSync(dirPath)) {
files = fs.readdirSync(dirPath)
files.forEach(f => {
const absPath = dirPath + '/' + f;
if (fs.statSync(absPath).isDirectory()) {
clearDir(absPath);
} else {
fs.unlinkSync(absPath);
}
})
}
}
clearDir(path.resolve(__dirname, 'dist'))
})
}
}
module.exports = CleanPlugin;
在webpack.config.js中配置:const path = require('path');
const CleanPlugin = require('./CleanPlugin');
module.exports = {
...
plugins: [
new CleanPlugin(),
],
...
}
运行npx webpack,会发现,在打包中,目录被清除了,最后又出现文件了。