webpack插件运行原理及编写

webpack是一个很好用的打包工具,怎么配置和使用大家都比较熟悉了,其中在配置的过程中会用到很多plugin,如果想进一步了解webpack,就要了解plugin的工作机制,再进一步,就是自己动手封装一个plugin.

插件存在的环节:

Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。
这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。
插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。

首先看下webpack打包后输出文件的格式:

webpack打包过后是将一个一个的模块变成了一个对象,key是模块路径,值是模块里面的代码,只是代码被转化成了字符串,被放在eval环境里面,这样实现的基础是,webpack实现了一个函数_webpack_require()函数,用来引入不同的模块,进而处理模块之间的关系。_webpack_require可以有commonjs规范,cmd规范,具体实现方式可以参见我的另外两篇文章:

手动实现commonJs规范

实现AMD规范

webpack plugin的工作机制

在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果

说明:可以安装lifecycle-webpack-plugin 插件来查看生命周期信息。

主要靠两个对象:

compiler对象和compilation对象
 

compiler对象:

  • Compiler 对象包含了 Webpack 环境所有的的配置信息,包含 options,loaders,plugins 这些信息,这个对象在 Webpack 启动时候被实例化,它是全局唯一的,可以简单地把它理解为 Webpack 实例;

compilation对象

  • Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当 Webpack 以开发模式运行时,每当检测到一个文件变化,一次新的 Compilation 将被创建。Compilation 对象也提供了很多事件回调供插件做扩展。通过 Compilation 也能读取到 Compiler 对象。

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

webpack事件流(这里是老版本实现,新版本使用钩子函数

核心模块:tabable

实现机制:Webpack 的事件流机制应用了观察者模式,和 Node.js 中的 EventEmitter 非常相似。

插件作用:监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作

事件流机制的作用: 保证了插件的有序性,使得整个系统扩展性很好。

Compiler 和 Compilation 都继承自 Tapable,可以直接在 Compiler 和 Compilation 对象上广播和监听事件

/**
* 广播出事件
* event-name 为事件名称,注意不要和现有的事件重名
* params 为附带的参数
*/
compiler.apply('event-name',params);

/**
* 监听名称为 event-name 的事件,当 event-name 事件发生时,函数就会被执行。
* 同时函数中的 params 参数为广播事件时附带的参数。
*/
compiler.plugin('event-name',function(params) {
  
});

注意:

有些事件是异步的,这些异步的事件会附带两个参数,第二个参数为回调函数,在插件处理完任务时需要调用回调函数通知 Webpack,才会进入下一处理流程。例如:

compiler.plugin('emit',function(compilation, callback) {
  // 支持处理逻辑

  // 处理完毕后执行 callback 以通知 Webpack 
  // 如果不执行 callback,运行流程将会一直卡在这不往下执行 
  callback();
});

关于常用api,这里仅列出,不做详细介绍:

插件可以用来修改输出文件、增加输出文件、甚至可以提升 Webpack 性能、等等,总之插件通过调用 Webpack 提供的 API 能完成很多事情。

常用:

1,读取输出资源、代码块、模块及其依赖

2,监听文件变化

3,修改输出资源

4,判断 Webpack 使用了哪些插件

手动编写一个插件

1,搭建一个基本架子:

2,添加两个事件

  • done:在成功构建并且输出了文件后,Webpack 即将退出时发生;
  • failed:在构建出现异常导致构建失败,Webpack 即将退出时发生;
class EndWebpackPlugin {

  constructor(doneCallback, failCallback) {
    // 存下在构造函数中传入的回调函数
    this.doneCallback = doneCallback;
    this.failCallback = failCallback;
  }

  apply(compiler) {
    compiler.plugin('done', (stats) => {
        // 在 done 事件中回调 doneCallback
        this.doneCallback(stats);
    });
    compiler.plugin('failed', (err) => {
        // 在 failed 事件中回调 failCallback
        this.failCallback(err);
    });
  }
}
// 导出插件 
module.exports = EndWebpackPlugin;

html-webpack-plugin实例:

参考:https://segmentfault.com/a/1190000012840742?utm_source=tuicool&utm_medium=referral

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值