这次我要当 webpack5 react 配置工程师

lxf2023-03-13 10:06:01

提示:本文主要是学习构建webpack5知识体系【近万字总结】 - AdminJS (Admin.net)文章实操的,坚定一个原则,能用esm 就不用commongjsesm 是未来,所以如果想看esm 配置webpack-react 的可以看这篇文章,并且坑基本上被踩完了,如果想看详细描述的commongjs 配置webpack-react 可以看构建webpack5知识体系【近万字总结】 - AdminJS (Admin.net)这篇文章。

项目地址:ohlyf/webpack-react: webpack搭建react开发环境template (github.com)

预备知识

webpack 配置主要分为七种:entry(入口)output(出口)loader(转换)plugin(插件)mode(模式)resolve(解析)optimization(优化)

含义

1. entry

入口是指依赖关系图的开始,从入口开始寻找依赖,打包构建,webpack 允许一个或多个入口配置,一般都是src 下的index.js 作为入口

export default {
  entry: './src/index.js'
}
export default {
  entry: {
    index: './src/index.js',
    other: './src/other.js'
  }
}

2. output

配置webpack 打包的出口,可配置打包后的位置打包后的文件名

export default {
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: '[name].bundle.js'
  }
}

3. loader

webpack 自带JavaScriptJSON 文件的打包构建能力,无需额外配置,其他文件则需要安装loaderplugin 进行处理

export default {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
}

4. plugin

给予某些文件格式一条龙服务

export default {
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ]
}

5. mode

webpack5提供了模式选择,包括开发模式生产模式空模式 ,并且对不同模式做了对应的内置优化,可以通过配置模式让项目性能更优

export default {
  mode: 'development'
}

6. resolve

resolve 用于设置模块如何解析,常用配置:

  • alias 配置别名,简化模块引入
  • extensions 在引入模块时可不带后缀
  • symlinks 用于配置nom link 是否生效,禁用可提升编译速度 —— 在pnpm 使用有问题
export default {
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.d.ts'],
    alias: {
      '@': './'
    },
    symlinks: false
  }
}

7. optimization

optimization 用于自定义webpack 的内置优化配置,一般用于生产模式 提升性能,常用配置:

  • minimize 是否需要压缩bundle
  • minimizer 配置要锁工具,如TerserPluginOptimizeCSSAssetsPlugin
  • splitChunks 拆分bundle
  • runtimeChunk 是否需要将所有生成chunk 之间共享的运行时文件拆分出来
export default {
  optimization: {
    minimizer: [
      new CSSMinimizerPlugin()
    ],
    splitChunks: {
      chunks: 'all',
      // 重复打包问题
      cacheGroups: {
        verdors: {
          // node_modulesl里的代码
          test: /[\\/]node_modules[\\/]/,
          chunks: 'all',
          name: 'vendors',
          priority: 10,
          enforce: true
        }
      }
    }
  }
}

实践基础篇

基础配置

1. 新建项目目录

这次我要当 webpack5 react 配置工程师

2. 改commonjsesm

进入package.json 删掉main:index.js 改为type:modulemodule:index.js

这次我要当 webpack5 react 配置工程师

3. 安装插件

npm i webpack-merge webpack webpack-cli -D

4. 添加基本配置结构

// webpack.common.js

export default{
  
}
// webpack.dev.js

import { merge } from "webpack-merge";
import common from './webpack.common.js';

export default merge(common, {
  
})
// webpack.prod.js

import { merge } from "webpack-merge";
import common from './webpack.common.js';

export default merge(common, {
  
})

5. 配置入口(entry)

入口只需要在公共配置common 中配置

// webpack.common.js

export default{
   entry: {
    index: './src/index.js'
	 }
}

6. 配置出口(output)

生产环境的output 需要通过contenthash 值来区分版本和变动,以达到缓存的效果,而本地为了构建效率,则不需要引入contenthash

占位符作用:

  • [name]- chunk name,如果chunk 没有名称,则会使用其id 作为名称
  • [contenthash] - 输出文件内容的md4-hash

先封装resolveApp 封装路径函数

// config/paths.js

import * as fs from "fs";
import * as path from "path";

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);

