说明
玩转 webpack 学习笔记
Tapable 是如何和 webpack 联系起来的?
可以看下面这段代码
if (Array.isArray(options)) { compiler = new MultiCompiler(options.map(options => webpack(options))); } else if (typeof options === "object") { options = new WebpackOptionsDefaulter().process(options); compiler = new Compiler(options.context); compiler.options = options; new NodeEnvironmentPlugin().apply(compiler); if (options.plugins && Array.isArray(options.plugins)) { for (const plugin of options.plugins) { if (typeof plugin === "function") { plugin.call(compiler, compiler); } else { plugin.apply(compiler); } } } compiler.hooks.environment.call(); compiler.hooks.afterEnvironment.call(); compiler.options = new WebpackOptionsApply().process(options, compiler); }
- 插件需要一个 apply 方法,接收一个 compiler 参数
- 插件上做一些 hooks 的监听,触发了插件做一些操作
模拟 Compiler.js
const { SyncHook, AsyncSeriesHook } = require('tapable'); module.exports = class Compiler { constructor() { this.hooks = { accelerate: new SyncHook(["newspeed"]), brake: new SyncHook(), calculateRoutes: new AsyncSeriesHook(["source", "target", "routesList"]), }; } run() { this.accelerate(10); this.break(); this.calculateRoutes("Async", "hook", "kaimo demo"); } accelerate(speed) { this.hooks.accelerate.call(speed); } break() { this.hooks.brake.call(); } calculateRoutes() { this.hooks.calculateRoutes.promise(...arguments).then( () => { }, (err) => { console.error(err); } ); } };
插件 my-plugin.js
const Compiler = require('./Compiler') class MyPlugin { constructor() { } apply(compiler) { compiler.hooks.brake.tap("WarningLampPlugin", () => console.log('WarningLampPlugin')); compiler.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`)); compiler.hooks.calculateRoutes.tapPromise("calculateRoutes tapAsync", (source, target, routesList) => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(`tapPromise to ${source} ${target} ${routesList}`) resolve(); }, 1000) }); }); } }
模拟插件执行
const myPlugin = new MyPlugin(); const options = { plugins: [myPlugin] } const compiler = new Compiler(); for (const plugin of options.plugins) { if (typeof plugin === "function") { plugin.call(compiler, compiler); } else { plugin.apply(compiler); } } compiler.run();
实战运行测试
我们根据上面的代码新建两个文件,添加上面代码
执行 node my-plugin.js
,结果如下