webpack源码之tapable

引言

去年3月的时候当时写了一篇 webpack2-update之路,到今天webpack已经到了4.2,更新挺快的,功能也在不断的完善,webpack4特性之一就是零配置, webpack生命力真的很顽强,积极跟上环境的变化,响应社区的需求,不断的迭代,由于parcel在其以前就有这个特性了。直接运行webpack命令,默认production模式,可是会有WARNING。

以下所示在package.json中启动脚本配置node

"scripts": {
    "build": "webpack --mode production",  //代码作了压缩/做用域提高(就是将依赖模块内容直接放到当前模块内)/去掉了开发模式下存在的代码/更容易使用输出的资源文件(assets作了优化处理)
    "dev": "webpack-dev-server --open --mode development", //支持注释/提示/source maps
  },

这种约定大于配置的开发方式,在不少框架中都存在, 默认的配置覆盖了大部分用户使用的场景,提升了大部分人的生产力。固然除了默认配置外还有其它一些特性,例如支持导入更多的模块类型,能够解析.json.wasm类型的文件等等。webpack

虽然使用形式上变化的这么快, 可是其核心思想没多大变化。 其中webpack内部有一个事件流机制,基于tapable,也是本文研究的对象,它的做用是将各个插件串联起来,还有webpack中负责编译的Compile也是tapable的实例,因此这个蛮重要的,下面详细说一下。git

tapable概念

tapable相似于node中的EventEmitter,专一于自定义事件的触发和处理,自身能够被继承或混入到其它模块中。例如compile的实现就用到了tapable,以下所示。github

var Tapable = require("tapable");

function Compiler() {
    Tapable.call(this);
}

Compiler.prototype = Object.create(Tapable.prototype);

Hook分析

class Car {
    constructor() {
        this.hooks = {
            accelerate: new SyncHook(["newSpeed"]),
            break: new SyncHook(),
            calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])
        };
    }

}
const myCar = new Car();
//使用tap方法添加了一个消费者,其中tap的第一个参数,通常是用来确认插件的名称
myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`));
myCar.hooks.accelerate.call('100')
//输出   Accelerating to 100

说明 其中SyncHook继承了Hook方法,主要做用是重写了compile方法。而Hook内部维护了 this.taps = [],每次执行tap时,都会进行insert,call的时候经过web

this[name](...args)

进行执行,在call执行的时候其内部涉及到工厂模式,由于call的调用,须要先执行当前SyncHook的compile方法,用工厂模式的目的就是根据传入的不一样option返回不一样的经过new Function拼接出的
处理逻辑函数,由于Hook有好几种实现,在实现类的实例中添加的消费者能够是sync,promise,async等等,都须要对应不一样compile来进行处理。json

tapable使用分析

const {Tapable,SyncHook} = require("tapable");
const myCar = new Tapable();
myCar.hooks = {
    myHook: new SyncHook()
};
let speed = 0;
myCar.plugin("my-hook", () => speed+=2);
myCar.hooks.myHook.call();
myCar.plugin("my-hook", () => speed += 10);
myCar.hooks.myHook.call();
console.log(speed);
//输出14

说明
plugin(name:string, handler:function):容许将一个自定义插件注册到 Tapable 实例 的事件中。它的行为和 EventEmitter 的 on() 方法类似,用来注册一个处理函数/监听器,来在信号/事件发生时作一些事情,他最终仍是调用hook.tap(tapOpt, options.fn)进行存储。而call就所有取出来执行。segmentfault

总结

上面这些知识是理解插件和webpack运行原理的前置条件,更多内容待下次分解api

参考源码版本说明
tapable: "1.0.0",
webpack: "^4.2.0",promise

参考连接
https://medium.com/webpack/we...
https://medium.com/webpack/we...
https://github.com/dwqs/blog/...
https://doc.webpack-china.org...
https://github.com/webpack/ta...框架

相关文章
相关标签/搜索