0%

编写一个插件

webpack插件由以下组成:

一个javaScript命名函数或者JavaScript类

由插件函数的prototype上定义的一个apply方法

指定一个绑定到webpack自身的事件钩子

处理webpack内部实例的特定数据

功能完成后调用webpack提供的回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 一个 JavaScript 类
class MyExampleWebpackPlugin {
// 在插件函数的 prototype 上定义一个 `apply` 方法,以 compiler 为参数。
apply(compiler) {
// 指定一个挂载到 webpack 自身的事件钩子。
compiler.hooks.emit.tapAsync(
'MyExampleWebpackPlugin',
(compilation, callback) => {
console.log('这是一个示例插件!');
console.log(
'这里表示了资源的单次构建的 `compilation` 对象:',
compilation
);

// 用 webpack 提供的插件 API 处理构建过程
compilation.addModule(/* ... */);

callback();
}
);
}
}

webpack通过plugin机制让其更加灵活,以适应各种应用场景,在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果

Compiler和Compilation

插件开发中最重要的两个资源就是compiler和compilation对象,理解它们的角色是扩展webpack引擎重要的第一步

compiler对象代表了完整的webpack环境配置,这个对象在启动webpack时被一次性实例化,可以简单理解为webpack实例,并配置好所有可操作的设置,包括options,loader和plugin。当在webpack环境中启用一个插件时,插件将受到compiler对象的引用,可以使用它来访问webpack的主环境

compilation对象代表一次资源版本构建,当运行webpack开发环境中间件时,每当检测一个文件变化,就会创建一个新的compilation,从而生成一组新的编译资源,一个compilation对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖大的状态信息。compilation对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用,通过compilation也能读取到compiler对象

compiler和compilation区别在于:compiler代表了整个webpack从启动到关闭的生命周期,而compilation只是代表了一次新的编译

基本插件架构

插件是由具有apply方法的prototype对象所实例化出来的,这个apply方法在安装插件时,会被webpack compiler调用一次,apply方法可以接受一个webpack compiler对象的引用,从而可以在回调函数中访问到compiler对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap(
'Hello World Plugin',
(
stats /* 绑定 done 钩子后,stats 会作为参数传入。 */
) => {
console.log('Hello World!');
}
);
}
}

module.exports = HelloWorldPlugin;

安装插件:

1
2
3
4
5
6
7
// webpack.config.js
var HelloWorldPlugin = require('hello-world');

module.exports = {
// ... 这里是其他配置 ...
plugins: [new HelloWorldPlugin({ options: true })],
};