The five cores of the Webpack introductory tutorial [entry, output, mode, loader (regular expression), plugin], configuration files, plug-ins, css and pictures in the processing project

Introduction to Webpack (I) five cores [entry, output, mode, loader (regular expression), plugin], configuration file, plug-in, css and pictures in processing project

Summary:

  • Introduction + five cores

  • General process

    • Initialize a project with npm init and install webpack
    • Copy the three previously created files into the project
    • On the command line, enter webpack index.js
    • Change the index.js file introduced in index.html to. / dist/main.js file and run it in the browser
      • If you do not want the code to be compressed, you can add -- mode development after the command to indicate that it is packaged in the development mode (the development mode will not compress the code)
    • When webpack is packaged, the webpack.config.js file in the project root directory will be used as the configuration file by default. Therefore, you can change the default configuration of webpack by creating a new webpack.config.js file
  • Function and difference of - S -D during npm installation

    • -S

      • Namely--save((save)
        The package name will be registered in package.json of dependencies In the production environment, the dependency of this package still exists
        
    • -D

      • Namely--dev((production)
        The package name will be registered in package.json of devDependencies Inside, the package exists only in the development environment-D,as babel,sass-loader These parsers
        

        They are different from dependencies because they only need to be installed on the development machine and do not need to run code in the production environment

  • Plug in

    • CleanWebpackPlugin: automatically clear the old files every time you pack. The output.path directory is cleared by default
    • html webpack plugin: generates an html file and automatically introduces the packaged js file
    • MiniCssExtractPlugin: extract css into a separate file and import it through link
    • Optimize cssassets webpack plugin: in order to reduce the file volume, we usually compress the css file
  • The loader handles the style file css in the project

    • webpack cannot process css files by default, so you need to use css loader to process css files in the project. Create a new css file and import it in js. You must import it in js (not in html)
    • The loader needs to be configured in the module.rules of the webpack configuration file
    • step
      • Install CSS loader and add configuration in the configuration file
      • Install style loader and continue to modify the configuration
        • The function of style loader is to insert css into the style tag in the head
      • Execute the package command and open the index.html file in the browser
  • The loader processes the photos in the project

    • file-loader
      • Only bg.jpeg introduced by css is packaged and output, and the imported image path is replaced by the packaged path. There are problems with the images directly introduced by js and html
      • For images dynamically added through js, we can use the require() method to introduce
      • Modify the file loader parameter (solve the problem of js importing pictures)
    • html-loader
      • For images in html, we can use html loader or html withimg loader
      • Therefore, when there is ejs syntax in html, we can't use html loader to process images, but directly use ejs syntax to introduce
    • deploy
      • So far, all our files are exported to dist directory, which is not convenient for later release and launch
      • For example, css files are output to the style directory, pictures are output to the images directory, js is output to the js Directory
      • Modify the webpack configuration and repackage
    • url-loader
      • Use URL loader instead of file loader. URL loader will encode and package small images into files based on 64 to reduce the number of network requests
    • image-webpack-loader
      • Compress pictures

1, Basic concepts

1. What is webpack

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

2. Understand module, chunk and bundle

In webpack, everything is a module, and any file can be regarded as a module. js, css and pictures are all modules.
webpack will introduce the entry file and its dependencies into a chunk, and then package it into a bundle after a series of processing.

3. Five cores of webpack

(1) entry
The entry of webpack package. Its value can be string, array or an object

// Single entry single file
entry: "./src/index.js"

// Single entry multi file
entry: ["./ src/index.js", "./src/common.js"] // If index.js and common.js have no dependency, they can be packaged together in this way

// Multiple entry
entry: {
  page1: "./src/page1.js",  //page1 and page2 are key values
  page2: "./src/page2.js"
}

(2) output
The output packaged by webpack is commonly configured as follows

output: {
  path: path.resolve(__dirname, "./dist"),
  // Single entry (default)
  // filename: "main.js",
  // Filename: "JS / main. JS"
  // In case of multiple entries, the file name cannot be written dead because there will be multiple outputs
  filename: "[name].js", // Name indicates the name of the chunk. Here is the key value in the entry
  chunkFilename: "[name].js", // The packaged name of the module loaded on demand
  publicPath: "/" // The path where the project is deployed on the server. If it is in the root path, otherwise/
}

(3) mode
webpack packaging is divided into two modes: development mode and production mode. The default mode is production mode

optiondescribe
developmentProcess.env.node_ The value of Env is set to development. Enable NamedChunksPlugin and namedmodules plugin.
productionProcess.env.node_ The value of Env is set to production. Enable FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin

(4) loader
By default, webpack can only process files in js and json formats, while the role of loader is to convert files in other formats into files that webpack can process

The loader needs to be configured in the module.rules of the webpack configuration file

module.exports = {
 entry: ...,
 output: ...,
 module: {
   noParse:  /node_modules/, //Ignore resolving node_ Files in modules
   rules: [
     {
       test: /\.xxx$/, // Match the file with suffix xxx; Regular matching rule: ^ indicates the starting position of the string
//$represents the end position of the string, and / / in / \. xxx $/ represents the inherent position of the regular expression
       // Single loader
       // loader: "xxx-loader",
       // options: {},
       // Multiple loaders. The processing order of loaders is from back to front, so the loaders that need priority processing are placed at the end of the array
       // use: ["xxxx-loader", "xxx-loader"],
       //  If a loader needs to be configured, write it in the following format
       use: [
         {
           loader: "xxxx-loader",
           options: {}
         },
         "xxx-loader"
       ],
       include: [path.resolve(__dirname, "./src")], // Only parse the files in src, which can be regular files
       exclude: [path.resolve(__dirname, "./library")], // Ignore the files in the library, which can be regular
       // When multiple rules match a certain type of file at the same time, you can use the enforce parameter to specify the priority
       enforce: "pre" // The loader in the rule is executed first, and the loader in the rule is executed last
     },
     {
       // When the rules match, the following rules are no longer matched. For example, if a file matches the first rule, it will no longer match the following rule
       oneOf: [
         {
           test: /\.xxx$/,
           use: "xxx-loader"
         }, 
         {
           test: /\.xxx$/,
           use: "xxx-loader"
         }
       ] 
     }
   ]
 }
}

(5) plugin
webpack plug-ins. Each plug-in has a specific function, which can handle things that the loader cannot handle
The use of plug-ins is very simple. Just add the instantiation object of the plug-in in the plugins array

const xxxWebpackPlugin = require("xxx-webpack-plugin");
module.exports = {
  entry: ...,
  output: ...,
  plugins: [
    new xxxWebpackPlugin(),
    new xxxxWebpackPlugin({
      // Configuration items for plug-ins
    })
  ]
}

2, Simple use of webpack

  1. Create util.js, index.js, index.html, and write the following
// util.js
export const print = (str) => {
  console.log(str);
};

// index.js
import {print} from "./util";
print("hello webpack");

// index.html
...
<!-- stay body Introduced in index.js -->
<body>
<script src="./index.js"></script>
</body>
...
  1. Open index.html in the browser and find an error on the console

Because the browser does not support the modular syntax of es6, webpack can work at this time

  1. Initialize a project with npm init and install webpack

    NPM I webpack cli - g / / global installation
    NPM I webpack cli - D / / installed in the project

4. Copy the three newly created files into the project. The structure is as follows:

  1. On the command line, enter webpack index.js

index.js indicates the entry file. Since the default output of webpack is dist/main.js, there is no need to specify the exit. You can also use webpack entry -o output to specify the exit

After executing the command, you will find that a dist folder and the main.js file are generated on the left

  1. Change the index.js file introduced in index.html to. / dist/main.js file and run it in the browser

It runs successfully without error

When you open main.js, you will find that the code in it has been compressed. If you don't want the code to be compressed, you can add -- mode development after the command to indicate that it is packaged in the development mode (the development mode will not compress the code)

Use profile

It is very cumbersome to enter a long string of commands during each package. You can add scripts in package.json, as shown in the following figure

Then it is packaged by npm run build:dev or npm run build:pro (build:dev and build:pro are user-defined names)

When webpack is packaged, the webpack.config.js file in the project root directory will be used as the configuration file by default. Therefore, you can change the default configuration of webpack by creating a new webpack.config.js file

// webpack.config.js
module.exports = {
  //mode: "development", / / because the packaging mode is specified in the package.json script, it does not need to be set
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "main.js",
  }
}

3, HtmlWebpackPlugin and CleanWebpackPlugin

Copy a copy of index.html to the dist directory, and modify the main.js path it introduces to the correct relative path
Create a new server.js file and add the following code (using the express framework in NodeJS)

const express = require("express"); // Install npm i express -D first
const path = require("path");
const app = express();
app.use(express.static(path.resolve(__dirname, "dist"), {maxAge: 3600000}))
app.listen(3000);

Enter node server.js on the command line, and then open 127.0.0.1:3000 in the browser. The results are as follows

Modify the parameter of the print function in index.js to "hello node", repackage and refresh the page

The print results were not updated because the browser's strong cache took effect and did not request new files. The cache is based on the url. As long as the url changes, the cache will become invalid. We only need to modify the js file name to modify the corresponding url. Therefore, we want the packaged file name to be generated dynamically according to the file content. At this time, we can modify the configuration as

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[chunkhash:10].js", // The hash value of the chunk content, which will be described in detail later
  }
}

