插件基本结构
在之前的源码解析中,我们知道webpack是提供了很多hook给插件去挂载(比如compiler和compilation实例都有很多hook),然后基于他的事件流触发他的钩子也就是触发插件的运行。
插件的运行环境
插件没有像loader那样的独立运行环境,只能在webpack中运行
插件的基本结构

可以看到插件有一个apply方法,这也是之前说到的 插件应用到compiler上面的方式,在apply中可以挂在compiler或者compilation上面的hook上。
搭建插件的运行环境
在配置文件的plugin配置属性中添加就可以
开发一个简单的插件
这个简单的插件,在webpack准备阶段,compiler实例刚刚被创建的时候,apply的时候就结束了所有的代码执行,就是在这个时候console了。
const path = require('path');const MyPlugin = require('./plugins/my-plugin');module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'main.js'},plugins: [new MyPlugin({name: 'my plugin'})]}// my-pluginmodule.exports = class MyPlugin {constructor (options) {this.options = options;}apply(compiler) {console.log('My plugin is executed!');console.log('My plugin options', this.options );}}
更复杂的插件开发场景
回想loader的开发过程,参数需要借助loader-utils这个npm包来获取,这个包还有其他功能比如说获取参数name中的占位符,并且根据具体占位符生成具体的输出文件名。
但是在插件中要获取参数比较简单,因为在webpack位置文件中,引入插件的时候就会创建实例,而参数就在创建实例的时候传进去了。因此插件的参数可以通过插件的构造函数获取。
// my-plugin
module.exports = class MyPlugin {
constructor (options) {
this.options = options;
}
apply(compiler) {
console.log('My plugin is executed!');
console.log('My plugin options', this.options );
}
}
参数的错误处理
- 在接受参数的阶段可以做参数的判断,比如需要的参数是否齐全,参数数据类型是否正确。这个阶段可以直接通过throw关键字抛出Error对象来抛出错误
- 如果在挂载阶段没问题,在触发的时候,hooks.xxx.call()时传参有问题,可以通过获取compiler中的compilation对象,使用compilation对象的warning和errors传递错误信息。

通过compilation进行文件写入
这里写错了compiler.plugin()应该改为compiler.hooks.emit.tap(),只传一个函数作为参数就可以了
插件扩展

实战开发一个压缩构建资源为zip包的插件
要求:
前提准备
我们需要知道怎么去生成一个zip包,这里使用一个npm包——jszip。还有怎么把这个包写入到磁盘中。
JSZip

Compiler上负责文件生成的hooks

