Webpack 5-基础配置-生产模式介绍,Css 处理,Html 压缩,总结

2023年05月06日 10:14 · 阅读(261) ·

依赖环境

名称 版本
操作系统 Windows 10 X64
Node.js Nodejs 16+
Webpack 8.5.0
Webpack 5-基础 -

来源

名称 版本
视频地址 尚硅谷Webpack5入门到原理(面试开发一条龙)
视频+资料下载 百度云资料
课件下载 Webpack5-课件.zip
Webpack 文档 https://webpack.docschina.org/concepts/

生产模式介绍

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

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

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

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

生产模式准备

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

1. 文件目录

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

2. 修改 webpack.dev.js

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

  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. module.exports = {
  5. entry: "./src/main.js",
  6. output: {
  7. path: undefined, // 开发模式没有输出,不需要指定输出目录
  8. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  9. // clean: true, // 开发模式没有输出,不需要清空输出结果
  10. },
  11. module: {
  12. rules: [
  13. {
  14. // 用来匹配 .css 结尾的文件
  15. test: /\.css$/,
  16. // use 数组里面 Loader 执行顺序是从右到左
  17. use: ["style-loader", "css-loader"],
  18. },
  19. {
  20. test: /\.less$/,
  21. use: ["style-loader", "css-loader", "less-loader"],
  22. },
  23. {
  24. test: /\.s[ac]ss$/,
  25. use: ["style-loader", "css-loader", "sass-loader"],
  26. },
  27. {
  28. test: /\.styl$/,
  29. use: ["style-loader", "css-loader", "stylus-loader"],
  30. },
  31. {
  32. test: /\.(png|jpe?g|gif|webp)$/,
  33. type: "asset",
  34. parser: {
  35. dataUrlCondition: {
  36. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  37. },
  38. },
  39. generator: {
  40. // 将图片文件输出到 static/imgs 目录中
  41. // 将图片文件命名 [hash:8][ext][query]
  42. // [hash:8]: hash值取8位
  43. // [ext]: 使用之前的文件扩展名
  44. // [query]: 添加之前的query参数
  45. filename: "static/imgs/[hash:8][ext][query]",
  46. },
  47. },
  48. {
  49. test: /\.(ttf|woff2?)$/,
  50. type: "asset/resource",
  51. generator: {
  52. filename: "static/media/[hash:8][ext][query]",
  53. },
  54. },
  55. {
  56. test: /\.js$/,
  57. exclude: /node_modules/, // 排除node_modules代码不编译
  58. loader: "babel-loader",
  59. },
  60. ],
  61. },
  62. plugins: [
  63. new ESLintWebpackPlugin({
  64. // 指定检查文件的根目录
  65. context: path.resolve(__dirname, "../src"),
  66. }),
  67. new HtmlWebpackPlugin({
  68. // 以 public/index.html 为模板创建文件
  69. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  70. template: path.resolve(__dirname, "../public/index.html"),
  71. }),
  72. ],
  73. // 其他省略
  74. devServer: {
  75. host: "localhost", // 启动服务器域名
  76. port: "3000", // 启动服务器端口号
  77. open: true, // 是否自动打开浏览器
  78. },
  79. mode: "development",
  80. };

运行开发模式的指令:

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

