css

style-loader: 创建style标签将css注入页面
css-loader: 处理css资源,对@import 和 url()等进行处理,处理css-module

  1. {
  2. test: /\.css$/,
  3. loader: "style-loader!css-loader?modules" // ?后面跟配置参数,这里表示配置modules为true
  4. options: {}
  5. },

css-module

http://www.ruanyifeng.com/blog/2016/06/css_modules.html
会将类名编译成哈希字符串
:global(.title) { color: green; }: 不会编译成哈希字符串
组合:使用composes属性,让一个选择器继承另一个,

  1. .className {
  2. background-color: blue;
  3. }
  4. .title {
  5. composes: className;
  6. color: red;
  7. }

输入其它模块

  1. composes: className from './another.css';

支持变量,不过需要安装postcss-loader, @value blue: #0c77f8;

  1. {
  2. test: /\.css$/,
  3. loader: "style-loader!css-loader?modules!postcss-loader"
  4. },

处理图片

Webpack4:file-loader 和 url-loader
Webpack5:内置到 Webpack 配置即可

  1. {
  2. test: /\.(png|jpe?g|gif|webp)$/,
  3. type: "asset",
  4. parser: {
  5. dataUrlCondition: {
  6. maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
  7. //,减少请求数量,但体积变得更大
  8. }
  9. }
  10. },

自动清空上次打包资源

  1. output: {
  2. path: path.resolve(__dirname, "dist"),
  3. filename: "static/js/main.js",
  4. clean: true, // 自动将上次打包目录资源清空
  5. },

处理字体图标

  1. {
  2. test: /\.(ttf|woff2?)$/,
  3. type: "asset/resource",
  4. generator: {
  5. filename: "static/media/[hash:8][ext][query]",
  6. },
  7. },

type: “asset/resource”和type: “asset”的区别:

  1. type: “asset/resource” 相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理
  2. type: “asset” 相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式

eslint

  1. plugins: [
  2. new ESLintWebpackPlugin({
  3. // 指定检查文件的根目录
  4. context: path.resolve(__dirname, "src"),
  5. }),
  6. ],

Babel处理兼容性

  1. {
  2. test: /\.js$/,
  3. exclude: /node_modules/, // 排除node_modules代码不编译
  4. loader: "babel-loader",
  5. },

处理html

  1. new HtmlWebpackPlugin({
  2. // 以 public/index.html 为模板创建文件
  3. // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
  4. template: path.resolve(__dirname, "public/index.html"),
  5. }),

开发服务器

使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。

  1. // 开发服务器
  2. devServer: {
  3. host: "localhost", // 启动服务器域名
  4. port: "3000", // 启动服务器端口号
  5. open: true, // 是否自动打开浏览器
  6. },

提取css成单独文件

Css 文件打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式,闪屏
解决方案:利用插件提取成单独的css文件,通过link标签加载

  1. npm i mini-css-extract-plugin -D
  2. // 配置
  3. use: [MiniCssExtractPlugin.loader, "css-loader"],
  4. use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
  5. // 提取css成单独文件
  6. new MiniCssExtractPlugin({
  7. // 定义输出文件名和目录
  8. filename: "static/css/main.css",
  9. }),

处理css兼容性

  1. npm i postcss-loader postcss postcss-preset-env -D
  2. {
  3. // 用来匹配 .css 结尾的文件
  4. test: /\.css$/,
  5. // use 数组里面 Loader 执行顺序是从右到左
  6. use: [
  7. MiniCssExtractPlugin.loader,
  8. "css-loader",
  9. {
  10. loader: "postcss-loader",
  11. options: {
  12. postcssOptions: {
  13. plugins: [
  14. "postcss-preset-env", // 能解决大多数样式兼容性问题
  15. ],
  16. },
  17. },
  18. },
  19. ],
  20. },

控制兼容性,在package.json配置

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

合并配置

  1. // 获取处理样式的Loaders
  2. const getStyleLoaders = (preProcessor) => {
  3. return [
  4. MiniCssExtractPlugin.loader,
  5. "css-loader",
  6. {
  7. loader: "postcss-loader",
  8. options: {
  9. postcssOptions: {
  10. plugins: [
  11. "postcss-preset-env", // 能解决大多数样式兼容性问题
  12. ],
  13. },
  14. },
  15. },
  16. preProcessor,
  17. ].filter(Boolean);
  18. };
  19. {
  20. // 用来匹配 .css 结尾的文件
  21. test: /\.css$/,
  22. // use 数组里面 Loader 执行顺序是从右到左
  23. use: getStyleLoaders(),
  24. },

css压缩

  1. npm i css-minimizer-webpack-plugin -D
  2. // css压缩
  3. new CssMinimizerPlugin(),

html与js压缩

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

开启热更新

  1. module.exports = {
  2. // 其他省略
  3. devServer: {
  4. host: "localhost", // 启动服务器域名
  5. port: "3000", // 启动服务器端口号
  6. open: true, // 是否自动打开浏览器
  7. hot: true, // 开启HMR功能(只能用于开发环境,生产环境不需要了)
  8. },
  9. };

oneOf

