插件plugin
插件是 webpack
除了loader
以外的另一个核心功能。而通过对Webpack
源码的观察,我们发现Webpack
自身也是构建于各类插件之上。
插件目的在于解决上一篇文章所介绍的loader 无法实现的事。通过上篇文章的介绍,我们知道了loader
的主要作用是对各类的文件的解析、预处理。但如果仅有这些对于我们的日常开发是远远不够的,这也是插件所补充的部分。
如何使用插件
我们日常开发中如果需要使用Webpack
插件,就需要在webpack.config.js
中进行配置,比如:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /.(js|jsx)$/,
use: 'babel-loader',
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
};
上面的例子中首先通过require
加载通过npm安装的插件,接着在module.exports
中的plugins
中传入我们所需要的插件的实例,这里通过new
来创建一个插件的实例并进行加载。这里的例子是一个解析html
的插件,插件需要传入一个参数是需要处理的html
的相对路径,然后插件内部对该html进行解析,构建。该插件将为你生成一个 HTML5 文件, 在 body 中使用 script
标签引入你所有 webpack 生成的 bundle。HtmlWebpackPlugin
简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。
一个插件是如何开发的
plugins
是可以用自身原型方法apply
来实例化的对象。apply
只在安装插件被Webpack compiler
执行一次。apply
方法传入一个webpck compiler
的引用,来访问编译器回调。一个简单的插件代码结构是这样:
class Plugin {
constructor(options) {}
apply(compiler) {
//...
}
}
module.exports = Plugin
这里以HtmlWebpackPlugin
的代码为例:
apply(compiler){
compiler.hooks.make.tapAsync(
//...
)
}
这里的compiller.hooks.make()
函数,这是一个异步并发 AsyncParallelBailHook
钩子,也就是在编译完成之前执行的钩子函数,compiler里有很多钩子函数是在webpack
的compile
编译过程的不同阶段进行操作的钩子,这样也就扩展了我们的webpack
的功能。
插件的执行过程
首先介绍一下Compiler
,Compiler
模块是 webpack 的核心引擎,它通过 CLI 或 Node API 传递的所有选项,创建出一个 compilation 实例。它扩展(extend)自 Tapable
类,以便于我们注册和调用插件。大多数面向用户的插件首先在 Compiler
上注册。
监听
Compiler
支持可以监控文件系统的监听(watching)机制,并且在文件修改时重新编译。当处于监听模式(watch mode)时,compiler 会触发诸如watchRun
,watchClose
和invalid
等额外的事件。通常用于开发环境中使用,也常常会在webpack-dev-server
这些工具的底层之下调用,由此开发人员无须每次都使用手动方式重新编译。还可以通过 CLI 进入监听模式。
执行过程
- 在
Webpack
开始读取插件配置的过程中会先执行new xxxPlugin(options)
初始化一个xxxxPlugin
插件来获得其实例。 - 在初始化
compiler
对象后调用xxxxPlugin.apply(compiler)
给插件实例传入compiler
对象。 - 插件实例在获取到
compiler
对象后,就可以通过compiler.plugin(事件名称, 回调函数)
监听到Webpack
广播出来的事件。然后根据不同的事件,进行不同的操作。并且可以通过compiler
对象去操作Webpack
。