webpack king(二)
关于Tapable
Webpack的插件系统是基于事件的,通过发布订阅模式构建webpack的事件系统。
tapable是什么以及简单的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| let { SyncHook, AsyncParallelHook } = require("tapable"); class Test { constructor() { this.hooks= { arch: new SyncHook(['name']) } } tap() { this.hooks.arch.tap("test1", (...args) => { console.log(args) }); this.hooks.arch.tap("test2", (...args) => { console.log(args) }); } start() { console.log(111) this.hooks.arch.call('111'); } }
class Test1 { constructor() { this.hooks= { arch: new AsyncParallelHook(['name']) } } tap() { this.hooks.arch.tapAsync("test1", (...args, cb) => { setTimeout(() => { console.log(123) }, 1000) }); this.hooks.arch.tapAsync("test2", (...args, cb) => { setTimeout(() => { console.log(123) }, 1000) }); } start() { console.log(111) this.hooks.arch.callAsync('111'); } }
|
AsyncParallelHook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class AsyncParallelHook { constructor(){ this.tasks = []; } callAsync(...args) { let fn = args.pop(); let idx = 0 function done(name, cb) { idx++; if (idx === this,tasks.length) { fn(); } } this.tasks.forEach(t => { task(...args, done) }) } tapPromise(name, cb) { this.tasks.push(cb) } promise(...arg) { return Promise.all(this.tasks.map(t => t(arg))) } tapAsync(name, cb) { this.tasks.push(cb) } }
|
AsyncSeries
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class AsyncSeries { constructor(){ this.tasks = []; } callAsync(...args) { let fn = args.pop(); let idx = 0; const next = () => { if (this.tasks.length === idx) return fn() let tsk = this.tasks[index++]; tsk(...arg, next); } next() }
tapAsync(name, cb) { this.tasks.push(cb) } }
|
AsyncSeriesWaterfallHook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class AsyncSeriesWaterfallHook { constructor(){ this.tasks = []; } callAsync(...args) { let fn = args.pop(); let idx = 0; const next = (error, data) => { let tsk = this.tasks[index]; if (!tsk) return fn() tsk(...arg, next); } index === 0 && task(...args, next) index !== 0 && task(data, next) }
tapAsync(name, cb) { this.tasks.push(cb) } }
|