Plugins expose the full potential of the webpack engine to third-party developers. ———– Webpack
Plugin is more flexible than Loaders because it has access to the WebPack compiler and compilation core. This allows the Plugin to intercept webpack execution with hook functions, or even run a child compiler in tandem with the loader, as MiniCssExtractPlugin does.
Example code: Link
Basic structure of the WebPack Plugin
Taking the htML-webpack-plugin as an example, its use is as follows
plugins: [
newHtmlWebpackPlugin({ ... }),].Copy the code
It is easy to see that the basic form of the Webpack plugin is a constructor new function(), and in order to get compiler, the plugin needs to expose an interface (the apply function). So, its basic structure is as follows:
- A named JavaScript function object;
- In its
prototype
So, let’s define oneapply
Methods.
There are many ways to achieve this form of JavaScript, this article uses class to achieve, as follows
module.exports = class DemoPlugin {
apply() {
console.log('applying')}}Copy the code
Configuring the Development Environment
To be able to run the plugin, we need to create an environment
mkdir webpack-demo-plugin
cd webpack-demo-plugin
npm init
Copy the code
webpack.plugin.js
const path = require("path");
const PATHS = {
lib: path.join(__dirname, "index.js"),
build: path.join(__dirname, "build"),};module.exports = {
entry: {
lib: PATHS.lib,
},
output: {
path: PATHS.build,
filename: "[name].js",}};Copy the code
index.js
console.log("hello world")
Copy the code
Also add to package.json
"scripts": {
"build:plugin": "webpack --config webpack.plugin.js --mode production". }Copy the code
Implement webpack demo
Create a plugins/demo-plugin.js file containing the previous webpack plugin demo and import it into webpack.plugin.js.
webpack.plugin.js
const DemoPlugin = require("./plugins/demo-plugin.js");
module.exports = {
...
/ / introduction of the plugin
plugins: [new DemoPlugin()],
};
Copy the code
Try running NPM run build:plugin and print it on terminal
Applying Hash: 98C8997160AA995a58A4 Version: WebPack 4.12.0 Time: 93ms Built at: 2019-04-29 14:34:31 Asset Size Chunks Chunk Names lib.js 956 bytes 0 [emitted] lib [0] ./index.js 26 bytes {0} [built]Copy the code
It is a surprise to discover that the plug-in is running successfully.
Passing parameters
When applying a plugin, it is sometimes necessary to pass Options to tell the plugin what to do. The constructor of class DemoPlugin is triggered when new DemoPlugin()
plugins/demo-plugin.js
module.exports = class DemoPlugin {
constructor(options) {
this.options = options
}
apply() {
console.log('apply'.this.options)
}
}
Copy the code
You also need to modify webpack.plugin.js to pass the corresponding parameters
module.exports = {
...
plugins: [new DemoPlugin({ name: 'demo'}})],Copy the code
Run NPM run build:plugin to find apply {name: ‘demo’}. Schema-utils can be used to validate Options.
Understand the Compiler and compilation of Webpack
As described earlier in the basic structure of the WebPack Plugin, the Apply function can be used to access the core of webpack. Instead, the apply function takes compiler
plugins/demo-plugin.js
module.exports = class DemoPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
console.log(compiler)
}
}
Copy the code
Run the NPM Run Build: Plugin again, and you’ll find that all the compiler information is printed on the terminal, with hooks fields being the majority.
Looking at the official documentation, you will see that each hook corresponds to a specific stage. For example, the emit practice is executed before sending resources to the output directory. This allows you to control the compilation process by listening on the hooks.
plugins/demo-plugin.js
module.exports = class DemoPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.plugin('emit', (compilation, next) => {
console.log(compilation)
next()
})
}
}
Copy the code
Don’t forget to call next, or WebPack won’t continue to pack.
Running the NPM Run Build: Plugin displays more information than before, because the compiled object contains the entire dependency graph traversed by WebPack. You can access everything related to this, including entries, chunks, modules, assets, etc.
Write files through Compilation
The compilation can be used to write new files or modify files that have already been created. To better write files, we introduce an NPM package
npm install webpack-sources --save-dev
Copy the code
plugins/demo-plugin.js
const { RawSource } = require("webpack-sources");
module.exports = class DemoPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
const { name } = this.options;
compiler.plugin('emit', (compilation, next) => {
compilation.assets[name] = new RawSource("demo");
next()
})
}
}
Copy the code
Run the NPM run build:plugin on the terminal
Hash: 98C8997160AA995a58A4 Version: webpack 4.12.0 Time: 95ms Built at: 2019-04-29 16:08:52 Asset Size Chunks Chunk Names lib.js 956 bytes 0 [emitted] lib demo 4 bytes [emitted] [0] ./index.js 26 bytes {0} [built]Copy the code
In the Asset column, we have our own demo file.
For more hooks, see the Official Compilation Reference.
Manages Warnings and Errors
As an experiment, what happens if you insert throw new Error(“Message”) inside apply, the terminal prints Unhandled Rejection Error: Message. Webpack then interrupts execution.
To issue warnings or error messages to the user during compilation without affecting the execution of webpack, use compilation.warnings and compilation.errors.
compilation.warnings.push("warning");
compilation.errors.push("error");
Copy the code
conclusion
When you set out to design a plug-in, be sure to spend time researching existing plug-ins of the same type. Develop plug-ins one by one so that you only validate one at a time. If you have problems, check out the Webpack source code, which will enhance your debug intuition.
Reference:
Webpack.js.org/contribute/…
Survivejs.com/webpack/ext…
Webpack.js.org/api/plugins…