Webpack start

Time:2021-12-31

webpack

Webpack is a front-end resource packaging tool. It performs static analysis according to the dependencies of modules, and then generates corresponding static resources according to the specified rules.

Basic use

Install webpack locally

yarn add webpack webpack-cli --dev

File directory, createwebpack.config.jsConfiguration file (in webpack V4, no configuration is required, but most projects require complex settings).

const path = require("path");

module.exports = {
  /**
   *The default value is production
   *Development optimizes the packaging speed and adds some assistance required by the debugging process
   *Production optimization packaging results
   **/
  mode: "development",
  Entry: ". / SRC / main. JS", // entry file
  output: {
    Filename: "bundle. JS", // output filename
    path: path. Join (_dirname, "dist"), // output file path
  },
};

Run package command

yarn webpack

Resource module loading

Webpack can only process JS files by default, and non JS files can be loaded and processed through loader

File resources

Loader corresponding to installation file resource

yarn add css-loader style-loader --dev

File import

// main.js

import createHeading from "./heading.js";
import "./main.css";

const heading = createHeading();

document.body.append(heading);

Webpack profile

adoptcss-loaderTo complete the processing of CSS files, you need tostyle-loaderBring the packaged CSS file into the page

Note: the recording mechanism of the loader is from back to front, so the CSS loader in the array is used first, and the style loader is used later

const path = require("path");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

Picture resources

becauseindex.htmlNot generated todistInstead, it is placed in the root directory of the project, so the project root directory is taken as the root directory of the website, and webpack will default that all packaging results are placed under the root directory of the website, resulting in finding image resources in the root directory. Solution configurationpublicPath: 'dist/'

The image file encountered during webpack packaging is matched to the file loader according to the configuration file configuration. The file loader starts to work. First copy the imported file to the output directory, and then copy the file to the path after the output directory, which is returned as the return value of the current module, so that the resource is published.

Install the loader corresponding to the picture resource

yarn add file-loader --dev

File import

import createHeading from "./heading.js";
import "./main.css";
import icon from "./icon.png";

const heading = createHeading();

document.body.append(heading);

const img = new Image();
img.src = icon;
document.body.append(img);

Webpack profile

const path = require("path");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    publicPath: "dist/",
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: "file-loader",
      },
    ],
  },
};

URL resource

data urlsIt’s specialurlProtocols can be used to directly represent a file, traditionalurlThe server is required to have a corresponding file, and then we get the corresponding file by requesting this address. anddata urlIs a currenturlIt can directly represent the content of the fileurlThe text in contains the contents of the file and will not send any HTTP requests when used.

HTML content:data:text/html;charset=UTF-8,<h1>xxx</h1>

Png type file:data:image/png;base64,iVBORw0KGgoAAAANSUhE...

Install the loader corresponding to the resource

yarn add url-loader --dev

Webpack profile

...
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: {
          loader: "url-loader",
          options: {
            Limit: 10 * 1024, // use URL loader for image resources less than 10KB, and file loader for image resources greater than 10KB
          },
        },
      },
    ],
  },

Common loader classification

  • Compile conversion class
  • File operation class
  • Code check class

Webpack and es2015

Webpack handles import and export because the module needs to be packaged, but it cannot convert other ES6 features in the code

Install the loader corresponding to the resource

yarn add babel-loader @babel/core @babel/preset-env --dev
module: {
    rules: [
      {
        test: /.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.png$/,
        use: {
          loader: "url-loader",
          options: {
            Limit: 10 * 1024, // use URL loader for image resources less than 10KB, and file loader for image resources greater than 10KB
          },
        },
      },
    ],
  },

Module loading mode

Modules are loaded in accordance with ES modules standardsimportDeclaration, following the common JS standardrequireFunction, following amd standarddefineFunction sumrequirefunction

In addition to the above methods, the trigger module loading method also includes the methods in CSS style codeurlFunction sum@importInstruction, image tag in HTML codesrcattribute

HTMLsrcProperty triggers module loading

yarn add html-loader --dev
{
  test:/.html$/,
  use:{
    loader:'html-loader'
  }
}

However, HTML loader can only handle img: SRC attributes under HTML, and other additional attributes are configured through attrs

{
  test:/.html$/,
  use:{
    Loader: 'HTML loader', // only the HTML img SRC attribute can be processed by default, and other additional attributes can be configured through attrs
    options:{
      attrs:['img:src','a:href']
    }
  }
}

