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:

  • rulesIs in the form of an array, so we can configure manyloader
  • eachloaderCorresponds to the form of an object, object propertytestIs a matching rule, usually a regular expression
  • attributeuseFor a file type that matches, call the correspondingloaderFor 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 passpackage.json 的 mainTo export an NPM module as a loader, which can also be used in module.rulesloaderField 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

commonpluginAs 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 includeapplyMethod in order to accesscompilerThe instance
  • Passed to each plug-incompiler 和 compilationThe 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 taskWebpackGo 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