export { resolveApp };

配置dev出口+模式+source-map

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    filename: "[name].bundle.js",

    path: resolveApp("dist"),

    clean: true,
  },
  mode: "development",
  // 开发环境,开启 source map,编译调试
  devtool: "eval-cheap-module-source-map",
});

配置prod出口+模式

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    // bundle 文件名称 【只有这里和开发环境不一样】
    filename: "[name].[contenthash].bundle.js",

    // bundle 文件路径
    path: resolveApp("dist"),

    // 编译前清除目录
    clean: true,
  },
  mode: "production",
});

7. 配置html

安装插件

npm i html-webpack-plugin -D

新增public/index.html 添加div#root 为后续做准备,方便对html 进行修改

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

修改webpack.common.js

import HtmlWebpackPlugin from "html-webpack-plugin";

export default {
  entry: {
    index: "./src/index.js",
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
};

8. 配置devServer

  • webpack-dev-server 提供了一个基本的web server ,并且支持重新加载
  • webpack-dev-server 默认配置compress:true ,为每个静态文件开启gzip

安装

npm i webpack-dev-server -D

修改webpack.dev.js

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    filename: "[name].bundle.js",

    path: resolveApp("dist"),

    clean: true,
  },
  mode: "development",
  // 开发环境,开启 source map,编译调试
  devtool: "eval-cheap-module-source-map",
  
  devServer: {
    // 告诉服务器位置
    static: {
      directory: resolveApp("dist"),
    },
    port: 1012,
    hot: true,
  },
});

9. 配置打包命令试试

进入package.json 配置打包命令

"scripts": {
  	"dev": "webpack serve --config config/webpack.dev.js",
    "build": "webpack --config config/webpack.prod.js",
},

运行dev 配置了webpack serve 不会再打包,而是直接启服务器了

pnpm run dev

这次我要当 webpack5 react 配置工程师

运行build 可以看到dist 目录下打包结果

pnpm run build

这次我要当 webpack5 react 配置工程师

这次我要当 webpack5 react 配置工程师

10. 配置cross-env

通过cross-env 后续可以区分开发环境生产环境

安装

npm i cross-env -D

修改package.json

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack serve --config config/webpack.dev.js",
    "build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js",
},

进阶配置

1. 加载图片

由于原先的file-loader url-loader 等很热门,所以webpack5 将至内置了,只需要使用Assetmodules

// webpack.common.js

import HtmlWebpackPlugin from "html-webpack-plugin";
import { resolveApp } from "./paths.js";