Package and refresh the page (remember to modify the js file name introduced in. / dist/index.html)

It can be found that the file name has changed and the cache problem has been successfully solved. However, the change of file name raises two new problems

  1. You have to manually modify the js file name introduced in html every time you package
  2. The new file will not overwrite the old file, and there are more and more files in the output directory

HtmlWebpackPlugin and CleanWebpackPlugin can solve these two problems for us

npm i html-webpack-plugin clean-webpack-plugin -D

CleanWebpackPlugin: automatically clear the old files every time you pack. The output.path directory is cleared by default
html webpack plugin: generates an html file and automatically introduces the packaged js file

Add plugins configuration in config

const  HtmlWebpackPlugin  = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.export = {
  ...
  plugins: [
    new HtmlWebpackPlugin(),
    new CleanWebpackPlugin()
  ]
}

The html generated by the final package is shown in the figure below, which automatically helps us introduce js files

The html automatically generated by HtmlWebpackPlugin has no content. If you need to generate according to the existing html, you can specify a template for the plug-in. The common parameters are as follows

module.exports = {
  // The three entries here are to explain the chunks and excludeChunks of htmlwebpack plugin
  entry: {
    page1: "./src/page1.js",
    page2: "./src/page2.js",
    common: "./src/common.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: "index.html", // The file name of the generated html
      template: "index.template.html", // Specify template
      title: "hello webpack", // Set the title of html, which can be introduced in html through ejs syntax
      inject: true, // By default, the script tag is located at the bottom of the body, and the optional values are body, header and false (indicating that JS is not automatically introduced) 
      hash: false, // true means adding a hash value as a parameter after the imported js file, SRC = "main. js"? 78ccc964740f25e35fca"
      chunks: [page1, common], // There will be multiple files in multi entry packaging. All files are imported by default. This configuration means that only page1 and common are imported
      minify: {
        collapseWhitespace: true,   // Remove spaces
        minifyCSS: true, // Compress html inline css
        minifyJS: true,  // Compress html inline js
        removeComments: true,  // Remove comment
      }
    }),
    // Multiple pages require new multiple objects
    new HtmlWebpackPlugin({
      ...
      excludeChunk: [page1], // page1 does not need to be introduced, that is, only page2 and page2 are introduced
    }) 
  ]
}

