Learn webpack in 10 minutes

what is webpack


webpack is a static, modular packaging tool for modern JavaScript applications.

The front end is now more and more complex:

  • For example, in the development process, we need to develop in a modular way;
  • For example, some advanced features will be used to speed up our development efficiency or security, such as developing script logic through ES6+ and TypeScript, and writing css style code through sass and less;
  • For example, during the development process, we also hope to monitor the changes of files in real time and reflect them on the browser to improve the efficiency of development;
  • For example, after the development is completed, we need to compress, merge and optimize the code;

We can use tools to solve these problems, such as using Babel to convert es6 for compatibility, and using tsc to convert ts code. Then use the converted js to import it into html. The same goes for css. But we will find that it is very troublesome to deal with them one by one, so we need a build tool that can help us complete these things automatically. webpack is one such tool.

basic use

The official document of webpack is https://webpack.js.org/
The official document of webpack in Chinese is https://webpack.docschina.org/

  • DOCUMENTATION: The details of the document are also what we are most concerned about

The operation of Webpack depends on the Node environment, so we must have a Node environment on our computer.

Install

npm install webpack webpack-cli –g # 全局安装
npm install webpack webpack-cli –D # 局部安装

webpack 和 webpack-cli

webpack is the core code, and webpack-cli is a command-line tool that allows us to operate webpack on the command line.

The packaging command of webpack is that webpackwhen the cli is installed, we can directly enter webpack on the command line to start packaging.
Commands can also be added in the package.json script webpack. Use npm to start webpack packaging. The script commands in npm are equivalent to typing and executing on the command line.

As a command-line tool, webpack-cli is of course not installed. In fact, third-party scaffolding does not use webpack-cli, but uses something similar to its own vue-service-cli.

Packaged by default

We enter webpack on the command line to start packaging. At this time, there is a question, who is packaging by webpack? And who is packed where?
In fact, when we run webpack, webpack will look for src/index.js in the current directory as the entry point; therefore, if there is no src/index.js file in the current project, an error will be reported; a dist file will be generated after packaging Folder, which stores a main.js file, which is the file after we pack it.

This is the default packaging behavior, so can we change the entry and exit? Of course it can be changed. We can configure the packaging behavior by adding parameters to the webpack command.

webpack --entry ./src/main.js --output-path ./build

The above command reconfigures the packaging entry and exit of webpack.
However, there are many configurations of webpack, and it is unrealistic to configure them all by command line, so webpack also provides a configuration file. webpack.config.jsWhen webpack starts, it will read this file by default for configuration.
Of course, we can also specify the configuration file to read:

webpack --config wk.config.js

Understanding webpack

Understanding webpack

webpack.config.js

We mainly configure 8 aspects of webpack:

  1. mode: build mode
  2. entry: entry
  3. output: export
  4. module.rules: loader in module rules
  5. plugins: plugin
  6. devServer: development server
  7. resolve: module resolution
  8. devtool:source map

This article introduces from the perspective of using webpack to build a project from 0.

const path = require("path")

module.exports = {
    
    
  mode: "development",
  entry: "./src/index.js",
  output: {
    
    
    filename: "bundle.js",
    path: path.resolve(__dirname, "./dist"),
  },
  module: {
    
    
    rules: []
  },
  plugins: []
}

Entry file directory

Our previous rules for writing entry files are as follows: ./src/index.js, which directory does this ./ refer to? Is it the directory where the configuration file webpack.config.js is located?
If the location of our configuration file becomes the config directory, changing the entry to .../src/index.js will result in an error. The entry should still be written as ./src/index.js;

This is because the entry file is actually a context related to another attribute;
the role of context is to resolve entry points and loaders: by default, it represents the startup directory of webpack.

Therefore, it is recommended to manually change the entry directory to the directory where the configuration file is located, which is more intuitive:

module.exports = {
    
    
	context: path.resolve(__dirname, "./")
}

loader

There are three ways to use loader

  1. Inline method: add the loader used before the imported style, and use ! to split;
import "css-loader!./css/style.css"
  1. Command line mode: –module-bind
  2. configuration file

The first two methods are rarely used because they are not easy to manage, especially the command line method, which has been eliminated by webpack5. The main way is to use the configuration.

configuration method