Develop a loader

The resource loading process of webpack is similar to the work pipeline. Multiple loaders can be used in turn during the loading process, but the final result must be JS code.

Each webpack loader needs to export a function. The input is the content of the loaded resource file, and the output is the result of this processing.

const marked = require("marked");

module.exports = (source) => {
  const html = marked(source);
  return html;
};
module: {
  rules: [
    {
      test: /.md$/,
      use: [
        "html-loader",
        ".. / MD loader", // module name or file path, similar to nodejs require
      ],
    },
  ];
}

Plug in mechanism

Loader focuses on loading resource modules, plugin solves other automation work, and enhances the automation ability of webpack

Auto clear directory plugin

Install expansion pack

yarn add clean-webpack-plugin --dev
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    publicPath: "dist/",
  },
  module: {
    rules: [
      ...
    ],
  },
  plugins: [new CleanWebpackPlugin()],
};

Automatically generate HTML

Install expansion pack

yarn add html-webpack-plugin --dev

Generate HTML under dist to solve the problem that the introduction path in the HTML under the root needs to be hard coded through the public path declaration.

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    // publicPath: "dist/",
  },
  plugins: [new CleanWebpackPlugin(), new HtmlWebpackPlugin()],
};

user-defined metadata

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "webpack plugin sample",
      meta: {
        viewport: "width=device-width",
      },
      template: "./src/index.html",
    }),
  ],
};

template file

<!--./src/index.html-->
<!DOCTYPE html>
<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>Webpack</title>
  </head>
  <body>
    <div class="container">
      <!--  Accessing plug-in configuration data -- >
      <h1><%= htmlWebpackPlugin.options.title %></h1>
    </div>
  </body>
</html>

Output multiple page files at the same time

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "webpack plugin sample",
      meta: {
        viewport: "width=device-width",
      },
      template: "./src/index.html",
    }),
    new HtmlWebpackPlugin({
      filename: "about.html",
    }),
  ],
};

Static file copy plug-in

yarn add copy-webpack-plugin --dev
const CopyWebpackPlugin = require("copy-webpack-plugin");

plugins: [
  //Parameter array, specifying the copied file path (wildcard, directory, relative path)
  new CopyWebpackPlugin({
    patterns: ["public"],
  }),
];

How the plug-in mechanism works

The webpack plugin is implemented through the hook mechanism.

The hook mechanism is similar to events in the web. There are many links in the working process of webpack. In order to facilitate the extension of plug-ins, webpack has buried hooks in almost every link, so that when developing plug-ins, we can easily expand the ability of webpack by loading different tasks on these different nodes.

Develop a plug-in

Webpack requires that the plug-in must be a function or an object containing an apply method. Generally, we will define the plug-in as a type and then define an apply method in this type

Define a plug-in to mount tasks on the hook. This plug-in is used to clear the bundle Useless comments in JS

Myplugin file

module.exports = class MyPlugin {
  apply(compiler) {
    //This method is automatically called when the webpack is started. Compile configuration object and configuration information

    console. Log ("myplugin startup");

    //Access the hook emit through the hooks property
    //Reference: https://webpack.docschina.org/api/compiler-hooks/
    //The tap method registers the hook function (parameter 1: plug-in name, parameter 2: function attached to the hook)

    compiler.hooks.emit.tap("MyPlugin", (compilation) => {
      //Compilation can be understood as the context of this packaging, and all the results of the packaging process will be put into this object
      // compilation. The assets property is an object used to obtain the information of the resource file to be written to the directory

      for (const name in compilation.assets) {
        // console. Log ("file name:", name); As shown in the figure
        // console. Log ("file content:", compilation. Assets [name]. Source());

        if (name.endsWith(".js")) {
          //Get content
          const contents = compilation.assets[name].source();

          //Replace content
          const withoutComments = contents.replace(/\/\*\*+\*\//g, "");

          //Overwrite old content
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments. Length, // returns the size of the content. Webpack must be added
          };
        }
      }
    });
  }
};

configuration file

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const myPlugin = require("./MyPlugin.js");

module.exports = {
  mode: "none",
  entry: "./src/main.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
    // publicPath: "dist/",
  },

  plugins: [new CleanWebpackPlugin(), new myPlugin()],
};