如何压缩Webpack打包文件?React项目bundle体积过大求助
我正在从零开始学习Webpack并构建React应用,遇到了如下错误:
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB). This can impact web performance. Assets: bundle.js (792 KiB)
我的Webpack配置如下:
const HtmlWebpackPlugin = require('html-webpack-plugin'); const ForkTsCheckerPlugin = require("fork-ts-checker-webpack-plugin"); const ForkTsCheckerNotifierPlugin = require("fork-ts-checker-notifier-webpack-plugin"); const path = require("path"); module.exports = { mode: "development", entry: { main: "./src/index.js", }, output: { filename: "bundle.js", path: path.resolve("dist"), publicPath: "/", clean: true, chunkFilename: "chunk.[id].js", }, module: { rules: [ // typescript { test: /\.(ts|tsx)$/, use: "ts-loader", exclude: /(node_modules|bower_components)/, }, // js / jsx { test: /\.(js|jsx)$/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], plugins: ["@babel/plugin-transform-runtime"] } }, exclude: /(node_modules|bower_components)/ }, // css { test: /\.css$/i, use: ["style-loader", "css-loader"], }, // images { test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i, type: "asset/resource", }, ] }, resolve: { extensions: [".js", ".jsx", ".ts", ".tsx"], symlinks: false }, devtool: 'inline-source-map', devServer: { static: { directory: path.resolve(__dirname, "public"), publicPath: "http://localhost:3000/", }, port: 3000, compress: true, historyApiFallback: true, hot: true, open: true, }, plugins: [ new ForkTsCheckerPlugin(), new HtmlWebpackPlugin({ inject: true, template: path.join(__dirname, "public", "index.html") }), new ForkTsCheckerNotifierPlugin({ title: "typescript", excludeWarnings: false }) ], performance: { hints: "warning" }, optimization: { runtimeChunk: false, removeAvailableModules: false, removeEmptyChunks: false, splitChunks: { minSize: 10000, maxSize: 250000, } } }
目前我的应用仅包含以下文件:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=, initial-scale=1.0"> <title>Portfolio</title> </head> <body> <div id="root"></div> <script src="../dist/bundle.js"></script> </body> </html>
app.js
import React from "react"; const App = () => <h1>Hello World</h1>; export default App;
index.js
import React from "react"; import { ReactDOM } from "react"; import App from "./App"; ReactDOM.render( <App />, document.querySelector("#root") );
我的package.json依赖:
"devDependencies": { "@babel/cli": "^7.1.0", "@babel/core": "^7.1.0", "@babel/plugin-transform-runtime": "^7.19.1", "@babel/preset-env": "^7.1.0", "@babel/preset-react": "^7.0.0", "@types/node": "^18.8.5", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", "babel-loader": "^8.2.5", "css-loader": "^6.7.1", "fork-ts-checker-notifier-webpack-plugin": "^6.0.0", "fork-ts-checker-webpack-plugin": "^7.2.13", "html-webpack-plugin": "^5.5.0", "style-loader": "^3.3.1", "ts-loader": "^9.4.1", "typescript": "^4.8.4", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" }, "dependencies": { "@emotion/react": "^11.10.4", "@emotion/styled": "^11.10.4", "@mui/material": "^5.10.9" } }
我实在不明白为什么应用打包体积这么大,求解决办法。
1. 开发模式本身的特性导致体积偏大
当前设置mode: "development",Webpack在该模式下不会做代码压缩、tree shaking等优化,还会保留完整的调试信息,这是体积超标的核心原因之一。如果只是开发阶段,这个警告可以直接忽略;若要验证优化效果,可临时切换为mode: "production"测试,但日常开发建议保持development模式以保证调试体验。
2. 第三方依赖包体积过大
你的依赖中包含了完整的@mui/material组件库,哪怕没用到任何组件,开发模式下Webpack也会把整个库打包进bundle。如果暂时不需要MUI,可以先移除该依赖;如果必须保留,可在开发阶段使用按需导入方式减少打包体积。
3. 优化splitChunks拆分第三方依赖
当前的splitChunks配置没有合理拆分node_modules中的依赖,导致React、ReactDOM、MUI等全部打包进bundle.js。修改optimization配置:
optimization: { runtimeChunk: 'single', splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }
该配置会把所有第三方依赖单独打包为vendors.js,拆分bundle体积。
4. 修复ReactDOM导入错误
index.js中import { ReactDOM } from "react";是错误写法,ReactDOM是独立包,应改为:
import ReactDOM from 'react-dom/client';
同时更新React 18的渲染代码:
const root = ReactDOM.createRoot(document.querySelector("#root")); root.render(<App />);
这个错误虽不直接影响体积,但会导致运行报错,需优先修正。
5. 移除无用的Loader和插件
当前项目只有js/jsx文件,没有ts/tsx文件,可暂时移除ts-loader相关配置和ForkTsChecker系列插件,减少打包过程中的冗余处理,也能小幅降低体积。
6. 调整devtool配置缩小体积
inline-source-map会将source map嵌入到bundle中,大幅增加体积。开发时可改用cheap-module-source-map,它生成的source map体积更小,同时能满足调试需求:
devtool: 'cheap-module-source-map',
7. 删除index.html中手动引入的脚本
HtmlWebpackPlugin会自动注入打包后的脚本,手动添加的<script src="../dist/bundle.js"></script>会导致重复加载,应删除该标签。
内容的提问来源于stack exchange,提问作者Tucan

