Webpack is repleted with tapable Hooks, which are used to create, mount, and call hook callbacks.
Just now I opened webPack’s official website and found that webpack has a lot of hot hooks under the API. You can see that each hook has its own hook type under it. These hook types are provided by Tapable. Webpack also relies on these hooks to achieve complex functions, let’s take a look at these hooks how to use, and then go to see the source of WebPack (🤦♀️)
Sync hook
- SyncHook
This is the simplest hook for tapable, and its usage is very simple:
import { SyncHook } from 'tapable';
const hook = new SyncHook(); // Create the hook object
hook.tap('test'.() = > console.log('Hook callback')); // The tap method registers the hook callback
hook.call(); // The call method calls the hook and prints' hook callback '
Copy the code
Generally speaking, hook creation and hook invocation are in the main process code, and hook callback registration is in the plug-in code. This decouples the functionality of the plug-in from the main function, and actually enriches the functionality of the main process.
Passing parameters to the plug-in Requirement: We need to pass parameters to the plug-in that binds the hook when we call the hook. Take a hook in Webpack as an example:
/ / main process
compilation: new SyncHook(["compilation"."params"]),...this.hooks.compilation.call(compilation, params);
/ / the plugin
compiler.hooks.compilation.tap(
"SingleEntryPlugin".(compilation, { normalModuleFactory }) = > {
...
);
Copy the code
First, the hook needs to be declared with two parameters, passed in when the hook is called, and received in the plug-in function that binds the hook. This allows the plug-in to manipulate the parameters of the main process.
- SyncBailHook
The bail is one of the bail’s.
const this.hooks.test = new SyncBailHook()
this.hooks.test.tap('one'.() = > console.log(`one`));
this.hooks.test.tap('two'.() = > {console.log(`two`)); return 'success'}
this.hooks.test.tap('three'.() = > console.log(`three`));
this.hooks.test.call(); // Can print 'one' 'two'
Copy the code
A hook of the SyncBailHook type decides whether or not to proceed based on the value returned by the previous hook. If a non-undefined value is returned, all subsequent hook callbacks will be stopped. SyncBailHook is used when A, B, or C are executed in A certain order. If true is returned in A, then B and C need not be checked.
- SyncWaterfallHook
Waterfall means “Waterfall” in English. The next step depends on the execution result of the previous step.
const this.hooks.test = new SyncWaterfallHook(['num'])
this.hooks.test.tap('one'.(num) = > return num + 100);
this.hooks.test.tap('two'.(num) = > return num + 50);
this.hooks.test.tap('three'.(num) = > console.log(num));
this.hooks.test.call(100); // Print 250
Copy the code
Usage: When A data needs to go through three parts A, B and C in sequence, then the final data can be obtained
- SyncLoopHook
This hook should be easy to understand, as it means that the callback will always be executed unless a non-undefined value is returned.
Asynchronous hooks
Asynchronous hooks are used when the callback function in a plug-in is asynchronous.
- AsyncParallelHook
This is the type of hook used to handle asynchronous parallelism.
const {AsyncParallelHook} = require('tapable');
const FrontEnd = new AsyncParallelHook(['name']);
FrontEnd.tapAsync('webpack'.(name,cb) = >{
setTimeout(() = > {
console.log(name+" get webpack ")
cb();
}, 1000);
});
FrontEnd.tapAsync('react'.(name,cb) = >{
setTimeout(() = > {
console.log(name+" get react")
cb();
}, 1000);
});
FrontEnd.callAsync('wang'.() = >{
console.log("end");
})
Copy the code
// Output the resultGet webpack Get react endCopy the code
This is an example from the web where callbacks mounted on hooks are executed in parallel, without any sequential order, and are executed in the main flow after all asynchronous operations of the plug-in have been completed. You can ensure that all plug-in code is executed before executing some logic.
- AsyncParallelBailHook
This hook function is similar to AsyncParallelHook, except that the hook registered by the first plug-in is bailed and the final callback is called, regardless of whether the other plug-ins have finished executing.
- AsyncSeriesHook
This is the type of hook used to handle asynchronous serial. The registered asynchronous callback functions are executed in sequence, and when they are finished, the callback function of the main process is executed.
- AsyncSeriesBailHook
Execute serially, and as soon as one plug-in returns a value, the final callback is called immediately, and execution of subsequent plug-ins is not continued.
- AsyncSeriesWaterfallHook
Execute sequentially, and the return value of the first plug-in is taken as an argument of the second plug-in.
The types of hooks fall into the following categories:
- Synchronous hooks. Sync hook
- Asynchronous serial hooks. The hook at the beginning of AsyncSeries.
- Asynchronous parallel hooks. AsyncParallel begins with a hook.
Conclusion: In the whole compilation and packaging process of Webpack, a large number of hooks are exposed for internal and external plug-ins to use, and the whole main process of Webpack also depends on these hooks, these functions are realized by Tapable, from one event hook to the next event hook, Drive the entire webpack compilation process. Tapable is a typical subscribe publish model, but far more powerful than EventEmit, providing multiple hook types to meet the needs of different plug-ins. And the plug-in execution logic is decoupled from the main process, but the huge Webpack has a very clear code execution logic, and Tapable has an inseparable relationship.
Well, let’s go to webpack source ~