3. 修改 webpack.prod.js

  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. module.exports = {
  5. entry: "./src/main.js",
  6. output: {
  7. path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
  8. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  9. clean: true,
  10. },
  11. module: {
  12. rules: [
  13. {
  14. // 用来匹配 .css 结尾的文件
  15. test: /\.css$/,
  16. // use 数组里面 Loader 执行顺序是从右到左
  17. use: ["style-loader", "css-loader"],
  18. },
  19. {
  20. test: /\.less$/,
  21. use: ["style-loader", "css-loader", "less-loader"],
  22. },
  23. {
  24. test: /\.s[ac]ss$/,
  25. use: ["style-loader", "css-loader", "sass-loader"],
  26. },
  27. {
  28. test: /\.styl$/,
  29. use: ["style-loader", "css-loader", "stylus-loader"],
  30. },
  31. {
  32. test: /\.(png|jpe?g|gif|webp)$/,
  33. type: "asset",
  34. parser: {
  35. dataUrlCondition: {
  36. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  37. },
  38. },
  39. generator: {
  40. // 将图片文件输出到 static/imgs 目录中
  41. // 将图片文件命名 [hash:8][ext][query]
  42. // [hash:8]: hash值取8位
  43. // [ext]: 使用之前的文件扩展名
  44. // [query]: 添加之前的query参数
  45. filename: "static/imgs/[hash:8][ext][query]",
  46. },
  47. },
  48. {
  49. test: /\.(ttf|woff2?)$/,
  50. type: "asset/resource",
  51. generator: {
  52. filename: "static/media/[hash:8][ext][query]",
  53. },
  54. },
  55. {
  56. test: /\.js$/,
  57. exclude: /node_modules/, // 排除node_modules代码不编译
  58. loader: "babel-loader",
  59. },
  60. ],
  61. },
  62. plugins: [
  63. new ESLintWebpackPlugin({
  64. // 指定检查文件的根目录
  65. context: path.resolve(__dirname, "../src"),
  66. }),
  67. new HtmlWebpackPlugin({
  68. // 以 public/index.html 为模板创建文件
  69. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  70. template: path.resolve(__dirname, "../public/index.html"),
  71. }),
  72. ],
  73. // devServer: {
  74. // host: "localhost", // 启动服务器域名
  75. // port: "3000", // 启动服务器端口号
  76. // open: true, // 是否自动打开浏览器
  77. // },
  78. mode: "production",
  79. };

运行生产模式的指令:

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

4. 配置运行指令

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

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

以后启动指令:

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

Css 处理

提取 Css 成单独文件

Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式

这样对于网站来说,会出现闪屏现象,用户体验不好

我们应该是单独的 Css 文件,通过 link 标签加载性能才好

1. 下载包

  1. npm i mini-css-extract-plugin -D

2. 配置

  • webpack.prod.js
  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  5. module.exports = {
  6. entry: "./src/main.js",
  7. output: {
  8. path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
  9. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  10. clean: true,
  11. },
  12. module: {
  13. rules: [
  14. {
  15. // 用来匹配 .css 结尾的文件
  16. test: /\.css$/,
  17. // use 数组里面 Loader 执行顺序是从右到左
  18. use: [MiniCssExtractPlugin.loader, "css-loader"],
  19. },
  20. {
  21. test: /\.less$/,
  22. use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
  23. },
  24. {
  25. test: /\.s[ac]ss$/,
  26. use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
  27. },
  28. {
  29. test: /\.styl$/,
  30. use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
  31. },
  32. {
  33. test: /\.(png|jpe?g|gif|webp)$/,
  34. type: "asset",
  35. parser: {
  36. dataUrlCondition: {
  37. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  38. },
  39. },
  40. generator: {
  41. // 将图片文件输出到 static/imgs 目录中
  42. // 将图片文件命名 [hash:8][ext][query]
  43. // [hash:8]: hash值取8位
  44. // [ext]: 使用之前的文件扩展名
  45. // [query]: 添加之前的query参数
  46. filename: "static/imgs/[hash:8][ext][query]",
  47. },
  48. },
  49. {
  50. test: /\.(ttf|woff2?)$/,
  51. type: "asset/resource",
  52. generator: {
  53. filename: "static/media/[hash:8][ext][query]",
  54. },
  55. },
  56. {
  57. test: /\.js$/,
  58. exclude: /node_modules/, // 排除node_modules代码不编译
  59. loader: "babel-loader",
  60. },
  61. ],
  62. },
  63. plugins: [
  64. new ESLintWebpackPlugin({
  65. // 指定检查文件的根目录
  66. context: path.resolve(__dirname, "../src"),
  67. }),
  68. new HtmlWebpackPlugin({
  69. // 以 public/index.html 为模板创建文件
  70. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  71. template: path.resolve(__dirname, "../public/index.html"),
  72. }),
  73. // 提取css成单独文件
  74. new MiniCssExtractPlugin({
  75. // 定义输出文件名和目录
  76. filename: "static/css/main.css",
  77. }),
  78. ],
  79. // devServer: {
  80. // host: "localhost", // 启动服务器域名
  81. // port: "3000", // 启动服务器端口号
  82. // open: true, // 是否自动打开浏览器
  83. // },
  84. mode: "production",
  85. };