The configuration of module.rules is as follows:
The value corresponding to the rules attribute is an array: [Rule]

  • Each Rule is stored in the array, and Rule is an object, and multiple attributes can be set in the object to add module rules.
    • test attribute: used to match resources (resources), usually set to regular expressions;
    • use attribute: the corresponding value is an array: [UseEntry]
      • UseEntry is an object, you can set some other properties through the properties of the object
        • loader: There must be a loader attribute, and the corresponding value is a string;
        • options: optional attribute, the value is a string or object, and the value will be passed to the loader;
        • query: options have been used instead;
      • Passing a string (such as: use: [ 'style-loader' ]) is a shorthand for the loader attribute (such as: use: [ { loader: 'style-loader'} ]);
    • loader attribute: Shorthand for Rule.use: [ { loader } ] .

In addition, use is an array, and multiple loaders can be used for the same type of file.
The order in which loaders take effect is in accordance with the order in the use array, from back to front.

module: {
    
    
  rules: [
    {
    
    
      test: "正则",
      use: [
        {
    
     loader: "loader名", options?: {
    
    "可选的属性"} }, 
        {
    
    },
        {
    
    }
      ]
		},
    {
    
    },
    ...
  ]
}

In addition to the complete way of writing use, there are two kinds of grammatical sugar writing:

  1. Pass the string directly to the use array

It is shorthand for the loader attribute in useEntry:

use: [{
    
    loader: "css-loader"}]

use: ["css-loader"]
  1. Use the loader instead of the use array, and don't write the use array directly.
{
    
    
  test: "正则",
  use: []
}

{
    
    
  test: "正则",
  loader: "css-loader"
}

Of course, when you need to configure the loader, you still need to use the complete wording.

Processing style files

css-loader

To parse css files, you need to use css-loader.
Install:npm install css-loader -D

We can already load css files through css-loader, but you will find that this css does not take effect in our code (the page has no effect).
Because css-loader is only responsible for parsing the .css file, and will not insert the parsed css into the page; if we want to complete the operation of inserting style, then we need another loader, which is style-loader.

style-loader

Installation: npm install style-loader -D
Note: style-loader also works on css files, so in the same use array as css-loader, it must be loaded before inserting, and style-loader must be placed in front of css-loader to let css-loader take effect first.

style-loader inserts the content of the css file as an inline <style></style>style, so how to import the css file as a link?

less-loader

less is a separate tool, usually we can use it directly, it will automatically convert less files into css files in the same directory.
Install:npm i less -D

The less file is introduced into the packaged js file, so naturally the corresponding loader should be used to load it.
Install:npm i less-loader -D

PostCSS Tools

What is PostCSS?

  • PostCSS is a tool to transform css through JavaScript;
  • This tool can help us perform some CSS transformations and adaptations, such as automatically adding browser prefixes and resetting CSS styles;
  • But to achieve these functions, we need to use the corresponding plug-ins of PostCSS;

postcss is a separate tool like less, we can use it directly on the command line.
Install:npm install postcss postcss-cli -D

To use postcss to insert browser prefixes into css, you need to use its plug-in autoprefixer.
Install: npm install autoprefixer -D
use:npx postcss --use autoprefixer -o end.css ./src/css/style.css

postcss-loader

postcss is a tool in which plug-ins can be installed to achieve certain functions. For example, here is to install autoprefixer to add browser prefixes to css.
We can use the postcss tool alone, of course, we can also add postcss to webpack through the loader.

Install:npm install postcss-loader -D

Because postcss needs a corresponding plugin to work, we need to configure its plugin:

{
    
    
  test: /\.css$/,
  use: [
    "style-loader", 
    "css-loader", 
    {
    
    
      loader: "postcss-loader",
      options: {
    
    
        postcssOptions: {
    
    
          plugins: [
            require("autoprefixer")  
          ]
        }
      }
    }
   ]
},

postcss.config.js

In addition, we can also put the postcss configuration information into a separate file for management, so that there is no need to configure in webpack.config.js, just use it.
Create postcss.config.js in the root directory:

module.exports = {
    
    
  plugins: [require("autoprefixer")]
}

postcss-preset-env

