introduce

In Webapck, different plug-ins can be called for processing at different compilation stages.

So how do plug-ins get called at different stages? When we write the plugin, we must add an apply method to the plugin function. The apply method will have a parameter compiler, and we will register the hook function with the compiler, like this:

class MyPlugin {
    apply(compiler) {
        compiler.hooks.done.tapAsync('myPlugin'.() = > {
            // ...}); }}Copy the code

The Compiler object extends from Tapable. The hook function in Tapable can be understood as a component lifecycle in React or Vue.

In general, Tapable’s main purpose is to provide hook functions for plug-ins at various compile stages.

Method of use

There are 9 kinds of hooks commonly used in Tapable, which are divided into synchronous and asynchronous hooks.

Synchronous hook:

  1. SyncHook
  2. SyncBailHook
  3. SyncWaterfallHook
  4. SyncLoopHook

Asynchronous hook:

  1. AsyncParallelHook
  2. AsyncParallelBailHook
  3. AsyncSeriesHook
  4. AsyncSeriesBailHook
  5. AsyncSeriesWaterfallHook

In terms of using Tapable, it’s used the same way we used subscriber mode, you need to do a listener, and then you need to manually trigger, call back the listener event. The difference is that Tapable has multiple listening modes, and different listening modes correspond to different triggering modes.

Sync Async
Bind event: tap TapAsync, tapPromise
Execute the event: call CallAsync, promise

SyncHook

Hook functions are executed in sequence:

const syncHook = new SyncHook(['arg']);

syncHook.tap('listen1'.(arg) = > console.log('listen1:', arg));
syncHook.tap('listen2'.(arg) = > console.log('listen2:', arg));

syncHook.call('hello');

/** 
 输出:
 listen1: hello
 listen2: hello
*/
Copy the code

SyncBailHook

Hook functions are executed in sequence, but if one of them returns a non-undefined value, the rest of the hook functions are not executed.

const syncBailHook = SyncBailHook(['arg']);

syncBailHook.tap('listen1'.(arg) = > {
  console.log('listen1:', arg);
  return null;
});
syncBailHook.tap('listen2'.(arg) = > console.log('listen2:', arg));

syncBailHook.call('hello');

/**
 输出:
 listen1: hello 
 */
Copy the code

SyncWaterfallHook

Hook functions are executed in sequence, with the value returned by the previous hook function as an argument to the next one.

const hook = SyncWaterfallHook(['arg']);

hook.tap('listen1'.(arg) = > {
  console.log('listen1:', arg);
  return `${arg} listen1`;
});
hook.tap('listen2'.(arg) = > console.log('listen2:', arg));

hook.call('hello');

/**
 输出:
 listen1: hello
 listen2: hello listen1
 */
Copy the code

SyncLoopHook

Hooks are executed sequentially. If a hook returns a value that is not undefined, it is executed from the beginning. The rest of the hook functions are executed only when all of them return undefined.

const hook = SyncLoopHook(['arg']);
let num = 1;

hook.tap('listen1'.(arg) = > console.log('listen1'));
hook.tap('listen2'.(arg) = > {
  console.log(`listen2 === num: ${num}`);
  if(num === 2) {
    return undefined;
  }
  num += 1;
  return num;
});
hook.tap('listen3'.(arg) = > console.log('listen3'));

hook.call('hello');

/** Output: listen1 listen2 === num: 1 listen1 listen2 === num: 2 listen3 */
Copy the code

AsyncParallelHook

Hook functions are executed asynchronously and in parallel, and only when all the callback functions of the hook function are executed will the callback registered with the event be triggered.

const hook = AsyncParallelHook(['arg']);
const start = Date.now();

hook.tapAsync('listen1'.(arg, callback) = > {
  console.log('listen1', arg)
  setTimeout(() = > {
    callback();
  }, 1000);
});
hook.tapAsync('listen2'.(arg, callback) = > {
  console.log('listen2', arg);
  setTimeout(() = > {
    callback();
  }, 2000);
});

hook.callAsync('hello'.() = > {
  console.log('callback function execution, time:The ${Date.now() - start}`);
});

/** Output: listen1 hello listen2 The hello callback function is executed, which takes 2013 */
Copy the code

AsyncParallelBailHook

Hook functions are executed asynchronously and in parallel. When a hook function is called with a non-undefined value, the registered callback is executed immediately.

Note: All hook functions in AsyncParallelBailHook are executed.

const hook = AsyncParallelBailHook(['arg']);
const start = Date.now();

hook.tapAsync('listen1'.(arg, callback) = > {
  console.log('listen1', arg)
  setTimeout(() = > {
    callback(true);
  }, 1000);
});
hook.tapAsync('listen2'.(arg, callback) = > {
  console.log('listen2', arg);
  setTimeout(() = > {
    callback();
  }, 2000);
});

hook.callAsync('hello'.() = > {
  console.log('callback function execution, time:The ${Date.now() - start}`);
});

/** Output: listen1 hello listen2 The hello callback function is executed, which takes 1015 */
Copy the code

AsyncSeriesHook

Hook functions are executed sequentially, in sequence, after the previous hook is finished, the next hook is started, and the callback function that performs the event registration is executed last.

const hook = AsyncSeriesHook(['arg']);
const start = Date.now();

hook.tapAsync('listen1'.(arg, callback) = > {
  console.log(` listen1 = = time:The ${Date.now() - start}`)
  setTimeout(() = > {
    callback();
  }, 1000);
});
hook.tapAsync('listen2'.(arg, callback) = > {
  console.log(` listen2 = = time:The ${Date.now() - start}`)
  setTimeout(() = > {
    callback();
  }, 2000);
});

hook.callAsync('hello'.() = > {
  console.log('callback function execution, time:The ${Date.now() - start}`);
});

/** Output: listen1== Time: 1 Listen2 == Time: 1013 The callback function is executed, time: 3018 */
Copy the code

AsyncSeriesBailHook

The hook functions are executed asynchronously and serially, but as long as one of the hook functions calls callback with a non-undefined value, the registered callback functions are executed and the rest of the hook functions are not.

const hook = AsyncSeriesBailHook(['arg']);
const start = Date.now();

hook.tapAsync('listen1'.(arg, callback) = > {
  console.log('listen1')
  setTimeout(() = > {
    callback(true);
  }, 1000);
});
hook.tapAsync('listen2'.(arg, callback) = > {
  console.log('listen2')
  setTimeout(() = > {
    callback();
  }, 2000);
});

hook.callAsync('hello'.() = > {
  console.log('callback function execution, time:The ${Date.now() - start}`);
});

/** Output: listen1 Callback function execution, time: 1014 */
Copy the code

AsyncSeriesWaterfallHook

Hook functions are executed asynchronously. The arguments passed by the previous hook function through the callback function are used as arguments by the next hook function. When all hook functions are completed, the registered callback function is triggered, which receives the arguments returned by the last hook function.

const hook = AsyncSeriesWaterfallHook(['arg']);
const start = Date.now();

hook.tapAsync('listen1'.(arg, callback) = > {
  console.log('listen1', arg)
  setTimeout(() = > {
    callback(null.`${arg} listen1`);
  }, 1000);
});
hook.tapAsync('listen2'.(arg, callback) = > {
  console.log('listen2', arg)
  setTimeout(() = > {
    callback(null.`${arg} listen2`);
  }, 2000);
});

hook.callAsync('hello'.(_, arg) = > {
  console.log('callback function execution, time:The ${Date.now() - start}, arg:`, arg);
});

/** Output: listen1 hello listen2 Hello listen1 Callback function execution, time: 3016, arg: hello listen1 listen2 */
Copy the code

conclusion

  1. In the webpackcompilerObjects are extended fromTapable.
  2. TapableThe main function of webPack is to provide plugin hook functions at various stages of the WebPack compilation process.
  3. TapableprovidesasynchronousandsynchronousTo register hook functions and execute hook functions:
Sync Async
Bind event: tap TapAsync, tapPromise
Execute the event: call CallAsync, promise
  1. This article summarizes nine commonly used hook functions:
  • SyncHookThe hook functions are executed in turn.
  • SyncBailHookHook functions are executed in sequence, but if a hook function returns oneThe undefinedThen the rest of the hook functions will not execute.
  • SyncWaterfallHookHook functions are executed in sequence, and the value returned by the previous hook function is used as an argument to the next hook function.
  • SyncLoopHookHooks are executed in sequence, if one of them is returnedThe undefinedIs executed until all the hook functions executed returnundefinedThe rest of the hook functions continue to execute.
  • AsyncParallelHookHook functions are executed asynchronously and in parallel. Only after all the callback functions of the hook function are executed will the registered callback function be triggered.
  • AsyncParallelBailHookHook functions are executed asynchronously in parallel when called from a hook functioncallbackIs passed in aThe undefinedValue, then the callback function registered when the event is executed is executed immediately. Note:AsyncParallelBailHookAll hook functions in the.
  • AsyncSeriesHook: Hook functions are executed sequentially, in order of execution, after the previous hook is finished, the next hook is started, and the callback function that performs the event registration is executed last.
  • AsyncSeriesBailHookHook functions are executed asynchronously and serially, but as long as there is one hook function callcallbackWhen passed in aThe undefinedValue, the callback functions registered when the event is executed will be executed, and the remaining hook functions will not be executed.
  • AsyncSeriesWaterfallHookHook functions are executed asynchronously in serial, with the previous hook function calledcallbackThe arguments passed in are used as arguments to the next hook function, and the callback registered at the time of execution is triggered when all hook functions have finished executing. This callback receives the arguments returned by the last hook function.

The synchronous hook function selects how to execute the next hook function based on the results of the previous hook function.

An asynchronous hook function selects how to execute the next hook function and the callback registered when the event is executed based on the results of the previous hook function.