Have you ever encountered these problems:
- The files packaged by webpack are not compressed
- Static files should be manually copied to the output directory
- A lot of redundant code for environment judgment is written in the code
The previous article "webpack core features" loader mentioned loader
the mechanism of webpack. This article mainly talks about another core feature: plug-in ( plugin
).
The plug-in mechanism is to complete other automation tasks in the project except resource module packaging, and solve the above problems.
plugin
It is used to extend the functionality of webpack by injecting hooks into the build process, which brings great flexibility to webpack.
What is the difference between plugin and loader?
loader
It is a converter, which compiles and converts one type of file into another file, and operates the file. For example: converting .less
a file to .css
a file.
plugin
It is an expander, which is aimed at loader
the whole process of packaging after the end. It does not directly manipulate files, but works based on the event mechanism. Corresponding events will be broadcast at specific times in the webpack build process, and plug-ins can listen to the occurrence of these events and do corresponding things at specific times. Including: packaging optimization, resource management, injection of environment variables.
How should the plugin be configured?
For example HtmlWebpackPlugin
an HTML file can be generated for us that includes script
all modules in the body using tags. See how to configure:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpackConfig = {
...
plugins: [new HtmlWebpackPlugin()]
};
Reminder:
loader
Configured in module.rules, as the parsing rules of the module, the type is an array. Each item is an object, which contains attributes such as test (type file), loader, and options (parameters).plugin
It is configured separately, the type is an array, each item is anplugin
instance, and the parameters are passed in through the constructor.
What common plugins are there?
The list of plug-ins compiled below comes from the webpack Chinese official website. If you see something you are not familiar with, you plugin
can click the name to jump, take a look, and learn about the specific gameplay.
name | describe |
---|---|
AggressiveSplittingPlugin | Divide the original chunk into smaller chunks |
BabelMinifyWebpackPlugin | Minify with babel-minify |
BannerPlugin | Add a banner at the top of each generated chunk |
CommonsChunkPlugin | Extract common modules shared between chunks |
CompressionWebpackPlugin | A pre-prepared compressed version of resources, using Content-Encoding to provide access services |
ContextReplacementPlugin | Override the inference context of require expressions |
CopyWebpackPlugin | Copy individual files or entire directories to the build directory |
DefinePlugin | Global constants that allow configuration at compile time |
DllPlugin | In order to greatly reduce the build time, dll subpackage |
EnvironmentPlugin | Shorthand for the process.env key in DefinePlugin. |
ExtractTextWebpackPlugin | Extract text (CSS) from bundle to separate file |
HotModuleReplacementPlugin | Enable Hot Module Replacement (HMR) |
HtmlWebpackPlugin | Simple creation of HTML files for server access |
I18nWebpackPlugin | Add internationalization support to bundle |
IgnorePlugin | Exclude certain modules from the bundle |
LimitChunkCountPlugin | Set min/max limits for chunks to fine tune and control chunks |
LoaderOptionsPlugin | For migrating from webpack 1 to webpack 2 |
MinChunkSizePlugin | Make sure the chunk size exceeds the specified limit |
NoEmitOnErrorsPlugin | During the output stage, when a compilation error is encountered, skip |
NormalModuleReplacementPlugin | Replace resources that match a regular expression |
NpmInstallWebpackPlugin | Automatically install missing dependencies during development |
ProvidePlugin | No need to use modules via import/require |
SourceMapDevToolPlugin | Fine-grained control over source maps |
EvalSourceMapDevToolPlugin | Fine-grained control over eval source maps |
UglifyjsWebpackPlugin | Can control the version of UglifyJS in the project |
ZopfliWebpackPlugin | A pre-compressed version of resources via node-zopfli |
How to write a plugin?
Before talking about how to write plug-ins, let me briefly introduce a few fun things: tapable
, compiler
and compilation
.
tapable
tapable
It is a similar nodejs
library EventEmitter
, mainly to control the publication and subscription of hook functions. Of course, the mechanism tapable
provided is relatively comprehensive, which is divided into two categories: synchronous and asynchronous (asynchronous parallel and asynchronous serial are distinguished in asynchronous), and according to the different termination conditions of event execution, // types hook
are derived. Bail
Waterfall
Loop
Basic use:
const { SyncHook } = require('tapable');
const hook = new SyncHook(['name']);
hook.tap('hello', (name) => {
console.log(`hello ${name}`);
});
hook.tap('hi', (name) => {
console.log(`hi ${name}`);
});
hook.call('july');
// hello july
// hi july
summary:
tapable
The basic logic is to first tap
register the corresponding hook
processing function through the method of the class instance, and then call
trigger the callback function through the method.
compiler
compiler
The object contains all configuration information of the webpack environment, including options, loaders and plugins. It can be simply understood as a webpack instance. Represents the life cycle of the entire webpack from startup to shutdown .
compile
Internal implementation of:
class Compiler extends Tapable {
constructor(context) {
super();
this.hooks = {
/** @type {SyncBailHook<Compilation>} */
shouldEmit: new SyncBailHook(["compilation"]),
/** @type {AsyncSeriesHook<Stats>} */
done: new AsyncSeriesHook(["stats"]),
/** @type {AsyncSeriesHook<>} */
additionalPass: new AsyncSeriesHook([]),
/** @type {AsyncSeriesHook<Compiler>} */
...
};
...
}
Personal blog recommendation: boiled eggs blog
compile
Inherited tapable
, and then bound an hook
object on the instance.
compilation
compilation
The object contains the current module resources, compiled resources and changed files, etc. Only represents a new compilation .
compilation
Implementation of:
class Compilation extends Tapable {
/** * Creates an instance of Compilation. * @param {Compiler} compiler the compiler which created the compilation */
constructor(compiler) {
super();
this.hooks = {
/** @type {SyncHook<Module>} */
buildModule: new SyncHook(["module"]),
/** @type {SyncHook<Module>} */
rebuildModule: new SyncHook(["module"]),
/** @type {SyncHook<Module, Error>} */
failedModule: new SyncHook(["module", "error"]),
/** @type {SyncHook<Module>} */
succeedModule: new SyncHook(["module"]),
/** @type {SyncHook<Dependency, string>} */
addEntry: new SyncHook(["entry", "name"]),
/** @type {SyncHook<Dependency, string, Error>} */
};
}
}
When running the webpack development environment middleware, whenever a file change is detected, a new one will be created compilation
, thus generating a new set of compiled resources. An compilation
object representing current module resources, build resources, changed files, and state information about tracked dependencies. compilation
The object also provides many callbacks at key moments for the plug-in to choose to use when doing custom processing.
warm up
Write a very basic plugin
:
// 一个 JavaScript 命名函数。
function SimplePlugin() {}
// 在插件函数的 prototype 上定义一个 `apply` 方法。
SimplePlugin.prototype.apply = function (compiler) {
// 指定一个挂载到 webpack 自身的事件钩子。
compiler.plugin("webpacksEventHook", function (
compilation /* 处理 webpack 内部实例的特定数据。*/, callback ) {
console.log("This is an simple plugin!!!");
// 功能完成后调用 webpack 提供的回调。
callback();
});
};
After webpack started, it did the following things:
- Execute first in the process of reading configuration
new SimplePlugin()
, initialize a SimplePlugin and obtain its instance. - After initializing
compiler
the object, call it toSimplePlugin.apply(compiler)
pass in the object for the plugin instancecompiler
. - After the plug-in instance obtains
compiler
the object, it cancompiler.plugin("webpacksEventHook", function(compilation, callback){})
listen to the events broadcast by webpack andcompiler
operate webpack through the object.
combat
Write a practical plugin below.
The role is to do something when webpack is about to close. For example, it tells whether the package is completed and whether the execution is successful. Or execute some script
script. We named it AfterWebpackPlugin
. The usage is as follows:
module.exports = {
plugins: [
// 分别传入成功和失败时的回调函数
new AfterWebpackPlugin(
() => {
// 可以通知用户构建成功,执行发布脚本
},
(err) => {
// 构建失败时,抛出异常
console.error(err);
}
),
],
};
The implementation process here requires the help of the following two hooks:
- done : Occurs when webpack exits immediately after a successful build and output files.
- failed : The build fails when a build exception occurs, and occurs when webpack exits immediately.
The implementation code is as follows:
class AfterWebpackPlugin {
constructor(doneCb, failedCb) {
// 传入回调函数
this.doneCb = doneCb;
this.failedCb = failedCb;
}
apply(compiler) {
compiler.plugin("done", (res) => {
// webpack 生命周期 `done` 中的回调
this.doneCb(res);
});
compiler.plugin("failed", (err) => {
// webpack 生命周期 `failed` 中的回调
this.failedCb(err);
});
}
}
module.exports = AfterWebpackPlugin;
Development plug-in summary:
- Pay attention to finding the appropriate hooks in the webpack life cycle to complete the function.
- Be careful to understand the nuances of each hook in the webpack lifecycle.
expand
The events and explanations that occur during the webpack output phase are as follows:
event name | explain |
---|---|
should-emit | All the files that need to be output have been generated, ask the plug-in which files need to be output, and which ones do not need to be output |
emit | After determining which files to output, execute the file output, you can get and modify the output content here |
after-emit | file output complete |
done | Successfully completed a complete compilation and output process |
failed | If an exception is encountered in the compilation and output process, causing webpack to exit, it will directly jump to this step, and the plug-in can obtain the specific error cause in this event |
Well, the above is all the content of this article, I hope it will be helpful to you, and I hope you will give a lot of support to Code Farmer's House . Your support is the driving force for my creation! I wish you all a happy life!