简介
插件是 webpack 的支柱功能。webpack
自身也是构建于,你在 webpack
配置中用到的相同的插件系统之上!插件目的在于解决 loader
无法实现的其他事。
要想写好插件就要知道Webpack
中的两个比较核心的概念compiler
、compilation
、tapable
。在webpack 编译流程已经都要记录。Webpack
通过 Plugin
机制让其更加灵活,以适应各种应用场景。 在 Webpack
运行的生命周期中会广播出许多事件,Plugin
可以监听这些事件,在合适的时机通过 Webpack
提供的 API
改变输出结果。
实现一个 plugin
一个 webpack plugin 基本包含以下几步:
- 一个
JavaScript 函数或者类
- 在
函数原型(prototype)
中定义一个注入compiler
对象的apply
方法。 apply
函数中通过compiler
插入指定的事件钩子,在钩子回调中拿到compilation
对象- 使用
compilation
操纵修改webapack
内部实例数据。 - 异步插件,数据处理完后使用
callback
回调
最后会实现一个简单的clean-webpack-plugin
。
一个简单的插件
1 | class WebpackCleanupPlugin { |
如何使用在 webpack.config.js 中引入并且使用如下:
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); |
自己写的插件如下执行:
webpack
启动后,在读取配置的过程中会先执行new WebpackCleanupPlugin()
初始化一个 WebpackCleanupPlugin 获得其实例。- 在初始化
compiler
对象后,再调用WebpackCleanupPlugin.apply(compiler)
给插件实例传入compiler
对象。 - 插件实例在获取到
compiler
对象后,就可以通过compiler.plugin
(事件名称, 回调函数) 监听到Webpack
广播出来的事件。 - 并且可以通过
compiler
对象去操作webpack
。
Compiler、Compilation
- Compiler 对象包含了 Webpack 环境所有的的配置信息,包含
options
,hook
,loaders
,plugins
这些信息,这个对象在Webpack
启动时候被实例化,它是全局唯一的,可以简单地把它理解为Webpack
实例;Compiler
中包含的东西如下所示:
- Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当
Webpack
以开发模式运行时,每当检测到一个文件变化,一次新的Compilation
将被创建。Compilation
对象也提供了很多事件回调供插件做扩展。通过Compilation
也能读取到Compiler
对象。
Compilation
中包含的东西如下所示:
Compiler 和 Compilation 的区别在于:
Compiler
代表了整个Webpack
从启动到关闭的生命周期,而Compilation
只是代表了一次新的编译。
一个简单的清除文件插件
每次打包如果文件有修改会生成新的文件,文件的hash也会跟着变化,那么这个改变了的文件,他以前的文件就是无效的了,要把以前的文件清除掉,我们使用比较多的就是clean-webpack-plugin
,这里自己实现一个简单的文件清除。如果不知道hash、contenthash、chunkhash的区别可以看这一片文章。
大致分为以下几步:
- 获取
output
路径,也就是出口路径一般为dist
- 绑定钩子事件
compiler.plugin('done', (stats) => {})
- 编译文件,与原来文件对比,删除未匹配文件 (同时可以 options 设置要忽略的文件)
代码实现如下
1 | const recursiveReadSync = require('recursive-readdir-sync'); |
上面的这个插件实现了一个清除编译文件的效果。在这里就不做实验了,如果有兴趣可以自己把代码 copy 到本地,运行一下看一下结果。
总结
在上面大致知道怎么写一个简单的清除文件的webpack
的插件,其实还可以做更多的事情如下:
- 读取输出资源、代码块、模块及其依赖(在
emit
事件发生) - 监听文件变化
watch-run
- 修改输出资源
compilation.assets
具体实现可以看一下一下webpack 深入浅出
参考
干货!撸一个 webpack 插件(内含 tapable 详解+webpack 流程)
看清楚真正的 Webpack 插件