# 配置开发和生产模式的config

# 生产模式介绍

生产模式是开发完成代码后,我们需要得到代码将来部署上线。

这个模式下我们主要对代码进行优化,让其运行性能更好。

优化主要从两个角度出发:

  1. 优化代码运行性能
  2. 优化代码打包速度

# 生产模式准备

我们分别准备两个配置文件来放不同的配置

# 文件目录

├── webpack-test (项目根目录)
    ├── config (配置文件目录)
    ├── node_modules (下载包存放目录)
    ├── src (项目源码目录,除了html其他都在src里面)
    │    └── 略
    ├── public (项目html文件)
    │    └── index.html
    ├── .eslintrc.js(Eslint配置文件)
    ├── babel.config.js(Babel配置文件)
    └── package.json (包的依赖管理配置文件)
    ├── webpack.dev.js(开发模式配置文件!!!!)
    └── webpack.prod.js(生产模式配置文件!!!)
1
2
3
4
5
6
7
8
9
10
11
12

# 拓展 package.json 文件

{
  "name": "testdemo4",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "private": "true",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "npx webpack serve --config ./webpack.dev.js",
    "build:prod": "npx webpack --config ./webpack.prod.js",
    "build": "npx webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "@babel/core": "^7.24.9",
    "@babel/preset-env": "^7.24.8",
    "babel-loader": "^9.1.3",
    "css-loader": "^7.1.2",
    "css-minimizer-webpack-plugin": "^7.0.0",
    "eslint": "^9.7.0",
    "eslint-webpack-plugin": "^4.2.0",
    "html-webpack-plugin": "^5.6.0",
    "less-loader": "^12.2.0",
    "mini-css-extract-plugin": "^2.9.0",
    "postcss": "^8.4.39",
    "postcss-loader": "^8.1.1",
    "postcss-preset-env": "^9.6.0",
    "sass": "^1.77.8",
    "sass-loader": "^14.2.1",
    "style-loader": "^4.0.0",
    "webpack": "^5.93.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.0.4"
  },
  "browserslist": [
    "last 2 version",
    "> 1%",
    "not dead"
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 配置 webpack.dev.js

因为文件目录变了,所以所有绝对路径需要回退一层目录才能找到对应的文件

/**
 * 开发模式配置
 */

/** nodejs -- path文件路径模块 */
const path = require("path");

/** eslint代码检测 */
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
/** html文件处理  */
const HtmlWebpackPlugin = require("html-webpack-plugin");
/** css文件提取处理 */
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/** css文件压缩处理 */
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

//#region ===== tool 工具函数集
/**
 * @description 获取处理css样式的loaders工具配置函数, 配置了基础的loader,同时接收传参自定义loader
 * @param {Array} preProcessorList []
 * @returns
 */
const setStyleLoaders = (preProcessorList = []) => {
  return [
    // 单独提取css文件loader
    MiniCssExtractPlugin.loader,
    // 基础css-loader
    "css-loader",
    // css代码兼容处理loader配置
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    // 外部传入自定义 loader
    ...preProcessorList,
  ].filter(Boolean); // 筛选所有存在的loader
};
//#endregion

module.exports = {
  /** 入口文件 */
  entry: "./src/main.js",

  /** 输出文件配置 */
  output: {
    path: undefined, // 开发模式没有输出,不需要指定输出目录
    // 注意这里配置的是所有JS文件的输出路径,其他类型单独在 module-rules中配置
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    // clean: true, // 开发模式没有输出,不需要清空输出结果
  },

  /** 路径别名 */
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src/"),
    },
  },

  /** module  */
  module: {
    rules: [
      /** 处理 CSS 文件 */
      {
        test: /\.css$/,
        use: setStyleLoaders(), // 结果为: [MiniCssExtractPlugin.loader, "css-loader"],
      },

      /** 处理 less 文件 */
      {
        test: /\.less$/,
        use: setStyleLoaders(["less-loader"]), // 结果为: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
      },

      /** 处理 scss or sass 文件 */
      {
        test: /\.s[ac]ss$/,
        use: setStyleLoaders(["sass-loader"]), // 结果为: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
      },

      /** 处理 图片资源 */
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset", // 资源类型为 asset,Webpack 会根据文件类型选择合适的加载器进行处理, 比如 url-loader
        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?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },

      /** 媒体资源输出目录 */
      {
        test: /\.(mp4|mp3|avi)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },

      /** JS 文件的 babel 处理代码语法兼容性 */
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        // 也可以用包含 include: path.resolve(__dirname, "../src"),
        loader: "babel-loader",
        options: {
          cacheDirectory: true, // 开启babel编译缓存
          cacheCompression: false, // 缓存文件不要压缩
        },
      },
    ],
  },

  /** plugins */
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "./src"), // 注意路径
      exclude: "node_modules", // 默认值
      cache: true, // 开启缓存
      // 缓存目录
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js、css等资源
      template: path.resolve(__dirname, "./public/index.html"), // 注意路径
    }),
    /** css文件提取处理 */
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
    /** css压缩  */
    new CssMinimizerPlugin(),
  ],

  /** 配置开发服务器 */
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
    hot: true, // 热更新
  },

  /** 环境模式---开发模式 */
  mode: "development", // development or production
  devtool: "eval-source-map",
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

