前端性能优化实战:从LCP 4.5秒降到1.8秒的经历

yipeng
yipeng 正式会员正式会员认证极客认证极客
发布于 2026-08-02 10:55 ·132 浏览 ·0 回复
内容摘要

某核心业务后台因首屏资源过多、JS包过大、图片未懒加载及字体阻塞导致LCP约4.5秒,经Lighthouse和Performance定位后,采取拆包与路由级动态导入、删除未用库、图片懒加载和WebP转换、字体preload及font-display swap,并优化首屏JS执行和store序列化,最终将LCP降至1.8秒以内。

事情发生在上个月。公司的一个核心业务后台系统,用户反馈“打开特别慢”,尤其是首屏基本白屏时间很长。我拉了一下性能数据,LCP(Largest Contentful Paint,最大内容绘制)平均在 4.5 秒左右——这个数字在内部系统里还能忍,但放到面向客户的场景下,几乎等于劝退。

说实话,起初我以为是网络问题,或者服务器带宽不够。但看了 Network 面板后,发现事情没那么简单。这是个典型的“什么都往首屏塞”的项目:一个 HTML 响应 200 多 KB,JS 打包后主 chunk 超过 1.2MB,图片没做任何懒加载,字体文件更是直接阻塞渲染。

于是,我花了一周时间做了几件事,最终把 LCP 降到了 1.8 秒以内。整个过程算不上高深,但每一步都是实打实的收益,在这里分享一下。

不是玄学,是能查出来的

优化前,第一步永远是量化。我用 Lighthouse 跑了三轮,记录下关键指标:LCP 4.5s,FCP 2.8s,TTI 6.2s,CLS 0.12。诊断建议里,“减少未使用的 JavaScript”“预加载关键请求”“适当调整图片大小”这几项赫然在列。

但 Lighthouse 只能给方向,不能给细节。于是我打开 Performance 面板录制了一次加载过程,仔细看了主线程的时间线。结果很明显:HTML 解析很快,但脚本执行阶段被一个巨大的 JS 文件卡住了。一个组件库里所有的弹窗、表格、日期选择器全部被打进了主 bundle,连没用到的图表库也被 import 了。

进一步排查发现,首屏里有一个轮播图组件,图片不是懒加载的,浏览器在下载 JS 的同时还要去拉三张 2MB 的背景图。另外,字体文件是自托管的 woff2,但被 CSS 里的 @font-face 在渲染前就阻塞了。这些问题叠加在一起,LCP 自然就崩了。

从源头砍掉不需要的请求

第一步,先解决资源体积问题。我把主 bundle 用 webpack 的 splitChunks 做拆包,第三方库单独抽出来走 CDN。更重要的是,项目之前的很多模块都是同步 import,我改成了路由级别的动态 import(),让首屏只加载真正需要的部分。

这个过程不复杂,但需要仔细检查每个 import 路径。我删掉了两三个被“顺手”引入但从未使用的工具库,把一些大图从 PNG 转成了 WebP。主 bundle 从 1.2MB 缩到了 280KB,减少了近 80%。

接着是图片懒加载。给所有首屏以下的图片加了 loading="lazy",首屏的轮播图改成只加载第一张,后续的图片在滑动时再异步加载。同时给第一张图加了 fetchpriority="high",让浏览器优先安排下载。

字体这块,我调整了 CSS,把 font-display 从默认的 block 改成了 swap,并单独把字体文件加上了 preload。这样文字先以系统字体渲染,等自定义字体下载完再替换,避免了白屏等待。

代码执行和数据,是两个大头

资源体积降下来之后,LCP 有了明显改善,大概降到了 2.8 秒左右。但离 1.8 秒还有距离。我看了一下 Performance 面板,发现 JS 执行的时间占用还是太长,页面已经能画出来了,但主线程一直忙于执行脚本,导致图片等内容的绘制被卡住。

这次定位到了一个问题:某个全局混入的工具函数,在每次路由切换时都会执行一次深度遍历,把整个 store 里的数据全部序列化一遍。而首屏时 store 里的数据量有 1 万多条,这个遍历直接吃掉了 800ms。

解决方式很简单,给这个逻辑加了缓存和节流,同时把数据请求从页面挂载前改成了挂载后,用骨架屏占位。首屏的 TTI 从 6.2 秒降到了 3 秒左右,LCP 最终稳定在 1.8 秒以下。

细节的优化也不容忽视

顺便处理了几个小问题:

  • DNS 预解析:给所有跨域的 CDN 和 API 地址加了 <link rel="dns-prefetch">;
  • 预连接:对主要的资源来源加了 preconnect;
  • Gzip 改 Brotli:服务端开启了 Brotli 压缩,文本资源的体积又小了 20%;
  • 缓存策略:静态资源加上了 immutable 缓存,二次访问基本秒开。

这些改动单独拿出来每一项收益都很小,但综合起来,积少成多。

性能优化不是一次性的事

做完这一切之后,我把 Lighthouse 跑了一遍,性能评分从 47 分提到了 92 分。LCP 从 4.5 秒降到 1.8 秒,FCP 从 2.8 秒降到 1.2 秒。但说实话,更让人安心的是,这些改动不是临时的补丁,而是把构建配置和页面加载规则都固定了下来。

现在团队的新代码都要求走代码审查,主要看有没有新加大体积的依赖、图片是否设置了宽高和懒加载、路由是否需要动态引入。

性能优化这件事,没有一劳永逸。只要你不在乎,两三个月之后,LCP 又会不知不觉涨回去。但只要你建立了检查机制,它就能一直保持在一个健康的基线之上。这次的 4.5 到 1.8,不是终点,只是一个开始。

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-139.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~