案例实战之如何写一个webpack plugin
1.写一个生成打包文件目录的file.md文件
// 生成一个目录项目目录的文件夹
class FileListPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.hooks.emit.tap('fileListPlugin', (compilation) => {
let assets = compilation.assets
let content = 'In this build:\r\n'
Object.entries(assets).forEach(([fileName, fileSize]) => {
content += `--${fileName} —— ${Math.ceil(fileSize.size() / 1024)}kb\r\n`
})
console.log('====content====', content)
assets[this.options.filename] = {
source() {
return content
},
size() {
return content.length
}
}
})
}
}
module.exports = FileListPlugin
使用
const FileListPlugin = require('./plugins/fileListPlugin.js')
plugins:[
new FileListPlugin({
filename: 'filelist.md'
}),
]
生成的结果如下
![image-20191206173728326](F:\myobject\vue2\myb
2.写一个生成版权信息的copyright文件的插件
class CopyRightWebpackPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.hooks.compile.tap('webpackCompiler', () => {
console.log('compiler')
})
compiler.hooks.emit.tapAsync('CopyRightWebpackPlugin', (compilation, cb) => {
compilation.assets[this.options.filename] = {
source() {
return 'copyRight by heibao'
},
size() {
return 25
}
}
cb()
})
}
}
module.exports = CopyRightWebpackPlugin
webpack 的源码compiler钩子函数是借助tapable库实现的
const {
Tapable,
SyncHook,
SyncBailHook,
AsyncParallelHook,
AsyncSeriesHook
} = require("tapable");
class Compiler extends Tapable {
constructor(context) {
super();
this.hooks = {
/** @type {SyncBailHook<Compilation>} */
shouldEmit: new SyncBailHook(["compilation"]),
/** @type {AsyncSeriesHook<Stats>} */
done: new AsyncSeriesHook(["stats"]),
/** @type {AsyncSeriesHook<>} */
additionalPass: new AsyncSeriesHook([]),
/** @type {AsyncSeriesHook<Compiler>} */
beforeRun: new AsyncSeriesHook(["compiler"]),
/** @type {AsyncSeriesHook<Compiler>} */
run: new AsyncSeriesHook(["compiler"]),
/** @type {AsyncSeriesHook<Compilation>} */
emit: new AsyncSeriesHook(["compilation"]),
/** @type {AsyncSeriesHook<string, Buffer>} */
assetEmitted: new AsyncSeriesHook(["file", "content"]),
/** @type {AsyncSeriesHook<Compilation>} */
afterEmit: new AsyncSeriesHook(["compilation"]),
/** @type {SyncHook<Compilation, CompilationParams>} */
thisCompilation: new SyncHook(["compilation", "params"]),
/** @type {SyncHook<Compilation, CompilationParams>} */
compilation: new SyncHook(["compilation", "params"]),
/** @type {SyncHook<NormalModuleFactory>} */
normalModuleFactory: new SyncHook(["normalModuleFactory"]),
/** @type {SyncHook<ContextModuleFactory>} */
contextModuleFactory: new SyncHook(["contextModulefactory"]),
/** @type {AsyncSeriesHook<CompilationParams>} */
beforeCompile: new AsyncSeriesHook(["params"]),
/** @type {SyncHook<CompilationParams>} */
compile: new SyncHook(["params"]),
/** @type {AsyncParallelHook<Compilation>} */
make: new AsyncParallelHook(["compilation"]),
/** @type {AsyncSeriesHook<Compilation>} */
afterCompile: new AsyncSeriesHook(["compilation"]),
/** @type {AsyncSeriesHook<Compiler>} */
watchRun: new AsyncSeriesHook(["compiler"]),
/** @type {SyncHook<Error>} */
failed: new SyncHook(["error"]),
/** @type {SyncHook<string, string>} */
invalid: new SyncHook(["filename", "changeTime"]),
/** @type {SyncHook} */
watchClose: new SyncHook([]),
/** @type {SyncBailHook<string, string, any[]>} */
infrastructureLog: new SyncBailHook(["origin", "type", "args"]),
// TODO the following hooks are weirdly located here
// TODO move them for webpack 5
/** @type {SyncHook} */
environment: new SyncHook([]),
/** @type {SyncHook} */
afterEnvironment: new SyncHook([]),
/** @type {SyncHook<Compiler>} */
afterPlugins: new SyncHook(["compiler"]),
/** @type {SyncHook<Compiler>} */
afterResolvers: new SyncHook(["compiler"]),
/** @type {SyncBailHook<string, Entry>} */
entryOption: new SyncBailHook(["context", "entry"])
};
}}
上面的钩子函数是在webpack解析代码的不同周期执行的