// index.html
...
<head>
  <!-- After packaging, it will be replaced with the in the plug-in parameters title — hello webpack -->
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>
...

4, Working with style files in a project

webpack cannot process css files by default, so you need to use css loader to process css files in the project
Create a new css file and import it in js. Be sure to import it in js (no need to import it in html)

// index.css
body {
  background-color: plum;
}

// index.js
...
import "./index.css"

Install CSS loader and add configuration in the configuration file

npm i css-loader -D

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: "css-loader"
      }
    ]
  }
}

Execute the package command and open the index.html file in the browser

As shown in the figure above, the background color of the page has not changed, and there is no style in html

Although css is packaged in js files, it does not work on the corresponding elements. At this time, it needs to be handled by style loader
Install style loader and continue to modify the configuration to

npm i style-loader -D

module: {
  rules: [
    {
      test: /\.css$/,
      use: ["style-loader", "css-loader"] // From back to front, execute CSS loader first, and then style loader
    }
  ]
}

Repackage and refresh the page. The final effect is shown in the figure below

Therefore, the function of style loader is to insert css into the style tag in the head

In the actual project development, we may need to extract the css into a separate file and introduce it through link, so we can use the MiniCssExtractPlugin plug-in to do this

Install MiniCssExtractPlugin and replace style loader with MiniCssExtractPlugin.loader. Modify the configuration as follows

npm i mini-css-extract-plugin -D

output: {
  path: path.resolve(__dirname, "./dist"),
  filename: "[name].js" // For ease of understanding, we change [chunkash: 10]. JS to [name].js, indicating the name of the chunk
},
module: {
  rules: [
    {
      test: /\.css$/,
      use: [MiniCssExtractPlugin.loader, "css-loader"]
    }
  ]
},
plugins: [
  new MiniCssExtractPlugin(),
  new CleanWebpackPlugin(),
  new HtmlWebpackPlugin({
    template: "index.html",
    title: "hello webpack"
  })
]

The file and page effects generated after packaging are shown in the figure below

CSS is separately packaged into main.css (because index.css and index.js belong to the same chunk, their chunkname is main), and the generated html file is imported using link (the html webpack plugin helps us do this)

In order to reduce the file size, we usually compress the css file by using the optimizecssassatswebpackplugin plug-in
Install optimizecssasassetswebpackplugin and add