运行开发模式的指令:

npx webpack serve --config ./config/webpack.dev.js
1

# 配置 webpack.prod.js

/**
 * webpack.config.js 配置参考标准
 */

/** nodejs -- path文件路径模块 */
const path = require("path");

/** eslint代码检测 */
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
/** html文件处理  */
const HtmlWebpackPlugin = require("html-webpack-plugin");
/** css文件提取处理 */
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/** css文件压缩处理 */
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

//#region ===== tool 工具函数集
/**
 * @description 获取处理css样式的loaders工具配置函数, 配置了基础的loader,同时接收传参自定义loader
 * @param {Array} preProcessorList []
 * @returns
 */
const setStyleLoaders = (preProcessorList = []) => {
  return [
    // 单独提取css文件loader
    MiniCssExtractPlugin.loader,
    // 基础css-loader
    "css-loader",
    // css代码兼容处理loader配置
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    // 外部传入自定义 loader
    ...preProcessorList,
  ].filter(Boolean); // 筛选所有存在的loader
};
//#endregion

module.exports = {
  /** 入口文件 */
  entry: "./src/main.js",

  /** 输出文件配置 */
  output: {
    // 输出到本地根目录,所有输出文件的跟目录 ,dist文件夹下
    path: path.resolve(__dirname, "dist"),
    // 注意这里配置的是所有JS文件的输出路径,其他类型单独在 module-rules中配置
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    // 自动将上次打包目录资源清空
    clean: true,
  },

  /** 路径别名 */
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src/"),
    },
  },

  /** module  */
  module: {
    rules: [
      /** 处理 CSS 文件 */
      {
        test: /\.css$/,
        use: setStyleLoaders(), // 结果为: [MiniCssExtractPlugin.loader, "css-loader"],
      },

      /** 处理 less 文件 */
      {
        test: /\.less$/,
        use: setStyleLoaders(["less-loader"]), // 结果为: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
      },

      /** 处理 scss or sass 文件 */
      {
        test: /\.s[ac]ss$/,
        use: setStyleLoaders(["sass-loader"]), // 结果为: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
      },

      /** 处理 图片资源 */
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset", // 资源类型为 asset,Webpack 会根据文件类型选择合适的加载器进行处理, 比如 url-loader
        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?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },

      /** 媒体资源输出目录 */
      {
        test: /\.(mp4|mp3|avi)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },

      /** JS 文件的 babel 处理代码语法兼容性 */
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        // 也可以用包含 include: path.resolve(__dirname, "../src"),
        loader: "babel-loader",
      },
    ],
  },

  /** plugins */
  plugins: [
    /** eslint 检测 */
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
      exclude: "node_modules", // 默认值
    }),
    /** 模板 html 处理 */
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js、css等资源
      template: path.resolve(__dirname, "public/index.html"),
    }),
    /** css文件提取处理 */
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
    /** css压缩  */
    new CssMinimizerPlugin(),
  ],

  /** 配置开发服务器--生产环境不用配置 */

  /** 环境模式 */
  mode: "production", // development or production
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

运行生产模式的指令:

npx webpack --config ./config/webpack.prod.js
1

# 配置运行指令

为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面

// package.json
{
  // 其他省略
  "scripts": {
    "start": "npm run dev",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build:prod": "npx webpack --config ./config/webpack.prod.js",
  }
}
1
2
3
4
5
6
7
8
9

以后启动指令:

  • 开发模式:npm startnpm run dev
  • 生产模式:npm run build:prod