3. 运行指令

  1. npm run build

Css 兼容性处理

1. 下载包

  1. npm i postcss-loader postcss postcss-preset-env -D

2. 配置

  • webpack.prod.js
  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  5. module.exports = {
  6. entry: "./src/main.js",
  7. output: {
  8. path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
  9. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  10. clean: true,
  11. },
  12. module: {
  13. rules: [
  14. {
  15. // 用来匹配 .css 结尾的文件
  16. test: /\.css$/,
  17. // use 数组里面 Loader 执行顺序是从右到左
  18. use: [
  19. MiniCssExtractPlugin.loader,
  20. "css-loader",
  21. {
  22. loader: "postcss-loader",
  23. options: {
  24. postcssOptions: {
  25. plugins: [
  26. "postcss-preset-env", // 能解决大多数样式兼容性问题
  27. ],
  28. },
  29. },
  30. },
  31. ],
  32. },
  33. {
  34. test: /\.less$/,
  35. use: [
  36. MiniCssExtractPlugin.loader,
  37. "css-loader",
  38. {
  39. loader: "postcss-loader",
  40. options: {
  41. postcssOptions: {
  42. plugins: [
  43. "postcss-preset-env", // 能解决大多数样式兼容性问题
  44. ],
  45. },
  46. },
  47. },
  48. "less-loader",
  49. ],
  50. },
  51. {
  52. test: /\.s[ac]ss$/,
  53. use: [
  54. MiniCssExtractPlugin.loader,
  55. "css-loader",
  56. {
  57. loader: "postcss-loader",
  58. options: {
  59. postcssOptions: {
  60. plugins: [
  61. "postcss-preset-env", // 能解决大多数样式兼容性问题
  62. ],
  63. },
  64. },
  65. },
  66. "sass-loader",
  67. ],
  68. },
  69. {
  70. test: /\.styl$/,
  71. use: [
  72. MiniCssExtractPlugin.loader,
  73. "css-loader",
  74. {
  75. loader: "postcss-loader",
  76. options: {
  77. postcssOptions: {
  78. plugins: [
  79. "postcss-preset-env", // 能解决大多数样式兼容性问题
  80. ],
  81. },
  82. },
  83. },
  84. "stylus-loader",
  85. ],
  86. },
  87. {
  88. test: /\.(png|jpe?g|gif|webp)$/,
  89. type: "asset",
  90. parser: {
  91. dataUrlCondition: {
  92. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  93. },
  94. },
  95. generator: {
  96. // 将图片文件输出到 static/imgs 目录中
  97. // 将图片文件命名 [hash:8][ext][query]
  98. // [hash:8]: hash值取8位
  99. // [ext]: 使用之前的文件扩展名
  100. // [query]: 添加之前的query参数
  101. filename: "static/imgs/[hash:8][ext][query]",
  102. },
  103. },
  104. {
  105. test: /\.(ttf|woff2?)$/,
  106. type: "asset/resource",
  107. generator: {
  108. filename: "static/media/[hash:8][ext][query]",
  109. },
  110. },
  111. {
  112. test: /\.js$/,
  113. exclude: /node_modules/, // 排除node_modules代码不编译
  114. loader: "babel-loader",
  115. },
  116. ],
  117. },
  118. plugins: [
  119. new ESLintWebpackPlugin({
  120. // 指定检查文件的根目录
  121. context: path.resolve(__dirname, "../src"),
  122. }),
  123. new HtmlWebpackPlugin({
  124. // 以 public/index.html 为模板创建文件
  125. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  126. template: path.resolve(__dirname, "../public/index.html"),
  127. }),
  128. // 提取css成单独文件
  129. new MiniCssExtractPlugin({
  130. // 定义输出文件名和目录
  131. filename: "static/css/main.css",
  132. }),
  133. ],
  134. // devServer: {
  135. // host: "localhost", // 启动服务器域名
  136. // port: "3000", // 启动服务器端口号
  137. // open: true, // 是否自动打开浏览器
  138. // },
  139. mode: "production",
  140. };

