部署于Heroku的Create-React-App性能优化问题咨询
问题核心原因排查
- 中间件加载顺序错误:你当前配置中
express.static静态资源处理逻辑位于compression、expressStaticGzip压缩相关中间件之前,请求静态资源时会优先匹配原生静态服务,直接返回未压缩的原始文件,后续压缩配置完全不生效 - 静态资源路径冲突:代码中同时定义了
path.join(__dirname, 'build')和path.join(__dirname, '..', 'build')两个不一致的build路径,若server.js存放于项目根目录,后者会读取上层目录的build文件夹,导致找不到预生成的.br、.gz压缩文件 - 重复的压缩逻辑冲突:同时使用了
compression中间件实时压缩和expressStaticGzip读取预生成压缩文件两种方案,二者逻辑冲突也会导致压缩失效
优化方案
第一步:修正server.js配置
调整中间件顺序,统一路径,删除冗余配置,参考修正后代码:
//server.js const express = require('express'); const compression = require('compression'); const favicon = require('express-favicon'); const path = require('path'); const expressStaticGzip = require('express-static-gzip'); const port = process.env.PORT || 8080; const app = express(); // 压缩中间件必须放在所有静态资源处理逻辑最前面 app.use(compression()); app.use(favicon(__dirname + '/build/favicon.ico')); // 统一build路径,确认server.js在项目根目录时build文件夹和server.js同级 const buildPath = path.join(__dirname, 'build'); // 优先处理预压缩的静态资源 app.use( '/', expressStaticGzip(buildPath, { enableBrotli: true, orderPreference: ['br', 'gz'], // 新增缓存配置,优化二次加载速度 setHeaders: (res, path) => { if (path.endsWith('.html')) { res.setHeader('Cache-Control', 'no-cache'); } else { res.setHeader('Cache-Control', 'public, max-age=31536000, immutable'); } } }) ); app.get('/ping', function (req, res) { return res.send('pong'); }); // 兜底路由放在最后 app.get('/*', (req, res) => { res.sendFile(path.join(buildPath, 'index.html'), err => { if (err) { res.status(500).send(err); } }); }); app.listen(port);
第二步:Heroku平台配置校验
- 确认项目根目录
.gitignore未排除build文件夹,保证构建产物能正常上传到Heroku - 在Heroku后台环境变量中配置
NODE_ENV=production、NPM_CONFIG_PRODUCTION=true,确保React构建时启用生产模式压缩 - 检查构建脚本配置:
package.json中的build命令需正常生成.br和.gz压缩文件,若使用compression-webpack-plugin生成预压缩文件,确认插件配置的输出路径和上述buildPath一致
第三步:额外性能优化
- 按需引入依赖:移除全量引入的Bootstrap样式,只保留当前项目用到的SCSS模块,web3js按功能按需引入,减少主包体积
- 静态资源压缩:所有图片转成WebP格式,压缩后再上线,字体文件按需裁剪只保留用到的字符
- 代码分割:路由级别的组件采用懒加载,拆分主包体积,减少首次加载需要下载的资源大小
内容的提问来源于stack exchange,提问作者KamiNoCube
相关产品推荐
相关产品推荐