打包时每个文件都会经过所有loader处理,虽然正则没匹配上的没有处理,但都要过一遍比较费时间

  1. rules: [
  2. {
  3. oneOf: [
  4. {
  5. // 用来匹配 .css 结尾的文件
  6. test: /\.css$/,
  7. // use 数组里面 Loader 执行顺序是从右到左
  8. use: ["style-loader", "css-loader"],
  9. },
  10. ]
  11. }
  12. ]

include/exclude

  1. {
  2. test: /\.js$/,
  3. // exclude: /node_modules/, // 排除node_modules代码不编译
  4. include: path.resolve(__dirname, "../src"), // 也可以用包含
  5. loader: "babel-loader",
  6. },

Cache

对 Eslint 检查 和 Babel 编译结果进行缓存。

  1. {
  2. test: /\.js$/,
  3. // exclude: /node_modules/, // 排除node_modules代码不编译
  4. include: path.resolve(__dirname, "../src"), // 也可以用包含
  5. loader: "babel-loader",
  6. options: {
  7. cacheDirectory: true, // 开启babel编译缓存
  8. cacheCompression: false, // 缓存文件不要压缩
  9. },
  10. },
  11. new ESLintWebpackPlugin({
  12. // 指定检查文件的根目录
  13. context: path.resolve(__dirname, "../src"),
  14. exclude: "node_modules", // 默认值
  15. cache: true, // 开启缓存
  16. // 缓存目录
  17. cacheLocation: path.resolve(
  18. __dirname,
  19. "../node_modules/.cache/.eslintcache"
  20. ),
  21. }),

多进程打包

主要是打包js文件
仅在特别耗时的操作中使用,因为每个进程启动就有大约为 600ms 左右开销。

  1. npm i thread-loader -D
  2. const os = require("os");
  3. const TerserPlugin = require("terser-webpack-plugin");
  4. // cpu核数
  5. const threads = os.cpus().length;
  6. // js
  7. {
  8. test: /\.js$/,
  9. // exclude: /node_modules/, // 排除node_modules代码不编译
  10. include: path.resolve(__dirname, "../src"), // 也可以用包含
  11. use: [
  12. {
  13. loader: "thread-loader", // 开启多进程
  14. options: {
  15. workers: threads, // 数量
  16. },
  17. },
  18. {
  19. loader: "babel-loader",
  20. options: {
  21. cacheDirectory: true, // 开启babel编译缓存
  22. },
  23. },
  24. ],
  25. },
  26. // eslint
  27. new ESLintWebpackPlugin({
  28. // 指定检查文件的根目录
  29. context: path.resolve(__dirname, "../src"),
  30. exclude: "node_modules", // 默认值
  31. cache: true, // 开启缓存
  32. // 缓存目录
  33. cacheLocation: path.resolve(
  34. __dirname,
  35. "../node_modules/.cache/.eslintcache"
  36. ),
  37. threads, // 开启多进程
  38. }),
  39. optimization: {
  40. minimize: true,
  41. minimizer: [
  42. // css压缩也可以写到optimization.minimizer里面,效果一样的
  43. new CssMinimizerPlugin(),
  44. // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
  45. new TerserPlugin({
  46. parallel: threads // 开启多进程
  47. })
  48. ],
  49. },

减少Babel转换后代码体积

Babel给每个模块都引入了辅助代码,将这些辅助代码作为一个独立模块,来避免重复引入。

  1. {
  2. loader: "babel-loader",
  3. options: {
  4. cacheDirectory: true, // 开启babel编译缓存
  5. cacheCompression: false, // 缓存文件不要压缩
  6. plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
  7. },
  8. },

压缩图片

  1. npm i image-minimizer-webpack-plugin imagemin -D
  2. // 无损模式
  3. npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
  4. // 有损压缩
  5. npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D

提取重复代码

  1. optimization: {
  2. // 代码分割配置
  3. splitChunks: {
  4. chunks: "all", // 对所有模块都进行分割
  5. // 以下是默认值
  6. // minSize: 20000, // 分割代码最小的大小
  7. // minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
  8. // minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
  9. // maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
  10. // maxInitialRequests: 30, // 入口js文件最大并行请求数量
  11. // enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
  12. // cacheGroups: { // 组,哪些模块要打包到一个组
  13. // defaultVendors: { // 组名
  14. // test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
  15. // priority: -10, // 权重(越大越高)
  16. // reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
  17. // },
  18. // default: { // 其他没有写的配置会使用上面的默认值
  19. // minChunks: 2, // 这里的minChunks权重更大
  20. // priority: -20,
  21. // reuseExistingChunk: true,
  22. // },
  23. // },
  24. // 修改配置
  25. cacheGroups: {
  26. // 组,哪些模块要打包到一个组
  27. // defaultVendors: { // 组名
  28. // test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
  29. // priority: -10, // 权重(越大越高)
  30. // reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
  31. // },
  32. default: {
  33. // 其他没有写的配置会使用上面的默认值
  34. minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
  35. minChunks: 2,
  36. priority: -20,
  37. reuseExistingChunk: true,
  38. },
  39. },
  40. },