npm i optimize-css-assets-webpack-plugin -D

plugins: [
  ...
  new OptimizeCssAssetsWebpackPlugin()
]

In order to demonstrate the effect, add a little more style in index.css, and then package it. It is found that the content of the output CSS file is compressed to one line

For. Less,. scss and other style files, you only need to install the corresponding loader and add configuration. Take less as an example

{
  test: /\.less$/,
  use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
}

5, Working with pictures in a project

Like style files, webpack cannot process images by default, so it needs a corresponding loader to process them
Install file loader and add corresponding configuration

npm i file-loader -D

// Add in module.rules
{
  test: /\.(png|jpe?g|gif|svg)$/,
  use: {
    loader: "file-loader",
    options: {
      name: "[name]-[contenthash:10].[ext]" // ext indicates the suffix of the file
    }
  }
}

Modify and package the index.html, index.css and index.js files, as shown in the following figure

Preview Results

As can be seen from the above two figures, only bg.jpeg imported from css is packaged and output, and the imported image path is also replaced with the packaged path. There are problems with the images directly imported from js and html

For images dynamically added through js, we can use the require() method to introduce

photo.src = require("./images/vue.jpeg");

Package preview, the results are as follows

The image is packaged and output, but the src path is incorrect and becomes a Module object. That's because the image processed by file loader is exported using ESModule by default, but we use commonJS to import it. There are two ways to solve this problem
Method 1: modify the file loader parameter (recommended, because the processing in html is also introduced using commonJS)

Method 2: modify the code in js as follows

photo.src =  require("./images/vue.jpeg").default;
// perhaps
import img from "./images/vue.jpeg"
photo.src = img;

For images in html, we can use html loader or html withimg loader to process them. Take html loader as an example
Install HTML loader, add configuration, and repackage

npm i html-loader -D

{
    test: /\.html$/,
    use: "html-loader"
}

So far, the pictures in css, js and html can be packaged and processed correctly, but note that the title in the head is not parsed by htmlWebpackPlugin

Because after processing with html loader, htmlWebpackPlugin cannot parse the ejs syntax in html, but outputs it as a string. Therefore, when there is ejs syntax in html, we can't use html loader to process images, but directly use ejs syntax to introduce

<img src="<%= require('./src/images/webpack.jpg') %>">

So far, all our files are exported to dist directory, which is not convenient for later release and online. Therefore, we want different types of files to be exported to different directories, such as css files to style directory, pictures to images directory, js to js Directory

Modify the webpack configuration and repackage

// Modify output
filename: "js/[name].js" // It was "[name].js" before modification
// Add parameters to file loader options
outputPath: "images" // Output to images in dist directory
//  MiniCssExtractPlugin add parameter
new MiniCssExtractPlugin({
  filename: "style/[name].css"
})

You can see that the files are indeed packaged in the corresponding directory, but the pictures introduced by css are not displayed. Analyze the reasons

Images are placed in the images directory, and images / is automatically spelled in front of the image path introduced by css. However, because css is placed in the style directory, the relative path between css and images has changed, so the image path introduced by css cannot be displayed

This problem can be solved by adding a parameter to MiniCssExtractPlugin.loader

{
  test: /\.css$/,
  use: [{
    loader: MiniCssExtractPlugin.loader,
    options: {
      publicPath: "../" // Spell.. / in front of the resource path introduced by css. This is the added parameter
    }
  }, "css-loader"]
}

Pack again to see the effect

ok! The problem of picture display has been solved perfectly. Next, we will make some minor optimization

  1. Use URL loader instead of file loader. URL loader will encode and package small images into files based on 64 to reduce the number of network requests
  2. Use image webpack loader to compress images

npm i url-loader image-webpack-loader -D

{
  test: /\.(jpe?g|png|gif|svg)$/,
  use: [{
    loader: "url-loader",
    options: {
      name: "[name]-[contenthash:10].[ext]",
      outputPath: "images",
      limit: 10 * 1024, // Indicates that pictures less than 10k will be encoded by base64
      fallback: "file-loader", // Pictures larger than 10k are processed by file loader. The default value is not set
      esModule: false
    }
  }, {
    loader: "image-webpack-loader",
    options: {
      disabled: true // When developing or using webpack dev server, it can speed up the initial compilation and, to a lesser extent, the subsequent compilation (from official documents)
    }
  }]
}

It can be seen that only bg.jpeg (21k compressed to 19k) is packaged for output, while webpack.jpg (9.9k) and vue.jpeg (7k) are encoded by base64 and directly packaged into the file. That's all for the processing of pictures

Tags: Javascript Webpack css regex

Posted on Thu, 02 Sep 2021 02:38:12 -0400 by robotman321