插件用于以各种方式自定义 webpack 构建过程。
webpack 附带了各种内置插件,可以通过 webpack.[plugin-name] 访问这些插件。
module.exports = {
//...
plugins: [
new webpack.DefinePlugin({
// Definitions...
}),
],
};
-
模块
-
命名
-
输出
-
优化
-
日志
-
分析
-
其他
- dotenv-webpack
- webpack-flush-chunks
- webpack-isomorphic-tools
- compression-webpack-plugin
- sw-precache-webpack-plugin
- browser-sync-webpack-plugin
- npm-install-webpack-plugin
- webpack-shell-plugin
- webpack-livereload-plugin
- start-server-webpack-plugin
- open-browser-webpack-plugin
- i18n-webpack-plugin
- appcache-webpack-plugin
- 实例化:插件在创建 webpack 配置文件时实例化
- 初始化:插件实例的 apply 方法在 webpack 编译器安装插件时调用一次
- 注册钩子:apply 方法里注册事件钩子,在 webpack 构建至对应事件阶段时,调用注册的钩子函数
- 操作构建:钩子函数执行时会传入相应构建阶段的内部对象,这些对象暴露了操作构建的方法,详见 Plugin API
- 结束:插件完成了构建操作后需要通知 webpack 结束本次钩子操作,可以通过回调或者返回 promise 的方式。
创建插件
const validateOptions = require('schema-utils');
// 常见名称,通常命名为 XxxWebpackPlugin
const pluginName = 'HelloWorldWebpackPlugin';
// 插件配置校验规则
const schema = {
type: 'object',
properties: {
message: {
type: 'string',
},
},
};
// 默认配置
const defaultOptions = {
message: 'Hello World!',
};
// 插件实现主体以类的形式声明
class HelloWorldWebpackPlugin {
// 在配置 webpack 的时候,创建插件实例
constructor(options = defaultOptions){
validateOptions(schema, options, pluginName);
this.options = options;
}
// 在 webpack 初始化的时候调用插件 apply 防范,并传入编译器实例
apply(compiler) {
// 注册钩子函数
compiler.hooks.emit.tapAsync(
pluginName,
(compilation, callback) => {
console.log(this.options.message);
// 通过 webpack API 操作构建编译结果
compilation.addModule(/* ... */);
callback();
}
);
}
}
module.exports = HelloWorldPlugin;
使用插件
// webpack.config.js
module.exports = {
plugins: [
HelloWorldPlugin({ message: 'Hello World!' }),
],
};
Tapable 是 Webpack 插件架构的核心支架,但它的源码量其实很少,本质上就是围绕着 订阅/发布 模式叠加各种特化逻辑,适配 webpack 体系下复杂的事件源-处理器之间交互需求,比如说有些场景需要支持将前一个处理器的结果传入下一个回调处理器;有些场景需要支持异步并行调用这些回调处理器。
插件操作构建可能是同步或者异步的,相应的需要调用不同的函数进行注册
-
同步:
compiler.hooks.emit.tap
-
异步:
compiler.hooks.emit.tapAsync
:钩子函数最后一个是一个回调函数,异步任务完成后要调用改函数compiler.hooks.emit.tapPromise
:钩子函数返回一个 Promise
- Compiler:Compiler 是 webpack 的编译器实例,它基于 wbepack 配置创建 Compilation。
- Compilation:Compilation 代表某次 Compiler 的编译过程和结果,通过它可以访问项目所有的模块和依赖。
- 操作构建结果:参见 Compilation
- ...
参照 html-webpack-plugin 的自定义钩子实现思路。