Summary of advanced use of WebPack5 (2)

Supporting video: Getting Started with Webpack 5 in Shang Silicon Valley and Principles

Supporting code: https://gitee.com/Augenstern-creator/kuang-study-web-pack5
Insert image description here

1. Process js resources

Webpack's processing of js is limited. It can only compile the ES modular syntax in js and cannot compile other syntax. As a result, js cannot run in browsers such as IE, so we hope to do some compatibility processing.

  • For js compatibility processing, we use Babel to complete
  • For code format, we use Eslint to complete

We first complete Eslint, and after checking that the code format is correct, Babel will handle the code compatibility.

1.1、Eslint

We use Eslint. The key is to write the Eslint configuration file and write various rules in it. When running Eslint in the future, the code will be checked based on the written rules.

There are many ways to write configuration files:

  • .eslintrc.*: Create a new file, located in the project root directory
    • .eslintrc
    • .eslintrc.js
    • .eslintrc.json
    • The difference is that the configuration format is different
  • package.jsonMedium eslintConfig: No need to create a file, write based on the original file

ESLint will find and automatically read them, so only one of the above configuration files needs to exist. Let's take .eslintrc.jsthe configuration file as an example and briefly look at some of the configurations:

module.exports = {
    
    
  // 解析选项
  parserOptions: {
    
    },
  // 具体检查规则
  rules: {
    
    },
  // 继承其他规则
  extends: [],
  // ...
  // 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};

parserOptionsparsing options

parserOptions: {
    
    
  ecmaVersion: 6, // ES 语法版本
  sourceType: "module", // ES 模块化
  ecmaFeatures: {
    
     // ES 其他特性
    jsx: true // 如果是 React 项目,就需要开启 jsx 语法
  }
}

rulesspecific rules

  • "off"or 0- turn off the rule
  • "warn"or 1- enable the rule to use warning level errors: warn(will not cause the program to exit)
  • "error"or 2- enable the rule to use error level errors: error(when triggered, the program will exit)
rules: {
    
    
  semi: "error", // 禁止使用分号
  'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
  'default-case': [
    'warn', // 要求 switch 语句中有 default 分支,否则警告
    {
    
     commentPattern: '^no default$' } // 允许在最后注释 no default, 就不会有警告了
  ],
  eqeqeq: [
    'warn', // 强制使用 === 和 !==,否则警告
    'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
  ],
}

extendsInheritance: It is too laborious to write rules bit by bit during development, so there is a better way to inherit existing rules. The following are the more famous rules:

// 例如在React项目中,我们可以这样写配置
module.exports = {
    
    
  extends: ["react-app"],
  rules: {
    
    
    // 我们的规则会覆盖掉react-app的规则
    // 所以想要修改规则直接改就是了
    eqeqeq: ["warn", "smart"],
  },
};

1.2. Using Eslint in webpack

Insert image description here

  1. Download packageeslint-webpack-plugin、eslint
npm i eslint-webpack-plugin eslint -D
  1. .eslintrc.jsCreate a file in the project root directory
module.exports = {
    
    
  // 继承 Eslint 规则
  extends: ["eslint:recommended"],
  env: {
    
    
    node: true, // 启用node中全局变量
    browser: true, // 启用浏览器中全局变量
  },
  parserOptions: {
    
    
    ecmaVersion: 6, // es6
    sourceType: "module", // es6 模块化
  },
  rules: {
    
    
    "no-var": 2, // 不能使用 var 定义变量
  },
};
  1. webpack.config.jsIntroducing plugins in
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  1. webpack.config.jsConfigure in
// 插件
plugins: [
    new ESLintWebpackPlugin({
    
    
        // 指定检查文件的根目录(这里检查 src 文件夹,因为src 是我们写代码的地方)
        context: path.resolve(__dirname, "src"),
    }),
],

VsCode Eslintplugin

  • Open VSCode and download the Eslint plug-in to check for coding errors while writing code.

  • But at this time, all files in the project will be checked by Eslint by default, and the packaged files in our dist directory will report errors. But we only need to check the files under src, not the files under dist.

  • So you can use Eslint to ignore the file. Create a new one in the project root directory·.eslintignore

    # 忽略dist目录下所有文件
    dist
    

1.3、Babel

JavaScript compiler: Mainly used to convert code written in ES6 syntax into backward-compatible JavaScript syntax so that it can run in current and older versions of browsers or other environments

Babel's configuration files can be written in many ways:

  • babel.config.*: Create a new file, located in the project root directory
    • babel.config.js
    • babel.config.json
  • .babelrc.*: Create a new file, located in the project root directory
    • .babelrc
    • .babelrc.js
    • .babelrc.json
  • package.jsonMedium babel: No need to create a new file, write based on the original file

Babel will find and automatically read them, so only one of the above configuration files needs to exist. Let's take the babel.config.jsconfiguration file as an example:

module.exports = {
    
    
  // 预设
  presets: [],
};

presetsDefault: It is a set of Babel plug-ins that extend Babel functions

  • @babel/preset-env: A smart preset that allows you to use the latest JavaScript.
  • @babel/preset-react: A preset for compiling React jsx syntax
  • @babel/preset-typescript: A preset for compiling TypeScript syntax

1.4. Use in webpack

  1. Download package
npm i babel-loader @babel/core @babel/preset-env -D
  1. Create in the project root directorybabel.config.js
module.exports = {
    
    
  // 智能预设:能编译ES6的语法
  presets: ["@babel/preset-env"],
};
  1. webpack.config.jsConfigure in
{
    
    
    test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
            use: {
    
    
                loader: "babel-loader",
            }
},

2. Process HTML resources

  1. Download package
npm i html-webpack-plugin -D
  1. webpack.config.jsintroduced in
const HtmlWebpackPlugin = require("html-webpack-plugin");
  1. webpack.config.jsConfigure in
plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "public/index.html"),
    }),
  ],
  1. run command
