提升用户体验的关键 Core Web Vitals优化实战经验分享
项目初期的技术选型
这次的项目是个电商类网站,客户对性能要求特别高。说实话,一开始我也没太在意Core Web Vitals这些东西,觉得只要代码写得规范就行。但客户直接甩给我一份Lighthouse报告,说要达到Google的推荐标准,不然会影响SEO排名。
当时我心里还挺不服气的,觉得这些指标有点吹毛求疵。但仔细研究了一下,发现确实挺有道理的。特别是CLS(Cumulative Layout Shift)这个指标,我自己平时浏览网页时也经常遇到页面突然跳动的情况,体验确实很糟。
最大的坑:性能问题
真正开始优化的时候才发现,这玩意比想象中复杂多了。首先是LCP(Largest Contentful Paint),我们的首屏有个很大的banner图,加载速度慢得离谱。最开始用的是普通的标签,结果发现图片加载会阻塞渲染。
折腾了半天,最后改成了这样:
<picture>
<source srcset="banner.avif" type="image/avif">
<source srcset="banner.webp" type="image/webp">
<img src="banner.jpg" alt="促销banner" loading="lazy" width="1200" height="400">
</picture>
这里踩了几个坑要提醒大家:一定要记得设置width和height属性,否则浏览器无法提前计算布局,会导致CLS问题。另外loading=”lazy”对非首屏图片很有用,但首屏图片千万别用。
FID优化的意外收获
FID(First Input Delay)这个指标让我重新认识了JavaScript的执行机制。我们首页有个复杂的轮播组件,用了第三方库,结果发现首次交互延迟特别高。
后来我把初始化逻辑改成了这样:
setTimeout(() => {
import('./carousel.js').then(module => {
const initCarousel = module.default;
initCarousel();
});
}, 3000);
通过动态import和setTimeout,把非关键JS推迟执行,FID瞬间就降下来了。不过这里要注意,3秒的延迟时间是经过多次测试才确定的,太短的话会影响其他资源加载,太长又会影响用户体验。
CLS的持久战
CLS这个问题简直让人头大。排查了一圈发现罪魁祸首是字体文件加载。我们用的是自定义字体,导致页面在字体加载前后会出现明显的闪烁。
解决方案是在CSS里加了这个:
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}
但光这样还不够,因为有些广告位的高度是动态的,还是会引起页面跳动。最后只能给这些区域设置固定高度:
<div style="height:250px;">
<!-- 广告内容 -->
</div>
虽然这不是最完美的方案,但至少解决了大部分CLS问题。
监控与持续优化
为了让优化效果可量化,我接入了Google的Web Vitals库:
import {getCLS, getFID, getLCP} from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getLCP(console.log);
这里有个小技巧,建议把数据上报到自己的服务器:
function reportMetric(metric) {
navigator.sendBeacon('/analytics', JSON.stringify(metric));
}
getCLS(reportMetric);
getFID(reportMetric);
getLCP(reportMetric);
这样一来就能长期监控性能变化,及时发现问题。
回顾与反思
经过这一轮优化,Lighthouse分数从原来的60多分涨到了90分以上。但说实话,还是有一些问题没完全解决。比如某些第三方插件的加载时间依然不太可控,但这涉及到商业合作,暂时没办法完全优化。
总的来说,这次项目让我对性能优化有了更深的理解。以前总觉得这些指标是锦上添花,现在发现它们直接影响用户体验和业务指标。特别是移动端的性能优化,真的是个系统工程。
以上是我个人对Core Web Vitals优化的完整讲解,有更优的实现方式欢迎评论区交流。这个领域的最佳实践还在不断演进,后续我会继续分享这类博客。

暂无评论