What is Loader
Loader is used to convert the “source code” of a module and preprocess files when importing or “loading” a module
All WebPack does is analyze the dependencies of various modules, then form a list of resources, and finally package them into a specified file. As shown below:
Within Webpack, any file is a module, not just a JS file
By default, Webpack only supports packaging JS and JSON files when an import or require module is loaded
Webpack is unable to handle CSS, SASS, PNG files, etc. In this case, you need to configure the corresponding Loader to parse the file content
When loading modules, the order of execution is as follows:
When WebPack encounters an unknown module, WebPack looks for the file resolution rule in the configuration
There are three ways to configure loader:
- Configuration method (recommended) : Specify loader in webpack.config.js
- Inline: Specify loader explicitly in each import statement
- CLI: Specify them in shell commands
Configuration mode
Loader configuration is written in the module.rules property, which is described as follows:
rules
Is in the form of an array, so we can configure manyloader
- each
loader
Corresponds to the form of an object, object propertytest
Is a matching rule, usually a regular expression - attribute
use
For a file type that matches, call the correspondingloader
For processing
Code writing in the following form:
module.exports = {
module: {
rules: [{test: /.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader'.options: {
modules: true}}, {loader: 'sass-loader'}]}};Copy the code
Ii. Loader features
Here we continue with the above code to talk about loader features
As can be seen from the above code, three Loaders are configured in the use property to process CSS files respectively
Since Loaders support chain calls, each loader in the chain will process previously processed resources, which will eventually become JS code. The sequence is reversed, that is, the preceding execution modes are ass-loader, CSS-loader, and style-loader
In addition, loader has the following features:
- The Loader can be synchronous or asynchronous
- Loader runs in Node.js and can perform any operation
- Except for the usual pass
package.json
的main
To export an NPM module as a loader, which can also be used in module.rulesloader
Field refers directly to a module - Plugins can bring more features to the Loader
- Loader can generate additional arbitrary files
You can add more power to the JavaScript ecosystem through loader’s preprocessor functions. Users now have more flexibility to introduce fine-grained logic such as compression, packaging, language translation, and more
Common Loaders
During page development, we often load content other than JS files, so we need to configure a responsive loader to load
Common Loaders are as follows:
- Style-loader: Adds CSS to the DOM inline style tag style
- Css-loader: allows you to import CSS files via require and return CSS code
- Less – loader: deal with less
- Sass – loader: handle sass
- Postcss-loader: uses postCSS to process CSS
- Autoprefixer-loader: processes CSS3 attribute prefixes. This feature is deprecated. You are advised to use PostCSS
- File-loader: distributes files to the output directory and returns the relative path
- Url-loader: similar to file-loader, but returns a Data URL if the file is smaller than the specified limit
- HTML minify – loader: compressed HTML
- Babel-loader: Use Babel to convert ES6 files to ES
The following are some common uses of loader:
css-loader
Analyze the relationship between CSS modules and synthesize a CSS
npm install --save-dev css-loader
Copy the code
rules: [
...,
{
test: /.css$/,
use: {
loader: "css-loader".options: {
// Enable/disable URL () processing
url: true.// Enable/disable @import processing
import: true.// Enable/disable Sourcemap
sourceMap: false}}}]Copy the code
If you only load the file through CSS-loader, the style set by the page code does not take effect
The reason is that csS-loader only parses the.css file and does not insert the parsed CSS into the page
If we want to insert style, then we need another loader, which is style-loader
style-loader
Mount the content generated by CSS-loader into the head of the page using the style tag
npm install --save-dev style-loader
Copy the code
rules: [
...,
{
test: /.css$/,
use: ["style-loader"."css-loader"]}]Copy the code
Multiple Loaders for a task can be mounted at the same time. The processing sequence is from right to left and from bottom to top
less-loader
Less, SASS, and Stylus preprocessors are often used to write CSS styles during development to improve development efficiency. Less-loader is used here
npm install less-loader -D
Copy the code
rules: [
...,
{
test: /.css$/,
use: ["style-loader"."css-loader"."less-loader"]}]Copy the code
raw-loader
Import file contents in Webpack by import. The loader is not built in, so it must be installed first
npm install --save-dev raw-loader
Copy the code
Then configure it in webpack.config.js
module.exports = { ... .module: {
rules: [{test: /.(txt|md)$/,
use: 'raw-loader'}}}]Copy the code
file-loader
Moves the identified resource module to the specified output directory and returns the address of the resource in the output directory (string).
npm install --save-dev file-loader
Copy the code
rules: [
...,
{
test: /.(png|jpe? g|gif)$/,
use: {
loader: "file-loader".options: {
// placeholder [name] The name of the source resource module
// [ext] the suffix of the source resource module
name: "[name]_[hash].[ext]".// The packing location
outputPath: "./images".// The url of the packaged file
publicPath: './images',}}}]Copy the code
url-loader
It can handle all the things of file-loader, but when it comes to the image format module, it can selectively convert the image into base64 format string, and package it into JS. It is suitable for small size image, but not for large image.
npm install --save-dev url-loader
Copy the code
rules: [
...,
{
test: /.(png|jpe? g|gif)$/,
use: {
loader: "url-loader".options: {
// placeholder [name] The name of the source resource module
// [ext] the suffix of the source resource module
name: "[name]_[hash].[ext]".// The packing location
outputPath: "./images"
// The url of the packaged file
publicPath: './images'.< 100 bytes, convert to base64 format
limit: 100}}}]Copy the code
What is Plugin
A Plugin is a computer application that interacts with the main application to provide specific functionality
It is a program that follows a certain standard application program interface and can only run in the specified system, because it needs to call the function library or data provided by the original pure system
The same is true of the Plugin in WebPack, which gives it various flexible features such as package optimization, resource management, environment variable injection, etc., that run at different stages of The WebPack (hook/life cycle) throughout the webPack compilation cycle
The purpose is to solve other things that loader cannot implement
Configuration mode
This is how files are configured. In general, new instance objects are passed in via the plugins property in the configuration file export object. As follows:
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Install via NPM
const webpack = require('webpack'); // Access the built-in plug-in
module.exports = {
...
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({ template: './src/index.html'})]};Copy the code
5. Features of Plugin
It is essentially a javascript object with the Apply method
The Apply method is called by the Webpack Compiler and the Compiler object is accessible throughout the compile life cycle
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, (compilation) = > {
console.log('Webpack build process begins! '); }); }}module.exports = ConsoleLogOnBuildWebpackPlugin;
Copy the code
The first argument to compiler Hook’s tap method should be the camel-named plug-in name
For the entire compile lifecycle hooks, there are the following:
- Entry-option: initializes the option
- run
- Compile: The compilation that actually begins, before the compilation object is created
- Compilation: Generated the compilation object
- Make recursively analyzes dependencies from Entry and prepares to build each module
- After-compile: The build process ends
- Emit: Before writing the contents of assets in memory to the disk folder
- After-emit: After writing the contents of assets in memory to the disk folder
- Done: Completes all compilation
- Failed: Indicates a compilation failure
Common plugins
commonplugin
As shown in the figure:
Here are a few common uses of plug-ins:
HtmlWebpackPlugin
At the end of the packaging, an HTML file is automatically generated, and the JS module generated by the packaging is introduced into the HTML
npm install --save-dev html-webpack-plugin
Copy the code
// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
title: "My App".filename: "app.html".template: "./src/html/index.html"}})];Copy the code
<! --./src/html/index.html-->
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
<h1>html-webpack-plugin</h1>
</body>
</html>
Copy the code
In the HTML template, can pass % > < % = htmlWebpackPlugin. Options. XXX for configuration values
More configurations can be found on their own
clean-webpack-plugin
Delete (clean up) the build directory
npm install --save-dev clean-webpack-plugin
Copy the code
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
...
plugins: [...new CleanWebpackPlugin(),
...
]
}
Copy the code
mini-css-extract-plugin
Extract CSS into a separate file
npm install --save-dev mini-css-extract-plugin
Copy the code
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = { ... .module: {
rules: [{test: /.s[ac]ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'.'sass-loader']]}},plugins: [...new MiniCssExtractPlugin({
filename: '[name].css'}),... ] }Copy the code
DefinePlugin
A global object that allows configuration to be created at compile time is a plug-in built into WebPack and does not require installation
const { DefinePlugun } = require('webpack')
module.exports = {
...
plugins: [new DefinePlugin({
BASE_URL:'". /"}})]Copy the code
When you compile the Template module, you get the global object in the following form
<link rel="icon" href="<%= BASE_URL%>favicon.ico>"
Copy the code
copy-webpack-plugin
Copy files or directories to the execution area. For example, during the vue packaging process, if we put some files in the public directory, the directory will be copied to the dist folder
npm install copy-webpack-plugin -D
Copy the code
new CopyWebpackPlugin({
parrerns:[
{
from:"public".globOptions: {ignore: ['**/index.html']}}]})Copy the code
The rules for replication are set in the Patterns property:
- From: Sets the source from which to start the replication
- To: the location to be copied to, which can be omitted. It will be copied to the packaged directory by default
- GlobOptions: Sets additional options for writing files that need to be ignored
Vii. Differences between Loader and Plugin
We have mentioned the concept of Loader and Plugin, so let’s review it
- Loader is a file loader that loads resource files, performs some processing, such as compilation and compression, on these files, and finally packages them into a specified file
- Plugin gives WebPack a variety of flexible features, such as package optimization, resource management, environment variable injection, etc., to solve the other things that loader cannot implement
From the perspective of the whole operation time, it is shown as the figure below:
You can see the difference in runtime:
- Loader runs before the file is packaged
- Plugins work throughout the compile cycle
A number of events are broadcast during the life cycle of a Webpack run, and the Plugin can listen for these events and change the output when appropriate through the API provided by Webpack
For Loader, it is essentially A converter. It compiles A file into B file and operates the file. For example, it converts A.CSS or A.less into B.CSS
Write loader
Before writing loader, we first need to understand the nature of loader
This is essentially a function in which the context is filled by WebPack, so we can’t make loader an arrow function
The function takes an argument for the file source content that WebPack passes to the Loader
Function this is the object provided by WebPack to get all the information needed by the current loader
The function has asynchronous or synchronous operations, which are returned by this.callback as a string or Buffer
The code looks like this:
// Export a function, source is the file source content that webpack passes to loader
module.exports = function(source) {
const content = doSomeThing2JsString(source);
// If the loader is configured with an options object, this.query will point to options
const options = this.query;
// Can be used as a context to parse other module paths
console.log('this.context');
/ * * this. The callback parameter: * error: error | null, when loader error to throw an error * content: String | Buffer, after loader compiled need to export the * sourceMap: the content of the generated for the convenience of debugging the compiled contents of the source map * ast: The AST static syntax tree generated by this compilation can be used directly by subsequent loaders, thus saving the process of repeatedly generating AST */
this.callback(null, content); / / asynchronous
return content; / / synchronize
}
Copy the code
Generally, in the process of compiling loader, keep a single function and avoid multiple functions
For example, converting less files into CSS files is not a step in one step, but the chain call of less-loader, CSS-loader, and style-loader can complete the conversion
9. Write plugin
Because WebPack is based on a publish-subscribe model, many events are broadcast during the run life cycle, and plug-ins listen for these events so that they can perform their own plug-in tasks at specific stages
As you’ve seen before, webPack compilation creates two core objects:
- Compiler: contains all configuration information of the WebPack environment, including options, loader, plugin, and webPack lifecycle related hooks
- Compilation: Parameter to the plugin’s built-in event callback function, containing the current module resources, compile-generated resources, changed files, and state information about the dependencies being tracked. When a file change is detected, a new Compilation is created
If you want to implement the plugin yourself, you also need to follow certain specifications:
- A plug-in must be a function or an include
apply
Method in order to accesscompiler
The instance - Passed to each plug-in
compiler
和compilation
The object is the same reference and therefore is not recommended to be modified - Asynchronous events need to be notified by calling the callback function when the plug-in has finished processing the task
Webpack
Go to the next flow or it will get stuck
The template to implement the plugin is as follows:
class MyPlugin {
// Webpack calls the apply method of the MyPlugin instance to pass the Compiler object to the plug-in instance
apply (compiler) {
// Find the appropriate event hooks to implement your own plugin functionality
compiler.hooks.emit.tap('MyPlugin'.compilation= > {
// compilation: Context of the current packaging build process
console.log(compilation);
// do something...}}})Copy the code
At the time of the EMIT event, the conversion and assembly of the source file is complete, and you can read the final output resources, code blocks, modules and their dependencies, and modify the contents of the output resources