最近负责的内部核心业务系统上线后收到了用户的频繁反馈“系统刚打开的时候太卡了白屏时间有点长。”经过专业工具测试发现首屏的LCP最大内容渲染时间竟然高达4.8秒。在一个追求效率的B端系统中这个延迟是无法接受的。为此我开启了为期一周的性能攻坚战。为了精准定位瓶颈我使用了 Chrome DevTools 的 Performance 面板以及 Webpack Bundle Analyzer 进行分析发现了以下三个核心问题Vendor包体积过大前端打包后的chunk-vendors.js达到了 3.5MB包含了未做按需引入的 UI 组件库和大型第三方依赖。首页接口并发阻塞首页初始化时同时请求了 8 个接口且部分历史接口响应时间超过 1.5s导致前端渲染被阻塞。图片资源未压缩首页Banner图和几个icon图标直接使用了原图单张图片大小突破 2MB核心优化方案与代码实现方案一路由懒加载与第三方库 CDN 化首先对前端路由进行懒加载改造确保首页只加载必要的代码。同时将Vue/React、Axios、Echarts等体积较大的公共库抽离改用公共 CDN 引入。【优化前全量引入】JavaScript// main.js import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import echarts from echarts; Vue.use(ElementUI);【优化后Webpack 配置抽离】JavaScript// vue.config.js module.exports { configureWebpack: { externals: { vue: Vue, element-ui: ELEMENT, echarts: echarts } } }在index.html中通过script标签引入对应的 CDN 链接直接让 Vendor 包体积暴降 60%。方案二后端接口黄金组合Redis 缓存 异步线程池针对首页耗时较长的“多维度数据统计”接口前端改为分批次请求后端引入Redis 缓存并将原本串行执行的 SQL 查询改为线程池异步并行处理。【优化后后端核心伪代码Java/Spring Boot】JavaGetMapping(/home/data) public Result getHomeData() { // 1. 先查缓存 Object cachedData redisTemplate.opsForValue().get(home:data:cache); if (cachedData ! null) { return Result.success(cachedData); } // 2. 缓存失效使用线程池异步并行查询 CompletableFutureListUserVO userFuture CompletableFuture.supplyAsync(() - userService.queryActiveUsers(), executor); CompletableFutureListOrderVO orderFuture CompletableFuture.supplyAsync(() - orderService.queryTodayOrders(), executor); // 等待所有任务完成 CompletableFuture.allOf(userFuture, orderFuture).join(); // 组装数据并回写缓存 HomeDataDTO result combineData(userFuture.get(), orderFuture.get()); redisTemplate.opsForValue().set(home:data:cache, result, 10, TimeUnit.MINUTES); return Result.success(result); }方案三开启 Gzip 压缩在 Nginx 服务器上开启 Gzip 压缩用 CPU 的计算时间换取传输带宽进一步压榨传输时间。Nginx# nginx.conf server { listen 80; server_name localhost; gzip on; gzip_min_length 1k; # 大于1K的才压缩 gzip_comp_level 5; # 压缩级别1-9 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript; gzip_vary on; }。4. 优化效果对比经过上述三板斧的优化系统的各项指标迎来了质的飞跃指标优化前优化后提升幅度Vendor包体积3.5 MB840 KB↓ 76%首页核心接口耗时1.6s120ms↓ 92%首屏白屏时间 (LCP)4.8s310ms秒开体验5. 总结与反思本次性能优化让我深刻体会到性能瓶颈往往不是单一原因造成的必须全链路排查前端打包 $\rightarrow$ 网络传输 $\rightarrow$ 后端接口 $\rightarrow$ 数据库查询。在日常开发中建立“性能防御意识”如组件按需加载、接口防抖节流、合理的索引设计远比事后优化更重要。各位大佬你们在项目里还用过哪些首屏优化的绝招欢迎在评论区一起交流探讨
从 4.8s 到 900ms,记一次线上系统首屏加载速度极致优化历程
发布时间:2026/6/10 7:09:17
最近负责的内部核心业务系统上线后收到了用户的频繁反馈“系统刚打开的时候太卡了白屏时间有点长。”经过专业工具测试发现首屏的LCP最大内容渲染时间竟然高达4.8秒。在一个追求效率的B端系统中这个延迟是无法接受的。为此我开启了为期一周的性能攻坚战。为了精准定位瓶颈我使用了 Chrome DevTools 的 Performance 面板以及 Webpack Bundle Analyzer 进行分析发现了以下三个核心问题Vendor包体积过大前端打包后的chunk-vendors.js达到了 3.5MB包含了未做按需引入的 UI 组件库和大型第三方依赖。首页接口并发阻塞首页初始化时同时请求了 8 个接口且部分历史接口响应时间超过 1.5s导致前端渲染被阻塞。图片资源未压缩首页Banner图和几个icon图标直接使用了原图单张图片大小突破 2MB核心优化方案与代码实现方案一路由懒加载与第三方库 CDN 化首先对前端路由进行懒加载改造确保首页只加载必要的代码。同时将Vue/React、Axios、Echarts等体积较大的公共库抽离改用公共 CDN 引入。【优化前全量引入】JavaScript// main.js import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import echarts from echarts; Vue.use(ElementUI);【优化后Webpack 配置抽离】JavaScript// vue.config.js module.exports { configureWebpack: { externals: { vue: Vue, element-ui: ELEMENT, echarts: echarts } } }在index.html中通过script标签引入对应的 CDN 链接直接让 Vendor 包体积暴降 60%。方案二后端接口黄金组合Redis 缓存 异步线程池针对首页耗时较长的“多维度数据统计”接口前端改为分批次请求后端引入Redis 缓存并将原本串行执行的 SQL 查询改为线程池异步并行处理。【优化后后端核心伪代码Java/Spring Boot】JavaGetMapping(/home/data) public Result getHomeData() { // 1. 先查缓存 Object cachedData redisTemplate.opsForValue().get(home:data:cache); if (cachedData ! null) { return Result.success(cachedData); } // 2. 缓存失效使用线程池异步并行查询 CompletableFutureListUserVO userFuture CompletableFuture.supplyAsync(() - userService.queryActiveUsers(), executor); CompletableFutureListOrderVO orderFuture CompletableFuture.supplyAsync(() - orderService.queryTodayOrders(), executor); // 等待所有任务完成 CompletableFuture.allOf(userFuture, orderFuture).join(); // 组装数据并回写缓存 HomeDataDTO result combineData(userFuture.get(), orderFuture.get()); redisTemplate.opsForValue().set(home:data:cache, result, 10, TimeUnit.MINUTES); return Result.success(result); }方案三开启 Gzip 压缩在 Nginx 服务器上开启 Gzip 压缩用 CPU 的计算时间换取传输带宽进一步压榨传输时间。Nginx# nginx.conf server { listen 80; server_name localhost; gzip on; gzip_min_length 1k; # 大于1K的才压缩 gzip_comp_level 5; # 压缩级别1-9 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript; gzip_vary on; }。4. 优化效果对比经过上述三板斧的优化系统的各项指标迎来了质的飞跃指标优化前优化后提升幅度Vendor包体积3.5 MB840 KB↓ 76%首页核心接口耗时1.6s120ms↓ 92%首屏白屏时间 (LCP)4.8s310ms秒开体验5. 总结与反思本次性能优化让我深刻体会到性能瓶颈往往不是单一原因造成的必须全链路排查前端打包 $\rightarrow$ 网络传输 $\rightarrow$ 后端接口 $\rightarrow$ 数据库查询。在日常开发中建立“性能防御意识”如组件按需加载、接口防抖节流、合理的索引设计远比事后优化更重要。各位大佬你们在项目里还用过哪些首屏优化的绝招欢迎在评论区一起交流探讨