3. 控制兼容性

我们可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。

  1. {
  2. // 其他省略
  3. "browserslist": ["ie >= 8"]
  4. }

想要知道更多的 browserslist 配置,查看browserslist 文档

以上为了测试兼容性所以设置兼容浏览器 ie8 以上。

实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:

  1. {
  2. // 其他省略
  3. "browserslist": ["last 2 version", "> 1%", "not dead"]
  4. }

4. 合并配置

  • webpack.prod.js
  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  5. // 获取处理样式的Loaders
  6. const getStyleLoaders = (preProcessor) => {
  7. return [
  8. MiniCssExtractPlugin.loader,
  9. "css-loader",
  10. {
  11. loader: "postcss-loader",
  12. options: {
  13. postcssOptions: {
  14. plugins: [
  15. "postcss-preset-env", // 能解决大多数样式兼容性问题
  16. ],
  17. },
  18. },
  19. },
  20. preProcessor,
  21. ].filter(Boolean);
  22. };
  23. module.exports = {
  24. entry: "./src/main.js",
  25. output: {
  26. path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
  27. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  28. clean: true,
  29. },
  30. module: {
  31. rules: [
  32. {
  33. // 用来匹配 .css 结尾的文件
  34. test: /\.css$/,
  35. // use 数组里面 Loader 执行顺序是从右到左
  36. use: getStyleLoaders(),
  37. },
  38. {
  39. test: /\.less$/,
  40. use: getStyleLoaders("less-loader"),
  41. },
  42. {
  43. test: /\.s[ac]ss$/,
  44. use: getStyleLoaders("sass-loader"),
  45. },
  46. {
  47. test: /\.styl$/,
  48. use: getStyleLoaders("stylus-loader"),
  49. },
  50. {
  51. test: /\.(png|jpe?g|gif|webp)$/,
  52. type: "asset",
  53. parser: {
  54. dataUrlCondition: {
  55. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  56. },
  57. },
  58. generator: {
  59. // 将图片文件输出到 static/imgs 目录中
  60. // 将图片文件命名 [hash:8][ext][query]
  61. // [hash:8]: hash值取8位
  62. // [ext]: 使用之前的文件扩展名
  63. // [query]: 添加之前的query参数
  64. filename: "static/imgs/[hash:8][ext][query]",
  65. },
  66. },
  67. {
  68. test: /\.(ttf|woff2?)$/,
  69. type: "asset/resource",
  70. generator: {
  71. filename: "static/media/[hash:8][ext][query]",
  72. },
  73. },
  74. {
  75. test: /\.js$/,
  76. exclude: /node_modules/, // 排除node_modules代码不编译
  77. loader: "babel-loader",
  78. },
  79. ],
  80. },
  81. plugins: [
  82. new ESLintWebpackPlugin({
  83. // 指定检查文件的根目录
  84. context: path.resolve(__dirname, "../src"),
  85. }),
  86. new HtmlWebpackPlugin({
  87. // 以 public/index.html 为模板创建文件
  88. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  89. template: path.resolve(__dirname, "../public/index.html"),
  90. }),
  91. // 提取css成单独文件
  92. new MiniCssExtractPlugin({
  93. // 定义输出文件名和目录
  94. filename: "static/css/main.css",
  95. }),
  96. ],
  97. // devServer: {
  98. // host: "localhost", // 启动服务器域名
  99. // port: "3000", // 启动服务器端口号
  100. // open: true, // 是否自动打开浏览器
  101. // },
  102. mode: "production",
  103. };

5. 运行指令

  1. npm run build

Css 压缩

1. 下载包

  1. npm i css-minimizer-webpack-plugin -D

