webpack在前端工程化应用上有着很重要的地位,说到webpack,就会想到一堆插件,但是大部分开发工程师仅仅知道插件的使用啊,未曾去研究插件实现原理,这对于工程的定制化有着很重要的意义。本文主要探讨如何实现一个webapck插件,当然功能是相对简单的。有兴趣的可以去阅读一些webpack插件的源码,当然如果有大牛看到,欢迎留言指正不足。
webpack插件的作用是用来解决一些loader无法解决的问题。
从webpack的使用上可以看出webapck插件是一个构造函数,接收一个参数配置对象,所以我们可以首先定义:
function myWebpackPlugin(config){
...
}
通过打印webpack插件可以发现
以下介绍是老版本实现,新版本请使用hooks
webpack插件主要是使用到两个对象,compiler和compilation。
说明:
compiler::包含了webpack环境配置,当webpack调用插件的时候,会返回一个compiler对象,提供给插件。
- Compiler 对象包含了 Webpack 环境所有的的配置信息,包含 options,loaders,plugins 这些信息,这个对象在 Webpack 启动时候被实例化,它是全局唯一的,可以简单地把它理解为 Webpack 实例;
compilation:是编译过程的生命周期,这个对象可以访问所有的模块和它们的依赖。(compilation [.kɒmpə'leɪʃ(ə)n] n 编译;编辑;汇编)
- Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当 Webpack 以开发模式运行时,每当检测到一个文件变化,一次新的 Compilation 将被创建。Compilation 对象也提供了很多事件回调供插件做扩展。通过 Compilation 也能读取到 Compiler 对象。
webpack插件原型上有一个apply方法,接受compiler对象,用来监听webapck广播出来的事件
myWebpackPlugin.prototype.apply = function(compiler){
...
}
以上三个基本核心点,来梳理下webpack插件加载流程
在webpack启动后:
首先执行 new webpackPlugin(options),获得实例webpackPlugin;
然后调用webpackPlugin.apply(compiler)给插件实例传入compiler对象;
最后通过compiler.plugin(事件名称,回调函数)来监听到webpack广播出来的事件
webapck插件基本结构:
function compilerTest (options) {
}
compilerTest.prototype.apply = function (compiler) {
compiler.plugin('compilation', function (compilation) {
compilation.plugin("optimize", function() {
console.log("这里被触发了哦");
});
})
}
module.exports = compilerTest
接下来探讨下事件流:
流水线模型:
Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。
这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。
插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。
compiler广播和监听事件的实现
/**
* 广播出事件
* event-name 为事件名称,注意不要和现有的事件重名
* params 为附带的参数
*/
compiler.apply('event-name',params);
/**
* 监听名称为 event-name 的事件,当 event-name 事件发生时,函数就会被执行。
* 同时函数中的 params 参数为广播事件时附带的参数。
*/
compiler.plugin('event-name',function(params) {
});
Compilation的实现和compiler一样
webacpk插件实例:(持续更新)
参考:
https://www.jianshu.com/p/f96c6a69515d
https://segmentfault.com/a/1190000012840742