如何最小化React应用打包体积?CRA项目生产Webpack配置优化方案
首先纠正认知误区:create-react-app 执行npm run build时默认已将process.env.NODE_ENV设置为production,你提到的DefinePlugin配置只是生产构建的基础前提,并非900kb主chunk体积过大的核心原因。
以下是无需eject的通用优化方案:
第一步:定位体积来源
先明确900kb的构成,避免无方向优化:
- 安装分析工具:
npm i source-map-explorer -D - 在
package.json的scripts中新增命令:"analyze": "source-map-explorer build/static/js/main.*.js" - 先执行
npm run build,再运行npm run analyze,查看具体是哪些依赖/代码占了体积。
第二步:配置非eject化的webpack修改环境
CRA默认隐藏webpack配置,使用@craco/craco可在不eject的前提下修改配置:
- 安装依赖:
npm i @craco/craco -D - 修改
package.json的scripts,将原有的react-scripts命令替换为craco:"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" } - 项目根目录新建
craco.config.js,后续所有配置都写入该文件。
第三步:核心生产优化配置
在craco.config.js中写入如下配置:
const webpack = require('webpack'); module.exports = { webpack: { // 显式定义生产环境变量(兜底避免意外) plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production'), }) ], configure: (webpackConfig) => { // 1. 开启激进压缩,剔除调试代码 webpackConfig.optimization.minimize = true; webpackConfig.optimization.minimizer.forEach(minimizer => { // 适配terser压缩(react-scripts v4及以下) if (minimizer.constructor.name === 'TerserPlugin') { minimizer.options.terserOptions.compress = { ...minimizer.options.terserOptions.compress, drop_console: true, drop_debugger: true, } } // 适配esbuild压缩(react-scripts v5及以上) if (minimizer.constructor.name === 'ESBuildPluginMinifier') { minimizer.options.compress = { ...minimizer.options.compress, drop: ['console', 'debugger'] } } }) // 2. 配置依赖别名,支持tree-shaking webpackConfig.resolve.alias = { ...webpackConfig.resolve.alias, 'lodash': 'lodash-es', 'moment': 'dayjs', } // 3. 拆分第三方依赖,避免主chunk过大 webpackConfig.optimization.splitChunks = { chunks: 'all', cacheGroups: { // 基础react生态单独拆包,利用浏览器缓存 reactBase: { test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/, name: 'react-base', priority: 20, }, // 其余第三方依赖统一拆包 vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: 10, } } } // 分离运行时代码,避免业务代码变更影响第三方chunk缓存 webpackConfig.optimization.runtimeChunk = 'single'; // 4. 开启严格tree-shaking,剔除未使用代码 webpackConfig.optimization.usedExports = true; webpackConfig.optimization.sideEffects = true; return webpackConfig; } } }
第四步:精简polyfill体积
CRA会根据package.json中browserslist配置自动引入对应polyfill,过宽的浏览器支持范围会导致polyfill体积暴涨,可修改为仅支持现代浏览器:
"browserslist": [ "last 2 chrome versions", "last 2 edge versions", "last 2 firefox versions", "last 2 safari versions" ]
补充说明
你之前使用React.lazy()未达到优化效果,大概率是因为所有第三方依赖都被打包在主chunk中,上述配置完成依赖拆分后,React.lazy()拆分的业务代码会直接生成独立chunk,不会占用主chunk体积。
内容的提问来源于stack exchange,提问作者fishLegs
相关产品推荐
相关产品推荐

