From 5ecc7f0ddb1685b89e18703cb0c83a8693924033 Mon Sep 17 00:00:00 2001 From: tedjmzhang Date: Thu, 13 Jun 2024 19:47:59 +0800 Subject: [PATCH] =?UTF-8?q?tapable=E8=AF=A6=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 5 + package.json | 3 +- src/frontend/library/tapable/index.js | 214 ++++++++++++++++++++++++++ src/frontend/library/tapable/index.md | 148 ++++++++++++++++-- 4 files changed, 353 insertions(+), 17 deletions(-) create mode 100644 src/frontend/library/tapable/index.js diff --git a/package-lock.json b/package-lock.json index 1bd980a..fbec5dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2641,6 +2641,11 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "dev": true }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/package.json b/package.json index c38fc51..3b49b30 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "metalsmith": "^2.6.3", "metalsmith-layouts": "^2.3.1", "ora": "^8.0.1", - "shelljs": "^0.8.5" + "shelljs": "^0.8.5", + "tapable": "^2.2.1" } } diff --git a/src/frontend/library/tapable/index.js b/src/frontend/library/tapable/index.js new file mode 100644 index 0000000..8746750 --- /dev/null +++ b/src/frontend/library/tapable/index.js @@ -0,0 +1,214 @@ +let { SyncHook, AsyncSeriesHook } = require('tapable'); + +let syncHook = new SyncHook(['param1', 'param2']); +let asyncSeriesHook = new AsyncSeriesHook(['param1', 'param2']); + +syncHook.tap({ + name: '1 third hook', + stage: 1 +}, function (param, other) { + console.log('first param2', param, other) +}) +syncHook.tap({ + name: 'first hook', + stage: 11 +}, function (param, other) { + console.log('first param', param, other) +}) +syncHook.tap({ + name: 'second hook', + before: 'first hook', + stage: 12 +}, function (param, other) { + console.log('first param2', param, other) +}) +syncHook.tap({ + name: 'third hook', + stage: 3 +}, function (param, other) { + console.log('first param2', param, other) +}) +// console.log(syncHook.call.toString()); +// syncHook.call(1111, 2222); +// console.log(12, syncHook.call.toString()) + +asyncSeriesHook.tapAsync({ + name: '1 hook', + stage: 1 +}, function (param, other, callback) { + console.log('1 hook', param, other); + callback(); +}) +asyncSeriesHook.tapAsync({ + name: '3 hook', + stage: 3 +}, function (param, other, callback) { + console.log('3 hook', param, other); + callback(); +}) +asyncSeriesHook.tapAsync({ + name: '2 hook', + stage: 2 +}, function (param, other, callback) { + console.log('2 hook', param, other); + callback(); +}) +// console.log(asyncSeriesHook.callAsync.toString()); +// asyncSeriesHook.callAsync(1111, 2222, function(value) { +// console.log('last') +// }); +// console.log(12, asyncSeriesHook.callAsync.toString()) + +asyncSeriesHook.tapPromise({ + name: '3 hook', + stage: 3 +}, async function (param, other, callback) { + fetch() // 异步获取些东西 + console.log('3 hook', param, other); + callback(); +}) + +asyncSeriesHook.tapPromise({ + name: '2 hook', + stage: 2 +}, function (param, other, callback) { + console.log('2 hook', param, other); + callback(); +}) + +// console.log(asyncSeriesHook.callAsync.toString()); +asyncSeriesHook.promise(1111, 2222).then((res) => { + console.log('ok', res); +}).catch(err => console.log('something wrong', err)) + + + + + + +console.log('111') + +function anonymous1(param1, param2 +) { + "use strict"; + var _context; + var _x = this._x; + var _fn0 = _x[0]; + _fn0(param1, param2); + var _fn1 = _x[1]; + _fn1(param1, param2); + var _fn2 = _x[2]; + _fn2(param1, param2); + var _fn3 = _x[3]; + _fn3(param1, param2); + +} + +function anonymous2(param1, param2, _callback +) { + "use strict"; + var _context; + var _x = this._x; + function _next1() { + var _fn2 = _x[2]; + _fn2(param1, param2, (function (_err2) { + if (_err2) { + _callback(_err2); + } else { + _callback(); + } + })); + } + function _next0() { + var _fn1 = _x[1]; + _fn1(param1, param2, (function (_err1) { + if (_err1) { + _callback(_err1); + } else { + _next1(); + } + })); + } + var _fn0 = _x[0]; + _fn0(param1, param2, (function (_err0) { + if (_err0) { + _callback(_err0); + } else { + _next0(); + } + })); + +} +function anonymous3(param1, param2 +) { + "use strict"; + var _context; + var _x = this._x; + return new Promise((function (_resolve, _reject) { + var _sync = true; + function _error(_err) { + if (_sync) + _resolve(Promise.resolve().then((function () { throw _err; }))); + else + _reject(_err); + }; + function _next3() { + var _fn4 = _x[4]; + var _hasResult4 = false; + var _promise4 = _fn4(param1, param2); + if (!_promise4 || !_promise4.then) + throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise4 + ')'); + _promise4.then((function (_result4) { + _hasResult4 = true; + _resolve(); + }), function (_err4) { + if (_hasResult4) throw _err4; + _error(_err4); + }); + } + function _next2() { + var _fn3 = _x[3]; + _fn3(param1, param2, (function (_err3) { + if (_err3) { + _error(_err3); + } else { + _next3(); + } + })); + } + function _next1() { + var _fn2 = _x[2]; + var _hasResult2 = false; + var _promise2 = _fn2(param1, param2); + if (!_promise2 || !_promise2.then) + throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise2 + ')'); + _promise2.then((function (_result2) { + _hasResult2 = true; + _next2(); + }), function (_err2) { + if (_hasResult2) throw _err2; + _error(_err2); + }); + } + function _next0() { + var _fn1 = _x[1]; + _fn1(param1, param2, (function (_err1) { + if (_err1) { + _error(_err1); + } else { + _next1(); + } + })); + } + var _fn0 = _x[0]; + _fn0(param1, param2, (function (_err0) { + if (_err0) { + _error(_err0); + } else { + _next0(); + } + })); + _sync = false; + })); + +} \ No newline at end of file diff --git a/src/frontend/library/tapable/index.md b/src/frontend/library/tapable/index.md index d5a2189..fcf45e0 100644 --- a/src/frontend/library/tapable/index.md +++ b/src/frontend/library/tapable/index.md @@ -2,29 +2,145 @@ 统一管理不同类型的hooks 最基本的一个Hook类,该类型定义了一系列方法和属性,例如 -方法:tap, tapAsync, call, callAsync -属性:taps存放所有钩子 +方法:tap, tapAsync, call, callAsync, intercept +属性:taps存放所有钩子, interceptors存放所有的拦截器 Hook也分类型,例如 SyncHook:同步钩子,需要重写Hook类默认的tapAsync,tapPromise,compile方法。 AsyncSeriesHook:异步钩子,需要重写Hook类默认的compile,_call, call方法。 -最终导出的一般是某特定类型的Hook,例如SyncHook, AsyncSeriesHook。 +最终导出的一般是某特定类型的Hook,例如SyncHook, AsyncSeriesHook。 + +外部使用方式为Hook.(call|callAsync)(params) + +调用hook.tap方法会将参数和回调组合成{...options, fn: callback}放入hook.taps数组里面。 +按照options.before以及options.stage的大小,从小到大插入数组,具体是先before(表示在哪些options.name之前): string | string[], +等到before完全满足之后,再根据stage从小到大排列。 +**before优先级高于stage** + +hook.intercept({register: (tap) => {}})会将所有hook.taps遍历一遍当做参数传递给register函数,然后返回值覆盖hook.taps。 +每次新增hook.tap的时候都会对tap时候传递的参数执行所有的interceptors,返回处理过的值 + -外部使用方式为Hook.(call|callAsync)(params): ``` javascript +// 定义hook,第一个参数数组表示后续调用方法有几个参数,名字随便取,只是一个变量 +let syncHook = new SyncHook(['param1', 'param2']); + // 注册事件: -AsyncSeriesHook.tapAsync( - { - name: "CleanPlugin", - stage: 100 - }, - (compilation, callback) => { - doSomeThing(); - } -) +syncHook.tap({ + name: '1 third hook', + stage: 1 +}, function (param, other) { + console.log('first param2', param, other) +}) +syncHook.tap({ + name: 'first hook', + stage: 11 +}, function (param, other) { + console.log('first param', param, other) +}) +syncHook.tap({ + name: 'second hook', + before: 'first hook', + stage: 12 +}, function (param, other) { + console.log('first param2', param, other) +}) +syncHook.tap({ + name: 'third hook', + stage: 3 +}, function (param, other) { + console.log('first param2', param, other) +}) + +// syncHook.call会被改写成,_x存的所有的tap.fn +function anonymous(param1, param2 + ) { + "use strict"; + var _context; + var _x = this._x; + var _fn0 = _x[0]; + _fn0(param1, param2); + var _fn1 = _x[1]; + _fn1(param1, param2); + var _fn2 = _x[2]; + _fn2(param1, param2); + var _fn3 = _x[3]; + _fn3(param1, param2); + +} + // 调用事件: -AsyncSeriesHook.callAsync(compilation, err => { - doSomeThing(); +syncHook.call(compilation, 'dfasdf') +``` + + + +``` javascript +// 定义hook,第一个参数数组表示后续调用方法有几个参数,名字随便取,只是一个变量 +let asyncSeriesHook = new AsyncSeriesHook(['param1', 'param2']) + +// asyncSeriesHook.callAsync经过重写之后,会变成,_x存的所有的tap.fn +asyncSeriesHook.callAsync = function anonymous(param1, param2, _callback +) { + "use strict"; + var _context; + var _x = this._x; + function _next1() { + var _fn2 = _x[2]; + _fn2(param1, param2, (function (_err2) { + if (_err2) { + _callback(_err2); + } else { + _callback(); + } + })); + } + function _next0() { + var _fn1 = _x[1]; + _fn1(param1, param2, (function (_err1) { + if (_err1) { + _callback(_err1); + } else { + _next1(); + } + })); + } + var _fn0 = _x[0]; + _fn0(param1, param2, (function (_err0) { + if (_err0) { + _callback(_err0); + } else { + _next0(); + } + })); +} + +// 注册事件,异步函数需要手动调用callback才会执行下一个事件 +asyncSeriesHook.tapAsync({ + name: '1 hook', + stage: 1 +}, function (param, other, callback) { + console.log('1 hook', param, other); + callback(); +}) +asyncSeriesHook.tapAsync({ + name: '3 hook', + stage: 3 +}, function (param, other, callback) { + console.log('3 hook', param, other); + callback(); }) -``` \ No newline at end of file +asyncSeriesHook.tapAsync({ + name: '2 hook', + stage: 2 +}, function (param, other, callback) { + console.log('2 hook', param, other); + callback(); +}) + +// 异步函数的最后一个参数是一个回调函数,当tap的所有fn执行callback(param)中的param不为空的时候(或者执行完毕),会执行callAsync的回调 +asyncSeriesHook.callAsync(1111, 2222, function(value) { + console.log('last') +}); +```