In fact, when configuring postcss-loader, we do not need to use autoprefixer to configure the plugin. It also has a more hanging preset plugin: postcss-preset-env.
postcss-preset-env is also a postcss plug-in; it can help us convert some modern CSS features into CSS recognized by most browsers, and add the required polyfill (patch) according to the target browser or runtime environment ;
It also automatically helps us add autoprefixer (so it is equivalent to having built-in autoprefixer);

First, we need to install postcss-preset-env:npm install postcss-preset-env -D

When we use some postcss plug-ins, we can actually pass in strings directly:

plugins: ["postcss-preset-env"]

Summarize the webpack configuration for processing style files

const path = require("path")

module.exports = {
    
    
  mode: "development",
  entry: "./src/main.js",
  output: {
    
    
    filename: "bundle.js",
    path: path.resolve(__dirname, "./dist"),
  },
  module: {
    
    
    rules: [
      {
    
    
        test: /\.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"]
      },
      {
    
    
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"]
      },
    ]
  }
}
module.exports = {
    
    
  plugins: [require("postcss-preset-env")]
}

Handle static resource files

the way before

To process pictures in jpg, png and other formats, we also need a corresponding loader: file-loader
url-loader and file-loader work in a similar way, but can convert smaller files into base64 URIs.

Before webpack5, we needed to use some loaders to load these resources, such as raw-loader, url-loader, file-loader; starting
from webpack5, we can directly use the resource module type (asset module type) to replace the above loaders;

file naming rules

The file name after webpack packaging is a bunch of meaningless characters by default, which is not easy to distinguish. webpack also provides a way to allow us to control the packaged file name.
This method is PlaceHolders, which is like a placeholder, and the placeholder will be converted into its corresponding content after packaging.
webpack provides us with a large number of PlaceHolders to display different content: we can check the placeholder we need in the documentation.
https://webpack.js.org/loaders/file-loader/

Commonly used placeholders:

  • [ext]: processing file extension;
  • [name]: the name of the processing file;
  • [hash]: The content of the file, processed using the MD4 hash function, generates a 128-bit hash value (32 hexadecimal numbers);
  • [contentHash]: the result is consistent with [hash] in file-loader;
  • [hash:]: Shorten the length of the hash, the default 32 characters is too long;
  • [path]: The path of the file relative to the webpack configuration file;

Set the storage path of the file

If the packaged file path is not set, the files will be packaged to the dist root directory by default and scattered together. Therefore, it is necessary for us to standardize the location of each type of file after packaging.

Set the file path in the loader:

use:[{
    
    
  loader: "url-loader", 
  options: {
    
    
    name: "[name].[hash:4].[ext]",
    outputPath: "img"
  }
}]

In addition to the outputPath attribute, it can also be set directly when specifying the name. We usually use this method because it is very convenient.

use:[{
    
    
  loader: "url-loader", 
  options: {
    
    
    name: "img/[name].[hash:4].[ext]"
  }
}]

In addition to the above setting for a certain type of file, the file path can also be set globally. If the file name is also set locally, the global file name will be invalid for this type of file.

module.exports = {
    
    
  output: {
    
    
    filename: "bundle.js",
    path: path.resolve(__dirname, "./dist"),
    assetModuleFilename: "img/[name]_[hash:4][ext]"
  }
}

asset module type

The asset module type replaces all these loaders by adding 4 new module types:

  • asset/resource sends a separate file and export URL. Previously achieved by using file-loader;
  • asset/inline exports the data URI of an asset. Previously implemented by using url-loader;
  • asset/source exports the source code of the asset. Previously achieved by using raw-loader;
  • asset automatically chooses between exporting a data URI and sending a separate file. Previously, it was realized by using url-loader and configuring the upper limit of resource volume;

basic use

There is no need to use the loader, so there is no need to use, just use type to declare the type.

module: {
    
    
  rules: [
    {
    
    
      test: /\.(jpe?g|png|gif|svg)$/,
      type: "asset",
      // 局部设置打包后的文件名和路径
      generator: {
    
    
          filename: "img/[name]_[hash:6][ext]"
        },
      // 打包大小限制
      parser: {
    
    
        dataUrlCondition: {
    
    
          maxSize: 100 * 1024
        }
      }
    }
  ]
}

Huizhong's configuration for processing static files