2. 配置

  • webpack.prod.js
  1. const path = require("path");
  2. const ESLintWebpackPlugin = require("eslint-webpack-plugin");
  3. const HtmlWebpackPlugin = require("html-webpack-plugin");
  4. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  5. const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
  6. // 获取处理样式的Loaders
  7. const getStyleLoaders = (preProcessor) => {
  8. return [
  9. MiniCssExtractPlugin.loader,
  10. "css-loader",
  11. {
  12. loader: "postcss-loader",
  13. options: {
  14. postcssOptions: {
  15. plugins: [
  16. "postcss-preset-env", // 能解决大多数样式兼容性问题
  17. ],
  18. },
  19. },
  20. },
  21. preProcessor,
  22. ].filter(Boolean);
  23. };
  24. module.exports = {
  25. entry: "./src/main.js",
  26. output: {
  27. path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
  28. filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  29. clean: true,
  30. },
  31. module: {
  32. rules: [
  33. {
  34. // 用来匹配 .css 结尾的文件
  35. test: /\.css$/,
  36. // use 数组里面 Loader 执行顺序是从右到左
  37. use: getStyleLoaders(),
  38. },
  39. {
  40. test: /\.less$/,
  41. use: getStyleLoaders("less-loader"),
  42. },
  43. {
  44. test: /\.s[ac]ss$/,
  45. use: getStyleLoaders("sass-loader"),
  46. },
  47. {
  48. test: /\.styl$/,
  49. use: getStyleLoaders("stylus-loader"),
  50. },
  51. {
  52. test: /\.(png|jpe?g|gif|webp)$/,
  53. type: "asset",
  54. parser: {
  55. dataUrlCondition: {
  56. maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
  57. },
  58. },
  59. generator: {
  60. // 将图片文件输出到 static/imgs 目录中
  61. // 将图片文件命名 [hash:8][ext][query]
  62. // [hash:8]: hash值取8位
  63. // [ext]: 使用之前的文件扩展名
  64. // [query]: 添加之前的query参数
  65. filename: "static/imgs/[hash:8][ext][query]",
  66. },
  67. },
  68. {
  69. test: /\.(ttf|woff2?)$/,
  70. type: "asset/resource",
  71. generator: {
  72. filename: "static/media/[hash:8][ext][query]",
  73. },
  74. },
  75. {
  76. test: /\.js$/,
  77. exclude: /node_modules/, // 排除node_modules代码不编译
  78. loader: "babel-loader",
  79. },
  80. ],
  81. },
  82. plugins: [
  83. new ESLintWebpackPlugin({
  84. // 指定检查文件的根目录
  85. context: path.resolve(__dirname, "../src"),
  86. }),
  87. new HtmlWebpackPlugin({
  88. // 以 public/index.html 为模板创建文件
  89. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  90. template: path.resolve(__dirname, "../public/index.html"),
  91. }),
  92. // 提取css成单独文件
  93. new MiniCssExtractPlugin({
  94. // 定义输出文件名和目录
  95. filename: "static/css/main.css",
  96. }),
  97. // css压缩
  98. new CssMinimizerPlugin(),
  99. ],
  100. // devServer: {
  101. // host: "localhost", // 启动服务器域名
  102. // port: "3000", // 启动服务器端口号
  103. // open: true, // 是否自动打开浏览器
  104. // },
  105. mode: "production",
  106. };

3. 运行指令

  1. npm run build

html 压缩

默认生产模式已经开启了:html 压缩和 js 压缩

不需要额外进行配置

总结

本章节我们学会了 Webpack 基本使用,掌握了以下功能:

1.两种开发模式

  • 开发模式:代码能编译自动化运行
  • 生产模式:代码编译优化输出

2.Webpack 基本功能

  • 开发模式:可以编译 ES Module 语法
  • 生产模式:可以编译 ES Module 语法,压缩 js 代码

3.Webpack 配置文件

  • 5 个核心概念
    • entry
    • output
    • loader
    • plugins
    • mode
  • devServer 配置

4.Webpack 脚本指令用法

  • webpack 直接打包输出
  • webpack serve 启动开发服务器,内存编译打包没有输出