定义
webpack plugins是一个通过注册webpack自身编译过程中触发的生命周期钩子来实现访问和处理编译过程的javaScript函数或class。插件的使用范围从打包优化、压缩,一直到重新定义环境中的变量。
插件类型
- 按照插件所注册的事件分类
- 同步钩子
- SyncHook(同步钩子,被一个接一个地调用)
- Bail Hooks(同
SyncHook类似,如果该类型任何插件返回了除undefined之外的任意值,则值由该钩子返回并不会执行剩余的该类型钩子,如optimizeChunks、optimizeChunkModules等) - Waterfall Hooks(同
SyncHook类似,但将每个钩子的返回值传递给下一个钩子,如ModuleTemplate、ChunkTemplate等)
- 异步钩子
- Async Series Hooks(与
SyncHook类似,但钩子的回调函数是异步的,该钩子被一个接一个地调用) - Async waterfall Hooks(与
Waterfall Hooks类似,但钩子的回调函数是异步的) - Async Series Bail Hooks(与
Bail Hooks类似,但钩子的回调函数是异步的) - Async Parallel Hooks(与
Async Series Hooks类似,但被并行调用)
- Async Series Hooks(与
- 同步钩子
- 按照所属模块分类
Compiler钩子,Compiler对象代表了完整的webpack环境配置;Compilation钩子,Compilation对象代表了一次资源版本构建;
常用的插件
webpackbarwebpack 优雅的进度条和分析器;webpack.DefinePlugin在编译时使用特定值或表达式定义全局变量;webpack.HotModuleReplacementPlugin热更新插件(webpack v4 默认启用HMR);friendly-errors-webpack-plugin识别并整理、排序webpack 错误,为开发者提供更好的体验;webpack.optimize.CommonsChunkPlugin将公共模块组合到新的文件,减少公共代码的冗余;mini-css-extract-plugin将CSS提取成单独的文件,支持异步加载、不需重复编译;extract-text-webpack-plugin【已废弃】从一个或多个bundle中提取文本到一个单独的文件中;html-webpack-plugin创建 html 文件;fork-ts-checker-webpack-plugin在一个单独的进程上运行typeScript 类型检查;moment-locales-webpack-plugin轻松删除moment.js中未使用的locales;hard-source-webpack-plugin为模块提供一个中间缓存;VueLoaderPlugin配合vue-loader 15.x使用,用来处理vue 模块的module rule;copy-webpack-plugin将已存在的单个文件或整个目录复制到构建目录;webpack-bundle-analyzer树状图形式的bundle内容分析工具;
用法
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 生成html的插件
const webpack = require('webpack');
const config = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'}) // 使用new 操作符新建插件实例进而添加插件,通过选项(option)自定义。
]
};
module.exports = config;
运行原理
插件的本质是一个注册到Compiler钩子或Compilation钩子上的对象,而Compiler钩子或Compilation钩子均是继承自Tabable Hooks 类,该类支持使用tap或tapAsync、tapPromise来注册钩子处理函数,然后webpack 会在特定编译时机通过call或callAsync执行钩子处理函数,整个处理过程类似Node.js的EventEmitter 类。
制作插件
// plugins.js
const pluginName = 'testWebpackPlugins';
class MyWebpackPlugins {
// 插件实例化的入参
constructor(props){
console.log("props:", props);
}
// 在原型上定义的apply方法
apply(compiler){
// 使用beforeRun钩子
compiler.hooks.beforeRun.tapAsync(pluginName, (compiler, callback) => {
/* 逻辑处理 */
console.log("compiler:", compiler);
console.log("webpack即将构建");
callback()
})
// 使用emit钩子
compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) => {
/* 逻辑处理 */
console.log("compilation:", compilation);
console.log("即将生成资源到 output 目录");
callback()
});
}
}
module.exports = {
MyWebpackPlugins,
}
// webpack-config.js
const { MyWebpackPlugins} = require("./plugins"); // 引入插件
module.exports = {
// ... configuration settings here ...
plugins: [new MyWebpackPlugins({test:123})] // 注册插件
};