export default {
  entry: {
    index: "./src/index.js",
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        include: [resolveApp("src")],
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
};

inde.js引入图片打包试试

// index.js

import "./assets/images/pic2.jpeg";
![image-20230112155337828](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/936804cbbf2f4ff0974725f132a5f220~tplv-k3u1fbpfcp-zoom-1.image) 

2. 加载less

安装loader

npm i css-loader style-loader less less-loader -D

修改webpack.common.js

import HtmlWebpackPlugin from "html-webpack-plugin";
import { resolveApp } from "./paths.js";

export default {
  entry: {
    index: "./src/index.js",
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        include: [resolveApp("src")],
        type: "asset/resource",
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
    ],
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
};

由于style-loader已经将css 插入js 了,所以打包查看不到css

3. 配置React+TypeScript

安装

pnpm i react react-dom @types/react @types/react-dom typescript esbuild-loader -D

添加tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "ESNext",
    "target": "ESNext",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

新建src/index.tsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

新建src/App.tsx

import React from "react";
import "./style.css";
import "./index.less";

function App() {
  return (
    <div>
      <h1>hello</h1>
      <h2>world</h2>
    </div>
  );
}

export default App;

修改webpack.common.js

import HtmlWebpackPlugin from "html-webpack-plugin";
import { resolveApp } from "./paths.js";

export default {
  entry: {
    index: "./src/index.tsx",
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        include: [resolveApp("src")],
        type: "asset/resource",
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.(js|ts|jsx|tsx)$/,
        include: resolveApp("src"),
        use: [
          {
            loader: "esbuild-loader",
            options: {
              loader: "tsx",
              target: "esNext",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ],
  resolve: {
    extensions: [".tsx", "ts", ".js"],
  },
};

运行试试

pnpm run dev

进入localhost:1012

这次我要当 webpack5 react 配置工程师

可以看到React 组件已经渲染出来

实践优化篇

效率工具

1. 编译进度条

安装

pnpm i progress-bar-webpack-plugin chalk -D

修改webpack.common.js

import HtmlWebpackPlugin from "html-webpack-plugin";
import ProgressBarPlugin from "progress-bar-webpack-plugin";
import chalk from "chalk";
import { resolveApp } from "./paths.js";

export default {
  entry: {
    index: "./src/index.tsx",
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        include: [resolveApp("src")],
        type: "asset/resource",
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.(js|ts|jsx|tsx)$/,
        include: resolveApp("src"),
        use: [
          {
            loader: "esbuild-loader",
            options: {
              loader: "tsx",
              target: "esNext",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
    // 进度条
    new ProgressBarPlugin({
      format: `  :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
    }),
  ],
  resolve: {
    extensions: [".tsx", "ts", ".js"],
  },
};

2. 编译速度分析

安装

pnpm i speed-measure-webpack-plugin -D

修改webpack.common.js

import SpeedMeasurePlugin from "speed-measure-webpack-plugin";
const smp = new SpeedMeasurePlugin();

export default smp.wrap({
  // ...webpack config...
})

优化开发

1. 热更新

安装

pnpm i @pmmmwh/react-refresh-webpack-plugin react-refresh -D

修改webpack.dev.js

import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin";
import webpack from "webpack";

export default{
   plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new ReactRefreshWebpackPlugin(),
  ],
}

2. cache

webpack5 可以通过配置持久化缓存 ,来改善构建速度

修改webpack.common.js

export default {
  cache: {
    type: "filesystem"
  }
}

3. 限定构建范围

使用include 限定资源范围

export default {
  module: {
    rules: [
       {
          test: /\.(png|svg|jpg|jpeg|gif)$/i,
          include: [resolveApp("src")],
          type: "asset/resource",
      	},
    ]
  }
}

4. 优化resolve 配置

  • 取别名alias
// webpack.common.js

export default {
  resolve: {
        alias: {
          '@': './src'
        },
    }
}
  • 省略后缀extensions
export default {
  resolve: {
    extensions: ['.tsx','.ts','.js']
  }
}
  • 制定需要解析的目录modules
export default {
  resolve: {
    modules: [
      'node_modules',
      resolveApp('src')
    ]
  }
}
  • 是否使用symlinks
export default {
  resolve: {
    symlinks: false
  }
}

5. 排除依赖Externals

例如项目中使用了lodash 让它排除

// webpack.common.js

export default {
  externals: {
    lodash: {
      commonjs: "lodash",
      commonjs2: "lodash",
      amd: "lodash",
      root: "_"
    }
  }
}

减少打包体积

1. JS代码压缩

安装

pnpm i terser-webpack-plugin -D

修改webpack.prod.js

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import TerserPlugin from "terser-webpack-plugin";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    // bundle 文件名称 【只有这里和开发环境不一样】
    filename: "[name].[contenthash].bundle.js",

    // bundle 文件路径
    path: resolveApp("dist"),

    // 编译前清除目录
    clean: true,
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: 4,
        terserOptions: {
          parse: {
            ecma: 8,
          },
          compress: {
            ecma: 5,
            warnings: false,
            comparisons: false,
            inline: 2,
          },
          mangle: {
            safari10: true,
          },
          output: {
            ecma: 5,
            comments: false,
            ascii_only: true,
          },
        },
      }),
    ],
  },
  mode: "production",
});

2. CSS压缩

安装

pnpm i css-minimizer-webpack-plugin -D

修改webpack.prod.js

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import TerserPlugin from "terser-webpack-plugin";
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    // bundle 文件名称 【只有这里和开发环境不一样】
    filename: "[name].[contenthash].bundle.js",

    // bundle 文件路径
    path: resolveApp("dist"),

    // 编译前清除目录
    clean: true,
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: 4,
        terserOptions: {
          parse: {
            ecma: 8,
          },
          compress: {
            ecma: 5,
            warnings: false,
            comparisons: false,
            inline: 2,
          },
          mangle: {
            safari10: true,
          },
          output: {
            ecma: 5,
            comments: false,
            ascii_only: true,
          },
        },
      }),
      new CssMinimizerPlugin({
        parallel: 4,
      }),
    ],
  },
  mode: "production",
});

代码分离

1. 抽离重复代码

修改webpack.prod.js splitChunks

import { merge } from "webpack-merge";
import common from "./webpack.common.js";
import TerserPlugin from "terser-webpack-plugin";
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
import { resolveApp } from "./paths.js";

export default merge(common, {
  output: {
    // bundle 文件名称 【只有这里和开发环境不一样】
    filename: "[name].[contenthash].bundle.js",

    // bundle 文件路径
    path: resolveApp("dist"),

    // 编译前清除目录
    clean: true,
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: 4,
        terserOptions: {
          parse: {
            ecma: 8,
          },
          compress: {
            ecma: 5,
            warnings: false,
            comparisons: false,
            inline: 2,
          },
          mangle: {
            safari10: true,
          },
          output: {
            ecma: 5,
            comments: false,
            ascii_only: true,
          },
        },
      }),
      new CssMinimizerPlugin({
        parallel: 4,
      }),
    ],
    splitChunks: {
      // include all types of chunks
      chunks: "all",
      // 重复打包问题
      cacheGroups: {
        // node_modules里的代码
        // 第三方模块
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: "all",
          priority: 10, // 优先级
          enforce: true,
        },
        // 公共模块
        common: {
          name: "common", // chunk名称
          priority: 0, // 优先级
          minSize: 0, // 公共模块的大小限制
          minChunks: 2, // 公共模块最少复用过几次
        },
      },
    },
  },
  mode: "production",
});

2. CSS 文件分离

安装

pnpm i mini-css-extract-plugin -D

**修改webpack.common.js ** 使用时间分析有问题,只有删掉时间分析,loader 选项中不能使用boolean&&P{} 只有boolean?{}:{}

import HtmlWebpackPlugin from "html-webpack-plugin";
import ProgressBarPlugin from "progress-bar-webpack-plugin";

import MiniCssExtractPlugin from "mini-css-extract-plugin";
import chalk from "chalk";

import { resolveApp } from "./paths.js";
const isEnvProduction = process.env.NODE_ENV === "production";

export default {
  entry: {
    index: "./src/index.tsx",
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        include: [resolveApp("src")],
        type: "asset/resource",
      },
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        use: [
          isEnvProduction
            ? ({
                loader: "style-loader",
                options: {
                  esModule: false,
                },
              },
              {
                loader: MiniCssExtractPlugin.loader,
              })
            : {
                loader: "style-loader",
              },
          "css-loader",
          "less-loader",
        ],
      },
      {
        test: /\.(js|ts|jsx|tsx)$/,
        include: resolveApp("src"),
        use: [
          {
            loader: "esbuild-loader",
            options: {
              loader: "tsx",
              target: "esNext",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // 生成html,自动引入所有bundle
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
    // 进度条
    new ProgressBarPlugin({
      format: `  :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
    }),
    // 分离css
    new MiniCssExtractPlugin(),
  ],
  resolve: {
    extensions: [".tsx", "ts", ".js"],
    alias: {
      "@": resolveApp("src"),
    },
    modules: [resolveApp("src"), "node_modules"],
  },
  cache: {
    type: "filesystem", // 使用文件缓存
  },
};

3. 最小化entry chunk

修改webpack.prod.js 通过下面的配置,为运行时代码创建一个额外的chunk ,减少entry chunk 体积,提高性能

export default {
  optimization: {
        runtimeChunk: true,
      },
   };
}

### 加快加载速度

1. 按需加载

使用import() 语法懒加载

export default function App(){
  return (
  	<div>
    	<button onClick={()=>import('lodash')}>按需加载</button>
		</div>
  )
}

2. 浏览器缓存

webpack 支持根据资源内容,创建hash id ,当资源内容发生变化时,将创建新的hash id

配置JS bundle hash

// webpack.common.js

export default {
  output: {
    filename: isEnvProduction ? '[name].[contenthash].bundle.js':'[name].bundle.js'
  }
}

配置CSS bundle hash

// webpack.common.js

export default {
  plugins: [
    new MiniCssExtractPlugin({
       filename: isEnvProduction ? "[name].[hash:8].css" : "[name].css",
    })
  ]
}

配置optimization.moduleIds 让公共包splitChunkshash 不因新的依赖而改变,减少非必要的hash 变动

// webpack.prod.js

export default {
   optimization: {
    moduleIds: 'deterministic',
  }
}

总结:

  • 在小型项目中,添加过多的优化配置,作用不大,反而会因为额外的loaderplugin 增加构建时间
  • 在加快构建时间方面,作用最大的是配置cache ,可大大加快二次构建速度
  • 在减小打包体积方面,作用最大的是压缩代码分离重复代码Tree Shaking 可最大幅度减小打包体积
  • 在加快加载速度方面,按需加载浏览器缓存CDN 效果都很显著

## 自定义篇

自定义loader

自定义一个解析mdloader

参考地址:构建webpack5知识体系【近万字总结】 - AdminJS (Admin.net)

准备工作

这次我要当 webpack5 react 配置工程师

配置webpack.common.js

     {
        test: /\.md$/,
        use: [
          {
            loader: resolveApp("loaders") + "/html-color-loader.cjs",
            options: {
              text: "world",
            },
          },
          {
            loader: resolveApp("loaders") + "/md-loader.cjs",
            options: {
              headerIds: false,
            },
          },
        ],
      },

添加md-loader.cjs 用于转换成html

const marked = require("marked");

function markdownLoader(source) {
  // 获取配置的options
  const options = this.getOptions();
  const html = marked.parse(source, options);
  return JSON.stringify(html);
}
module.exports = markdownLoader;

**添加html-color-loader.cjs ** 用于自定义某些操作

function htmlColorLoader(source) {
  // 获取配置的options
  const options = this.getOptions();
  const newStr = source.replace("hello", `<span>hello ${options.text}</span>`);
  const code = `module.exports = ${newStr}`;
  return code;
}

module.exports = htmlColorLoader;

使用

// src/index.tsx

import html from "../index.md";
document.getElementById("root").innerHTML = html;

这次我要当 webpack5 react 配置工程师

自定义plugin

webpack 插件组成

  • 一个具名JavaScript 函数
  • 在它的原型上定义apply 方法
  • 指定一个触及到webpack 本身的事件钩子
  • 操作webpack 内部的实例特定数据
  • 在实现功能后调用webpack 提供的callback

插件由一个构造函数实例化出来,构造函数定义apply 方法,在安装插件时,apply 方法会被webpack compiler 调用一次,apply 方法可以接收一个webpack compiler 对象的引用,从而可以在回调函数中访问到compiler 对象

实现一个输出文件夹大小的plugin

修改webpack.common.js

import BundleSizePlugin from "../plugin/BundleSizePlugin.cjs";

 plugins: [
    // 输出文件夹大小
    new BundleSizePlugin({
      limit: 3,
    }),
  ],

新增plugin/BundleSizePlugin.cjs

const { statSync } = require("fs");
const { resolve } = require("path");

class BundleSizePlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    const { limit } = this.options;
    compiler.hooks.done.tap(`BundleSizePlugin`, (stats) => {
      const { path } = stats.compilation.outputOptions;
      const bundlePath = resolve(path);
      const { size } = statSync(bundlePath);
      const bundleSize = size;
      if (bundleSize < limit) {
        console.log(
          "输出success-----bundleSize:",
          bundleSize,
          "\n limit:",
          limit,
          "小于限制大小"
        );
      } else {
        console.log(
          "输出error-----bundleSize:",
          bundleSize,
          "\n limit:",
          limit,
          "超出限制大小"
        );
      }
    });
  }
}

module.exports = BundleSizePlugin;

效果

这次我要当 webpack5 react 配置工程师

参考资料

  • 构建webpack5知识体系【近万字总结】 - AdminJS (Admin.net)

  • 2022年我的面试万字总结(Node、webpack、性能优化) - AdminJS (Admin.net)