npx webpack

distThe file will be automatically generated under index.htmland the packaged js file will be automatically introduced.

Insert image description here

3. Development server & automation

Every time you write code, you need to manually enter instructions to compile the code. It is too troublesome. We hope to automate everything.

  1. Download package
npm i webpack-dev-server -D
  1. webpack.config.jsConfigure in
  // 开发服务器 devServer 和 mode 在同一级别
  devServer: {
    
    
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
  mode: "development",
  1. run command
npx webpack serve

Note that the running instructions have changed

And when you use the development server, all code will be compiled and packaged in memory and will not be output to the dist directory. When developing, we only care about whether the code can run and have effects. As for what the code is compiled into, we don't need to know.

4. Introduction to production mode

The production mode is that after the code is developed, we need to get the code and deploy it online in the future. In this mode, we mainly optimize the code to make it run better. Optimization mainly starts from two perspectives:

  1. Optimize code running performance
  2. Optimize code packaging speed

We need to prepare two configuration files to store different configurations and create them in the project root directory:

  • config/webpack.dev.js: development environment
  • config/webpack.prod.js:Production Environment

Modification webpack.dev.js, because the file directory has changed, all absolute paths need to go back one directory to find the corresponding files, and the relative paths do not need to change.

// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");



module.exports = {
    
    
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    
    
    // path: 文件输出目录,必须是绝对路径
    path: undefined, // 开发模式没有输出,不需要指定输出路径
    // filename: 输出文件名,入口文件打包输出到 `static/js/main.js`中,其他文件仍打包到上方 path 下
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    //clean: true, // 开发模式没有输出,不需要清空输出结果

  },
  // 加载器
  module: {
    
    
    // loader的配置
    rules: [
      {
    
    
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
    
    
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
    
    
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
    
    
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
    
    
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
    
    
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
    
    
        // 开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
    
    
          loader: "babel-loader",
        }
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录(这里检查 src 文件夹)
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // 开发服务器
  devServer: {
    
    
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
  // 模式
  mode: "development", // 开发模式
};

webpack.prod.jsThe production mode content is as follows:

// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");



module.exports = {
    
    
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    
    
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "../dist"),   // 生产模式需要输出
    // filename: 输出文件名,入口文件打包输出到 `static/js/main.js`中,其他文件仍打包到上方 path 下
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空

  },
  // 加载器
  module: {
    
    
    // loader的配置
    rules: [
      {
    
    
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
    
    
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
    
    
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
    
    
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
    
    
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
    
    
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
    
    
        // 开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
    
    
          loader: "babel-loader",
        }
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录(这里检查 src 文件夹)
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // 开发服务器
  //devServer: {
    
    
  //  host: "localhost", // 启动服务器域名
  //  port: "3000", // 启动服务器端口号
  //  open: true, // 是否自动打开浏览器
  //},
  // 模式
  mode: "production", // 生产模式
};

In this way, our instructions for running development mode and production mode are:

# 开发模式
npx webpack --config ./config/webpack.dev.js

# 生产模式
npx webpack --config ./config/webpack.prod.js

In order to facilitate running instructions in different modes, we define the instructions in scripts in package.json:

"scripts": {
    
    
    "start": "npm run dev",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build": "npx webpack --config ./config/webpack.prod.js",
    "test": "echo \"Error: no test specified\" && exit 1",
},

In this way, the startup command will become:

  • development mode
npm start  
# 或
npm run dev
  • production mode
npm run build

5. CSS processing

The Css file is currently packaged into a js file. When the js file is loaded, a style tag will be created to generate the style. This will cause a splash screen phenomenon for the website and the user experience is not good. We should use a separate Css file. Loading performance through link tags is better

  1. Download package
npm i mini-css-extract-plugin -D
  1. Introduced webpack.prod.js_
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  1. webpack.prod.jsConfigure in
    • "style-loader" To replace all withMiniCssExtractPlugin.loader
    • At the same time, you need to extract the css into a separate file.
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");


module.exports = {
    
    
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    
    
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "../dist"),   // 生产模式需要输出
    // filename: 输出文件名,入口文件打包输出到 `static/js/main.js`中,其他文件仍打包到上方 path 下
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空

  },
  // 加载器
  module: {
    
    
    // loader的配置
    rules: [
      {
    
    
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
    
    
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
      {
    
    
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
    
    
        test: /\.styl$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
      },
      {
    
    
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
    
    
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
    
    
        // 开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
    
    
          loader: "babel-loader",
        }
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录(这里检查 src 文件夹)
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
    
    
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // 开发服务器
  //devServer: {
    
    
  //  host: "localhost", // 启动服务器域名
  //  port: "3000", // 启动服务器端口号
  //  open: true, // 是否自动打开浏览器
  //},
  // 模式
  mode: "production", // 生产模式
};

  1. Run command
# 启动生产模式
npm run build

5.1. CSS compatibility processing

  1. Download package
npm i postcss-loader postcss postcss-preset-env -D
  1. webpack.prod.jsConfigure in
    • Configure after "css-loader"and before"less-loader"
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");


module.exports = {
    
    
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    
    
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "../dist"),   // 生产模式需要输出
    // filename: 输出文件名,入口文件打包输出到 `static/js/main.js`中,其他文件仍打包到上方 path 下
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空

  },
  // 加载器
  module: {
    
    
    // loader的配置
    rules: [
      {
    
    
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader",
          {
    
    
            loader: "postcss-loader",
            options: {
    
    
              postcssOptions: {
    
    
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },],
      },
      {
    
    
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", {
    
    
          loader: "postcss-loader",
          options: {
    
    
            postcssOptions: {
    
    
              plugins: [
                "postcss-preset-env", // 能解决大多数样式兼容性问题
              ],
            },
          },
        },"less-loader"],
      },
      {
    
    
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", {
    
    
          loader: "postcss-loader",
          options: {
    
    
            postcssOptions: {
    
    
              plugins: [
                "postcss-preset-env", // 能解决大多数样式兼容性问题
              ],
            },
          },
        },"sass-loader"],
      },
      {
    
    
        test: /\.styl$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", {
    
    
          loader: "postcss-loader",
          options: {
    
    
            postcssOptions: {
    
    
              plugins: [
                "postcss-preset-env", // 能解决大多数样式兼容性问题
              ],
            },
          },
        },"stylus-loader"],
      },
      {
    
    
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
    
    
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
    
    
        // 开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
    
    
          loader: "babel-loader",
        }
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录(这里检查 src 文件夹)
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
    
    
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // 开发服务器
  //devServer: {
    
    
  //  host: "localhost", // 启动服务器域名
  //  port: "3000", // 启动服务器端口号
  //  open: true, // 是否自动打开浏览器
  //},
  // 模式
  mode: "production", // 生产模式
};
  1. Control compatibility
    • We can package.jsonadd to the file browserslistto control the extent of style compatibility
{
    
    
  // 其他省略
  // last 2 version 无论什么浏览器,只兼容最近的两个版本
  // > 1%,覆盖99%的浏览器
  // not dead 不要已经死了的浏览器
  "browserslist": ["last 2 version", "> 1%", "not dead"]
}

