Core Web Vitals是Google推出的网页性能指标,包括LCP、FID、CLS三个核心指标,已经成为衡量网页性能的新标准。我用了三年Core Web Vitals,从最开始的盲目追求指标,到后来的深入理解,踩了不少坑,也积累了很多经验。本文分享我用了三年Core Web Vitals才明白的道理,包括指标的真正含义、常见的优化误区、实战中的优化技巧、以及性能优化的本质,希望对做前端性能优化的同学有帮助。
一、初识Core Web Vitals
我第一次接触Core Web Vitals,是在2018年。那时候Google刚提出这个概念,还没有正式发布,只是在Chrome DevTools里有一些实验性的指标。
当时我对网页性能的理解,还停留在"页面加载时间"上,觉得页面加载越快,性能就越好。用的指标,主要是DOMContentLoaded、load事件的时间,以及自己在代码里打的时间戳。
后来,Google正式发布了Core Web Vitals,包括三个指标:
- LCP(Largest Contentful Paint):最大内容绘制,衡量页面主要内容的加载速度
- FID(First Input Delay):首次输入延迟,衡量页面的交互响应速度
- CLS(Cumulative Layout Shift):累积布局偏移,衡量页面的视觉稳定性
Google说,这三个指标,分别代表了网页性能的三个维度:加载、交互、视觉稳定。而且,这三个指标会影响Google搜索排名,性能好的网站,排名会更靠前。
那时候,我对这三个指标的理解很肤浅:
- LCP就是页面加载时间,越快越好
- FID就是点击响应时间,越快越好
- CLS就是页面不要跳动,越稳定越好
我觉得,这不就是把以前的性能指标换了个名字吗?没什么大不了的。
于是,我开始在项目里用Core Web Vitals,目标很简单:把三个指标都做到"良好"(LCP<2.5s,FID<100ms,CLS<0.1)。
但真正开始做的时候,才发现,事情没有我想的那么简单。
二、踩过的坑
在追求Core Web Vitals指标的过程中,我踩了很多坑。
坑1:盲目追求LCP,忽略了用户体验
最开始,我以为LCP就是页面加载时间,于是想尽一切办法让LCP变小。
我做了这些事情:
- 把所有图片都延迟加载,首屏只留一张很小的占位图
- 把首屏的内容都改成了纯文字,去掉了大图和复杂组件
- 把第三方脚本都延迟加载,甚至去掉了一些必要的功能
- 用了很多"黑科技",比如预渲染、SSR、边缘计算等
结果,LCP确实变小了,从3秒降到了1.5秒。但用户反馈,页面看起来"很空",首屏只有文字,没有图片,体验很差。而且,因为延迟加载了太多东西,页面滚动的时候,图片和内容才慢慢出来,反而感觉更慢了。
后来我才明白,LCP衡量的是"最大内容绘制",也就是页面上最大的那个内容元素(通常是图片或视频)的加载时间。LCP小,不代表用户体验好。如果为了LCP小,把首屏的主要内容都去掉了,那LCP虽然小了,但用户看到的是一个空页面,体验反而更差。
LCP的真正意义,是衡量用户"感知到的主要内容加载速度"。优化LCP,应该是让主要内容更快地加载出来,而不是把主要内容去掉。
坑2:FID优化了,但交互还是卡
FID(First Input Delay)衡量的是用户首次和页面交互时,浏览器响应的延迟时间。我最开始以为,FID小,页面交互就流畅。
于是,我优化了FID:
- 把首屏的JavaScript都拆分成小模块,按需加载
- 减少了主线程的长任务,把大的计算放到Web Worker里
- 优化了JavaScript的执行时间,减少了不必要的计算
FID确实变小了,从150ms降到了50ms。但用户反馈,页面交互还是卡,点击按钮之后,要等一会儿才有反应,滚动页面的时候也不流畅。
后来我才明白,FID只是"首次输入延迟",衡量的是用户第一次交互时,浏览器的响应延迟。它只衡量了交互的"第一次",而且只衡量了浏览器的响应延迟,没有衡量交互之后的处理时间和渲染时间。
也就是说,FID小,只代表浏览器能快速响应你的点击,但点击之后,事件处理函数要执行多久、页面要多久才能更新,FID是不衡量的。如果事件处理函数很复杂,执行时间很长,即使FID很小,用户还是会觉得卡。
而且,FID只衡量首次交互,后续的交互延迟,FID是不衡量的。如果首次交互很快,但后续交互都很慢,FID还是很好,但用户体验很差。
后来Google也意识到了这个问题,在2024年,用INP(Interaction to Next Paint)替代了FID,INP衡量的是所有交互的响应延迟,比FID更全面。
坑3:CLS优化了,但页面还是跳
CLS(Cumulative Layout Shift)衡量的是页面的累积布局偏移,也就是页面元素意外移动的程度。我最开始以为,CLS小,页面就不会跳。
于是,我优化了CLS:
- 给所有图片和视频都加了宽高属性
- 给广告位和动态内容预留了空间
- 避免了在页面加载完成后插入内容
CLS确实变小了,从0.3降到了0.05。但用户反馈,页面还是会跳,尤其是在网络慢的时候,页面元素会突然移位,很影响阅读。
后来我才明白,CLS衡量的是"累积布局偏移",它计算的是页面元素意外移动的程度和影响范围。CLS小,不代表页面完全不跳,只是跳动的程度比较小。
而且,CLS有一个特点:它只计算"意外的"布局偏移,如果是用户交互引起的布局偏移(比如点击展开菜单),是不算在CLS里的。但有些布局偏移,虽然是"意外的",但影响很小,CLS也不会算太多。
另外,CLS是"累积"的,也就是说,页面加载过程中所有的布局偏移,都会累加起来。如果页面加载时间很长,即使每次偏移都很小,累积起来也可能很大。
优化CLS,关键是要给所有动态内容预留空间,避免在页面加载过程中插入内容。但有些内容(比如广告、推荐内容),确实无法预知尺寸,这时候就要权衡,是预留空间(可能留白),还是接受一定的布局偏移。
坑4:指标好了,但搜索排名没提升
Google说,Core Web Vitals会影响搜索排名。于是我花了很大力气,把三个指标都做到了"良好",以为搜索排名会提升。
但结果,搜索排名并没有明显提升。网站的流量,也没有因为性能优化而明显增长。
后来我才明白,Core Web Vitals只是搜索排名的众多因素之一,而且不是最重要的因素。搜索排名最重要的因素,还是内容质量、网站权威性、用户体验等。性能只是其中的一个辅助因素,而且只有当性能差到一定程度的时候,才会明显影响排名。如果你的性能已经在"良好"以上了,再继续优化,对排名的提升就很有限了。
而且,Core Web Vitals的数据,是基于真实用户的测量数据(Chrome User Experience Report),不是你自己在实验室里测的数据。如果你自己测的指标很好,但真实用户的指标不好(比如用户的网络环境差、设备差),那搜索排名还是不会提升。
所以,优化Core Web Vitals,主要目的应该是提升用户体验,而不是为了搜索排名。把用户体验做好了,排名自然会慢慢提升。
坑5:为了指标,牺牲了代码可维护性
在优化Core Web Vitals的过程中,我用了很多"黑科技":
- 为了减少首屏JavaScript,把很多代码都改成了内联脚本
- 为了减少布局偏移,给很多元素加了固定的宽高,甚至用了!important
- 为了加快LCP,把首屏图片都转成了base64,内联在HTML里
- 为了减少主线程阻塞,把很多逻辑都放到了Web Worker里,增加了通信的复杂度
这些"黑科技",确实让指标变好了,但代码的可维护性大大降低了。后来要改需求的时候,发现代码很难懂,改起来很费劲,而且很容易引入bug。
有一次,我为了优化LCP,把首屏的一张大图转成了base64内联在HTML里。结果,HTML文件变大了很多,首屏的HTML加载时间变长了,反而影响了LCP。而且,base64的图片无法被浏览器缓存,每次加载页面都要重新下载,反而更慢了。
后来我才明白,性能优化不能牺牲代码的可维护性。用"黑科技"优化出来的性能,是不可持续的,而且可能会带来新的问题。性能优化应该用"正确的方式",在保持代码可维护性的前提下,提升性能。
三、三年后才明白的道理
用了三年Core Web Vitals,踩了很多坑,我才慢慢明白一些道理。
道理1:指标是手段,不是目的
这是最重要的一个道理。Core Web Vitals是衡量网页性能的手段,不是目的。优化性能的目的,是提升用户体验,而不是让指标数字变好看。
如果为了让指标变好看,而牺牲了用户体验(比如去掉首屏内容、延迟加载必要功能),那就是本末倒置了。指标好,但用户体验差,这样的优化没有任何意义。
反过来,如果用户体验很好,但指标不是最优的,那也没关系。比如,有些网站首屏有一个很大的英雄图(hero image),LCP可能会稍大一些,但用户觉得很好看、很有冲击力,体验很好。这时候,就不应该为了LCP小,而把英雄图去掉。
所以,优化性能的时候,要时刻想着:这个优化,是真的提升了用户体验,还是只是让指标变好看了?如果是后者,就不要做。
道理2:性能优化是系统工程,不是单点优化
最开始,我以为性能优化就是优化某一个点,比如优化图片、压缩JavaScript、减少HTTP请求。后来才明白,性能优化是一个系统工程,涉及到网络、服务器、前端、客户端等各个层面。
比如,LCP的优化,就涉及到:
- 网络层:DNS解析、TCP连接、TLS握手、HTTP请求响应
- 服务器层:响应时间、缓存策略、CDN配置
- 前端层:HTML结构、CSS加载、JavaScript执行、资源加载顺序
- 客户端层:浏览器渲染流程、设备性能、网络环境
只优化其中一个点,效果是有限的。要系统地优化,从网络到服务器到前端到客户端,全面地分析和优化。
而且,性能优化要根据实际情况来。不同的网站、不同的用户群体、不同的网络环境,优化的重点是不一样的。比如,面向发展中国家用户的网站,网络环境差,设备性能低,优化的重点应该是减少资源体积、降低设备要求;而面向发达国家用户的网站,网络环境好,设备性能高,优化的重点可能是交互体验和视觉稳定性。
所以,性能优化不能照搬别人的方案,要根据自己的实际情况,系统地分析,有针对性地优化。
道理3:真实用户数据比实验室数据重要
最开始,我优化性能,主要是在自己的电脑上,用Chrome DevTools和Lighthouse测数据。觉得自己测的数据好了,性能就好了。
后来才明白,实验室数据和真实用户数据,差距可能很大。
实验室数据,是在受控环境下测的,网络环境好,设备性能高,没有其他程序干扰。而真实用户的环境,千差万别:有的用户网络慢,有的用户设备差,有的用户同时开了很多标签页,有的用户在移动中网络不稳定。
而且,实验室数据通常只测一次,或者少数几次,而真实用户数据是大量用户的统计数据,更能反映整体的性能情况。
Google的Core Web Vitals,用的就是真实用户数据(Chrome User Experience Report,CrUX),而不是实验室数据。搜索排名,也是基于真实用户数据。
所以,优化性能,一定要关注真实用户数据。可以用Google Search Console、Chrome User Experience Report、或者自己埋点收集真实用户的性能数据。根据真实用户数据,找到性能瓶颈,有针对性地优化。
当然,实验室数据也有价值,它可以在开发过程中,快速地验证优化效果,帮助调试。但最终的性能判断,还是要看真实用户数据。
道理4:性能优化要持续进行,不是一劳永逸
最开始,我以为性能优化是一次性的工作,优化完了,指标好了,就完事了。后来才明白,性能优化是持续进行的,不是一劳永逸的。
因为:
- 网站在不断迭代,新功能、新代码、新依赖,都可能引入新的性能问题
- 用户的环境在变化,新的设备、新的浏览器、新的网络环境,都可能影响性能
- 性能指标在更新,Google会不断调整Core Web Vitals的定义和阈值
- 竞争对手在进步,你的性能不提升,相对来说就是在下降
所以,性能优化要融入日常开发流程中,而不是作为一个独立的项目。比如:
- 在CI/CD流程中加入性能检测,每次部署都检查性能指标,如果性能下降就告警
- 在代码审查中,关注性能影响,大的改动要评估性能影响
- 定期做性能审计,发现新的性能问题,及时优化
- 建立性能文化,让团队每个人都关注性能
只有持续地关注和优化性能,才能保持良好的用户体验。
道理5:不要过度优化,要权衡成本和收益
最开始,我有"性能强迫症",看到任何可以优化的地方,都想优化。比如,把一个10KB的JavaScript文件再压缩1KB,把一个100ms的请求再优化10ms。
后来才明白,性能优化要权衡成本和收益,不要过度优化。
有些优化,收益很小,但成本很高:
- 为了减少几KB的体积,把代码改得很难懂,可维护性大大降低
- 为了减少几ms的时间,引入了复杂的技术方案,增加了开发和维护成本
- 为了追求极致的指标,用了很多"黑科技",增加了系统的复杂度和风险
这些优化,从成本收益的角度看,是不值得的。有这些时间和精力,不如去做更有价值的事情,比如开发新功能、提升用户体验、修复bug。
性能优化有一个"边际收益递减"的规律:刚开始优化的时候,收益很大,成本很低;越往后优化,收益越小,成本越高。所以,要找到一个平衡点,在这个点上,性能足够好,优化的成本也合理。
一般来说,把Core Web Vitals做到"良好"(LCP<2.5s,FID<100ms,CLS<0.1),就已经足够了。再往上优化到"优秀"(LCP<1s,FID<50ms,CLS<0.05),收益就比较有限了,除非你的网站对性能有特别高的要求。
所以,不要过度优化,要权衡成本和收益,把精力放在最有价值的地方。
道理6:性能优化的本质,是尊重用户的时间
用了三年Core Web Vitals,我最大的感悟是:性能优化的本质,不是让指标数字变好看,不是为了搜索排名,而是尊重用户的时间。
每一个访问你网站的用户,都付出了时间。如果你的网站加载慢、交互卡、页面跳,用户就要花更多的时间等待,这是对用户时间的不尊重。
性能优化,就是让用户能更快地看到内容、更流畅地交互、更稳定地浏览,减少用户的等待时间,提升用户的体验。这是对用户时间的尊重,也是对用户的尊重。
想明白了这一点,性能优化就不再是一个冷冰冰的技术任务,而是一件有温度的事情。你优化的不只是代码和指标,更是用户的体验和感受。
所以,做性能优化的时候,要多站在用户的角度想:这个优化,能让用户更快地看到内容吗?能让用户更流畅地交互吗?能让用户更稳定地浏览吗?如果能,就做;如果不能,只是让指标变好看,就不要做。
尊重用户的时间,这才是性能优化的本质和初心。
四、实战中的优化技巧
说了这么多道理,下面分享一些实战中总结的优化技巧,这些技巧是经过验证的,确实能提升性能,而且不会牺牲用户体验和代码可维护性。
LCP优化技巧:
- 优化关键资源加载:首屏需要的CSS和JavaScript,要优先加载;非关键的资源,要延迟加载。可以用
<link rel="preload">预加载关键资源,用defer和async延迟加载非关键JavaScript。
- 优化图片:图片通常是LCP的最大元素。要优化图片:用现代格式(WebP、AVIF),压缩图片,用响应式图片(srcset),根据设备加载合适尺寸的图片。
- 优化服务器响应时间:服务器响应时间(TTFB)直接影响LCP。要优化服务器:用CDN,用缓存,优化后端逻辑,减少数据库查询。
- 优化渲染流程:避免阻塞渲染的CSS和JavaScript,减少重排重绘,用CSS containment优化渲染。
- 预连接关键域名:用
<link rel="preconnect">预连接关键的第三方域名,减少DNS解析和TCP连接的时间。
FID/INP优化技巧:
- 减少主线程阻塞:把大的JavaScript任务拆分成小任务,用
requestIdleCallback或setTimeout让出主线程,把计算密集的任务放到Web Worker里。
- 优化JavaScript执行:减少不必要的JavaScript执行,优化事件处理函数,避免在事件处理函数里做复杂计算。
- 减少第三方脚本影响:第三方脚本(广告、分析、社交插件等)经常会阻塞主线程。要延迟加载第三方脚本,或者用Web Worker加载,或者评估是否真的需要。
- 优化交互响应:点击之后,尽快给用户反馈(比如loading状态、动画),即使背后的处理还没完成,也要让用户知道"我收到你的操作了"。
CLS优化技巧:
- 给媒体元素设置尺寸:给图片、视频、iframe等元素,设置明确的宽高属性,或者用CSS aspect-ratio设置宽高比,避免加载后引起布局偏移。
- 给动态内容预留空间:广告、推荐内容、动态加载的组件,要预留空间,避免加载后插入引起布局偏移。如果无法预知尺寸,可以用占位符,或者在用户视口外加载。
- 避免在页面加载完成后插入内容:不要在页面加载完成后,在已有内容的上方插入新内容(比如公告条、推广横幅),这会引起布局偏移。如果必须插入,要预留空间,或者用动画平滑过渡。
- 用transform和opacity做动画:CSS动画用transform和opacity,不会引起布局偏移;不要用top、left、margin等会引起布局变化的属性做动画。
- 字体加载优化:字体加载可能会引起布局偏移(FOIT/FOUT)。要用
font-display: swap,或者预加载关键字体,减少字体加载引起的布局偏移。
通用优化技巧:
- 用HTTP/2或HTTP/3:HTTP/2支持多路复用,能同时加载多个资源,减少请求的开销。HTTP/3基于QUIC,性能更好。
- 用CDN:CDN能让用户从最近的节点加载资源,减少网络延迟。静态资源(图片、CSS、JavaScript、字体)都应该用CDN。
- 用缓存:合理设置缓存策略,让浏览器能缓存静态资源,减少重复加载。用文件哈希做缓存键,实现长期缓存。
- 减少资源体积:压缩文本资源(gzip/brotli),优化图片,移除不必要的代码(tree-shaking),减少第三方依赖。
- 监控和分析:用真实用户监控(RUM)工具,收集真实用户的性能数据,分析性能瓶颈,持续优化。
五、性能优化的正确姿势
最后,总结一下性能优化的正确姿势,这是我用了三年Core Web Vitals才总结出来的。
1. 先测量,再优化
不要盲目优化,先测量,找到性能瓶颈,再有针对性地优化。
测量的工具:
- 实验室测量:Chrome DevTools、Lighthouse、WebPageTest
- 真实用户测量:Google Search Console、Chrome User Experience Report、自己埋点
测量的维度:
- 加载性能:LCP、TTFB、资源加载时间
- 交互性能:FID/INP、主线程任务、事件处理时间
- 视觉稳定性:CLS、布局偏移的元素和原因
找到瓶颈之后,再优化,这样效率最高,效果最好。
2. 先优化大的,再优化小的
性能优化,要先优化影响大的,再优化影响小的。
比如,LCP优化,先优化最大的那个元素(通常是图片),再优化其他小的资源。如果最大的图片优化好了,LCP可能就达标了,其他的优化就可以缓一缓。
用二八法则:20%的优化,能带来80%的性能提升。先找到那20%的关键优化,做了之后,性能可能就达标了。剩下的80%的优化,收益只有20%,可以根据情况决定要不要做。
3. 先保证用户体验,再追求指标
性能优化,用户体验是第一位的,指标是第二位的。
任何优化,都要先问:这个优化,是真的提升了用户体验,还是只是让指标变好看了?如果是后者,就不要做。
比如,为了LCP小,把首屏大图去掉了,用户看到的是一个空页面,这就不是好的优化。正确的做法是,让大图更快地加载出来,而不是把它去掉。
4. 保持代码可维护性
性能优化,不能牺牲代码的可维护性。
不要用"黑科技",不要写难懂的代码,不要为了性能把代码搞得一团糟。用正确的、标准的方式优化,保持代码的清晰和可维护性。
如果一个优化,让代码变得很难懂、很难维护,即使性能提升了,也要慎重考虑。因为,代码是要长期维护的,可维护性差的代码,以后会带来更多的问题。
5. 持续监控,持续优化
性能优化不是一次性的,要持续监控,持续优化。
建立性能监控体系,收集真实用户的性能数据,设置告警,当性能下降时及时发现和处理。
把性能优化融入日常开发流程,在CI/CD中加入性能检测,在代码审查中关注性能影响,定期做性能审计。
只有持续地关注和优化,才能保持良好的性能。
六、写在最后
用了三年Core Web Vitals,从最开始的盲目追求指标,到后来的深入理解,我踩了很多坑,也学到了很多。
Core Web Vitals是一个很好的性能衡量标准,它让我们能更全面、更准确地衡量网页性能。但它只是工具,不是目的。性能优化的目的,是提升用户体验,是尊重用户的时间。
做性能优化,要保持清醒:不要为了指标而优化,要为了用户而优化;不要盲目追求极致,要权衡成本和收益;不要用"黑科技",要用正确的方式;不要一劳永逸,要持续优化。
性能优化是一条漫长的路,没有终点。但只要我们保持初心,以用户为中心,持续地学习和优化,就能让我们的网站越来越快,让用户的体验越来越好。
最后,用一句话结束本文:"性能优化的本质,不是让数字变好看,而是让用户的等待变少。尊重用户的时间,这才是性能优化的初心和归宿。"愿每一个做前端性能优化的同学,都能不忘初心,做出既快又好的网站。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录