Webpack flowchart
Important steps:
init => run => compile => compilation => make => afterCompile => seal => codeGen => emit => done
plugin idea
The idea of plugin plug-in is to find a place to insert between the above steps. The method inserted and called uses the event model, hooks:
// Define an event / hook this.hooks.eventName = new SyncHook(["arg1", "arg2"]); // Listen for an event / hook this.hooks.eventName.tap('Reason for monitoring', fn) // Trigger an event / hook this.hooks.eventName.call('arg1', 'arg2')
In the webpack source code, hooks are defined between each step. You just need to listen to a specific hook in the webpack life cycle to trigger the plugin, and then do what you want in the function.
Write your own webpack plugin
Let's first look at the source code of a plugin: clean-webpack-plugin
The function of this plug-in is to clear the previous dist file before the dist file is generated.
So which step of webpack is better for us to monitor and clear?
It should be that the chunk is about to be written to the hard disk. It's better when it's emit. It's not safe to empty it too early.
To confirm whether my idea is right, let's look at the key code of this plug-in:
apply(compiler: Compiler) { if (!compiler.options.output || !compiler.options.output.path) { // eslint-disable-next-line no-console console.warn( 'clean-webpack-plugin: options.output.path not defined. Plugin disabled...', ); return; } this.outputPath = compiler.options.output.path; /** * webpack 4+ comes with a new plugin system. * * Check for hooks in-order to support old plugin system * webpack 5+ removed the old system, the check now breaks */ const hooks = compiler.hooks; if (this.cleanOnceBeforeBuildPatterns.length !== 0) { hooks.emit.tap('clean-webpack-plugin', (compilation) => { this.handleInitial(compilation); }); } hooks.done.tap('clean-webpack-plugin', (stats) => { this.handleDone(stats); }); }
- hooks.emit.tap(): clear dist
- hooks.done.tap(): delete files other than assets
By looking at the source code, I confirmed my speculation.
The agreement to write plugin on the official website:
- A JavaScript named function.
- Define an apply method on the prototype of the plug-in function.
- Specify a binding to the webpack itself event hook .
- Process specific data for webpack internal instances.
- The callback provided by webpack is called after the function is completed.
// A JavaScript named function. function MyExampleWebpackPlugin() { }; // Define an 'apply' method on the prototype of the plug-in function. MyExampleWebpackPlugin.prototype.apply = function(compiler) { // Specify an event hook to mount to the webpack itself. compiler.plugin('webpacksEventHook', function(compilation /* Process specific data for webpack internal instances.*/, callback) { console.log("This is an example plugin!!!"); // The callback provided by webpack is called after the function is completed. callback(); }); };
The difference between loader and plugin
- Loader: it is A converter that compiles A file into B file, such as XX Convert MD to XX HTML, A pure file conversion process.
- Plugin: it aims at the whole packaging process of webpack, that is, the complete life cycle of webpack. It can participate in any stage. It can operate files and work based on the event mechanism. It can listen to all hooks that define hooks events in the packaging process of webpack and perform the operations you need (you can call a third-party plug-in or write it yourself).