5.2. Merge configuration

In order to improve code reusability, we use a method to handle our loader, webpack.prod.jsmodified in:

// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");


// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
    
    
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
    
    
      loader: "postcss-loader",
      options: {
    
    
        postcssOptions: {
    
    
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
    
    
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    
    
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "../dist"),   // 生产模式需要输出
    // filename: 输出文件名,入口文件打包输出到 `static/js/main.js`中,其他文件仍打包到上方 path 下
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空

  },
  // 加载器
  module: {
    
    
    // loader的配置
    rules: [
      {
    
    
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
    
    
        test: /\.less$/,
        use:getStyleLoaders("less-loader"),
      },
      {
    
    
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
    
    
        test: /\.styl$/,
        use:getStyleLoaders("stylus-loader"),
      },
      {
    
    
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
    
    
          dataUrlCondition: {
    
    
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
    
    
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
    
    
        // 开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
    
    
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
    
    
          loader: "babel-loader",
        }
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // 指定检查文件的根目录(这里检查 src 文件夹)
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
    
    
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // 开发服务器
  //devServer: {
    
    
  //  host: "localhost", // 启动服务器域名
  //  port: "3000", // 启动服务器端口号
  //  open: true, // 是否自动打开浏览器
  //},
  // 模式
  mode: "production", // 生产模式
};

5.3. CSS compression

  1. Download package
npm i css-minimizer-webpack-plugin -D
  1. webpack.prod.jsintroduced in
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
  1. webpack.prod.jsConfigure in
// 插件
plugins: [
    new ESLintWebpackPlugin({
    
    
        // 指定检查文件的根目录(这里检查 src 文件夹)
        context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
    
    
        // 以 public/index.html 为模板创建文件
        // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
        template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
    
    
        // 定义输出文件名和目录
        filename: "static/css/main.css",
    }),
    // css压缩
    new CssMinimizerPlugin(),
],
  1. run command
npm run build

Guess you like

Origin blog.csdn.net/Augenstern_QXL/article/details/133049807