module: {
    
    
    rules: [
      {
    
    
        test: /\.(jpe?g|png|gif|svg)$/,
        type: "asset",
        generator: {
    
    
          filename: "im/[name]_[hash:6][ext]"
        },
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 100 * 1024
          }
        }
      },
      {
    
    
        test: /\.(eot|ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "font/[name]_[hash:6][ext]"
        }
      }
    ]
  }
}

plugins

webpack plugin

mode

The Mode configuration option can tell webpack to use the built-in optimization of reactive mode:

  • The default value is production (when nothing is set);
  • Possible values ​​are: 'none' | 'development' | 'production';

What is the difference between these options?
image.png
Configuring mode is actually equivalent to a preset, and each value of mode represents many configurations.
image.pngimage.png

Babel

Babel

Use vue in webpack

Use vue in webpack

Build a local server devServer

Webpack builds a local server

Source Map

SourceMap

resolve

resolve is used to set how the module is parsed, for example, if the js suffix is ​​not written, how does webpack know to import the js file with the same name.

  • In development, we will have various module dependencies, these modules may come from the code written by ourselves, or from third-party libraries;
  • resolve can help webpack find the appropriate module code that needs to be imported from each require/import statement;
  • webpack uses the library enhanced-resolve to resolve file paths;

webpack can resolve three file paths:

  • absolute path
    • Since the absolute path of the file has been obtained, no further parsing is required.
  • relative path
    • In this case, the directory where the resource file using import or require is located is considered the context directory;
    • The relative path given in import/require will concatenate this context path to generate the absolute path of the module;
  • module path
    • All directory retrieval modules specified in resolve.modules;
    • The default value is ['node_modules'] , so the file will be found from node_modules by default;
    • We can replace the first-knowledge module path by setting an alias, and the configuration of alias will be explained later in detail;

Module import process

If a file:

  • If the file has an extension, pack the file directly;
  • Otherwise, the extension set in the resolve.extensions option will be used as the file extension for completion and then search and resolution;

If it is a folder:

  • It will search in the folder according to the file order specified in the resolve.mainFiles configuration option;
    • The default value of resolve.mainFiles is ['index']; so enter a directory and load the index file in it by default
    • Then resolve the extension according to resolve.extensions;

extensions and alias configuration

extensions is to automatically add extensions when parsing to files:

  • The default value is ['.wasm', '.mjs', '.js', '.json'];
  • So if we want to automatically load files such as .vue or jsx or ts without writing the suffix in our code, we need to add them in extensions;

Another very useful function is to configure the alias alias:

  • Especially when the directory structure of our project is relatively deep, or the path of a file may require path fragments such as .../.../.../;
  • We can give some common paths an alias;
module.exports = {
    
    
	resolve: {
    
    
    extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"],
    alias: {
    
    
      // __dirname 表示当前文件所在目录,也就是项目根目录
      "@": path.resolve(__dirname, "./src"), 
      "js": path.resolve(__dirname, "./src/js")
    }
  }
}

Configuration file environment distinction

Because some webpack configurations are only available in the development environment, the production environment is not suitable for these configurations, so different configuration files need to be used according to different environments.

There are two options:

  • Solution 1: Write two different configuration files, development and production environments, and load different configuration files respectively;
  • Solution 2: Split the configuration file into public modules, development modules and production modules. The development module and the production module merge the common modules separately, and then specify which configuration file to use in the npm script.
    • webpack.com.config.js
    • webpack.prod.config.js
    • webpack.dev.config.js

The entrance and exit, module analysis, and loader are all public parts. The devServer only serves the development environment, and some plug-ins need to look at their functions. For example, copy plug-ins are required in the production environment, but not in the development environment.

webpack-merge

Modular webpack configuration requires a plugin webpack-mergeto merge the base and environment configuration files.
Install:npm i webpack-merge -D

const {
    
     merge } = require('webpack-merge') // webpack-merge 导出的对象不止一个,要解构赋值
const commonConfig = require('./webpack.com.config.js') 

// merge() 合并两个配置文件,若有重复内容,后面文件的内容会覆盖前面文件的内容
module.exports = merge(commonConfig, {
    
    
  mode: 'development'
})
"build": "webpack --config webpack.prod.config.js",
"serve": "webpack serve --config webpack.dev.config.js"

Guess you like

Origin blog.csdn.net/qq_43220213/article/details/129608205