React SSR+Redux+Webpack项目优化后Gtmetrix评分未提升如何解决
React-Redux SSR项目Gtmetrix评分优化方案
Gtmetrix评分核心考察资源体积、缓存策略、核心Web指标(LCP、FID、CLS)、关键渲染路径等维度,针对你的配置可从以下方向优化:
一、Webpack生产配置优化
现有配置存在冗余规则、分包不彻底、无内容哈希缓存、压缩方案单一等问题,优化点如下:
- 合并重复的JS/JSX编译规则,删除冗余的
.js专属babel-loader配置 - 开启分包策略,拆分第三方依赖与公共代码,减小主包体积
- 输出文件名增加
contenthash,适配浏览器长缓存策略 - 新增CSS压缩、Brotli压缩(比gzip体积小20%左右),关闭生产环境sourceMap减少资源体积
- 修复SCSS规则重复配置
sass-loader的问题
优化后的核心配置片段:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const BrotliCompressionPlugin = require('brotli-webpack-plugin'); module.exports = { output: { path: path.join(__dirname, '/dist/'), filename: './[name].[contenthash:8].bundle.js', chunkFilename: './[name].[contenthash:8].chunk.js' }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'], plugins: [['@babel/plugin-transform-runtime', { regenerator: true }]] } } }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: false, modules: true, localIdentName: '[local]' } } ] }, { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: false, modules: true, localIdentName: '[name]__[local]___[hash:base64:5]' } }, 'sass-loader' ] }, // 其余loader规则保持不变 ] }, optimization: { minimize: true, minimizer: [ `...`, // 保留默认JS压缩能力 new CssMinimizerPlugin() ], splitChunks: { chunks: 'all', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: "vendors", priority: -10, chunks: "initial" }, common: { name: "common", minChunks: 2, priority: -20, reuseExistingChunk: true } } }, runtimeChunk: 'single' }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].[contenthash:8].css' }), new BrotliCompressionPlugin({ asset: "[path].br[query]", algorithm: "brotli", test: /\.(js|css|html|svg)$/, threshold: 10240, minRatio: 0.8 }), // 其余插件保持不变 ] }
二、Express服务端配置优化
现有配置存在缓存策略错误、未优先响应高压缩比资源的问题,优化点如下:
- 区分静态资源与SSR页面的缓存策略:JS/CSS/图片等带hash的静态资源设置1年长缓存,SSR返回的HTML页面设置
no-cache避免用户无法获取更新内容 - 优先响应Brotli压缩资源,提升传输效率
- 移除全局统一缓存头的错误配置
优化后的核心配置片段:
var express = require('express'); let cookieParser = require('cookie-parser'); var app = express(); const compression = require('compression'); const handleRender = require('./src/server/handleRender'); app.set('view engine', 'js'); app.engine('js', reactViews.createEngine()); require("@babel/polyfill"); var device = require('express-device'); require("@babel/register"); app.use(device.capture()); app.use(cookieParser()); // 优先响应Brotli压缩资源 app.use(compression({ level: 9, filter: (req, res) => { if (req.headers['accept-encoding']?.includes('br')) { res.set('Content-Encoding', 'br'); } return compression.filter(req, res); } })); // 静态资源单独设置长缓存 app.use(express.static(__dirname + '/public', { maxAge: '1y', etag: false })); app.use('/dist', express.static('dist', { maxAge: '1y', etag: false })); // HTML页面设置协商缓存,避免无法更新 app.use((req, res, next) => { if (req.accepts('html')) { res.set('Cache-Control', 'public, no-cache') } else { res.set('Cache-Control', 'public, max-age=31557600') } next() }) app.get('/',function(req, res,next) { handleRender(req, res, next); });
三、SSR渲染逻辑与性能指标优化
- 关键CSS内联:将首屏渲染所需的CSS直接内联到返回HTML的
head标签中,避免CSS文件加载阻塞渲染 - 优化Redux数据预取:仅预取首屏必须的接口数据,减少服务端接口请求耗时,降低TTFB(首字节时间)
- 核心Web指标优化:
- LCP优化:首屏最大元素(多为图片)优先加载,使用WebP格式图片,提前设置宽高属性
- CLS优化:所有图片、视频元素提前设置宽高,避免加载后撑开页面导致布局偏移
- FID优化:减少首屏执行的JS代码量,非必要逻辑延迟到页面加载完成后执行
- 非首屏组件懒加载:使用
React.lazy+Suspense实现非首屏组件按需加载,减少初始JS包体积 - 移除冗余依赖:如非必要可移除jQuery,使用原生JS替代对应功能,减少第三方依赖体积
内容的提问来源于stack exchange,提问作者Sushant Jadhav
相关产品推荐
相关产品推荐

