插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。插件能够 钩入(hook) 到在每个编译(compilation)中触发的所有关键事件。在编译的每一步,插件都具备完全访问 compiler
对象的能力,如果情况合适,还可以访问当前 compilation
对象。
创建插件比创建 loader 更加高级,因为你将需要理解一些 webpack 底层的内部特性来做相应的钩子。
webpack
插件由以下组成:
apply
方法。// A JavaScript class.
class MyExampleWebpackPlugin {
// Define `apply` as its prototype method which is supplied with compiler as its argument
apply(compiler) {
// Specify the event hook to attach to
compiler.hooks.emit.tapAsync(
'MyExampleWebpackPlugin',
(compilation, callback) => {
console.log('This is an example plugin!');
console.log('Here’s the `compilation` object which represents a single build of assets:', compilation);
// Manipulate the build using the plugin API provided by webpack
compilation.addModule(/* ... */);
callback();
}
);
}
}
插件是在其原型上拥有 apply 方法的实例化对象。在安装插件时,webpack编译器会调用这个apply方法一次。apply方法有一个对底层webpack编译器的引用,它授予对编译器回调的访问权。一个简单的插件结构如下:
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap('Hello World Plugin', (
stats /* stats is passed as an argument when done hook is tapped. */
) => {
console.log('Hello World!');
});
}
}
module.exports = HelloWorldPlugin;
这里回调函数的参数 stats 其实结构如下:
image.png
然后,要安装这个插件,只需要在你的 webpack 配置的 plugin 数组中添加一个实例:
// webpack.config.js
var HelloWorldPlugin = require('hello-world');
module.exports = {
// ... configuration settings here ...
plugins: [new HelloWorldPlugin({ options: true })]
};
还可以使用' schema-utils '来验证通过插件 options 选项传递的参数。这里有一个例子:
import validateOptions from 'schema-utils';
// schema for options object
const schema = {
type: 'object',
properties: {
test: {
type: 'string'
}
}
};
export default class HelloWorldPlugin {
constructor(options = {}){
validateOptions(schema, options, {
name: 'hello-world-plugin', // 报错时,输出的插件名名称。其他配置项参考 schema-utils 文档
});
}
apply(compiler) {}
}
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
compiler
对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。compilation
对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。这两个组件是任何 webpack 插件不可或缺的部分(特别是 compilation
),因此,开发者在阅读源码,并熟悉它们之后,会感到获益匪浅:
class HelloCompilationPlugin {
apply(compiler) {
// Tap into compilation hook which gives compilation as argument to the callback function
compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => {
// Now we can tap into various hooks available through compilation
compilation.hooks.optimize.tap('HelloCompilationPlugin', () => {
console.log('Assets are being optimized.');
});
});
}
}
module.exports = HelloCompilationPlugin;
有关compiler、compillation 和其他重要对象的钩子列表,请参阅plugins API文档。
writing-a-plugin 创建插件 api/plugins/ cn/api/plugins/ schema-utils