你的网页慢,用户不说直接走——前端性能监控教你“读心术”
你上线了一个页面,自认为飞快。但用户那边转圈转了三秒,走了。你浑然不知。今天我们来装一套“网页心电图仪”——前端性能监控。它能告诉你:用户打开你的网站,到底有多卡?哪里卡?卡的人多不多?不用等用户骂你,你就知道该优化哪了。
前言
性能优化不是“我觉得快”,而是“数据证明快”。没有监控的优化,就像闭着眼睛射箭——中了是运气,脱靶是常态。
Google 定义了三个核心指标(Core Web Vitals):LCP(加载速度)、FID(交互响应)、CLS(视觉稳定)。加上我们自己业务关心的指标(比如首屏时间、API耗时),组合起来就是你的“网页健康报告”。
今天我们就来搭一套轻量级前端性能监控,从采集到上报,再到报警,一条龙。
一、三大核心指标:你的网页“体检三项”
LCP(最大内容绘制):加载速度的“裁判”
LCP 测量页面主要内容(比如大图、标题、视频)加载完成的时间。理想值:2.5秒以内。
什么算“主要内容”?就是用户第一眼看到的那个最大的元素。可能是背景图,可能是大标题,也可能是视频封面。
FID(首次输入延迟):交互响应的“秒表”
用户第一次点击、触摸或按键,到浏览器真正开始处理的时间。理想值:100毫秒以内。
如果你的JS主线程被长任务阻塞,用户点了按钮没反应,FID就会高。用户会觉得“这网站卡死了”。
CLS(累计布局偏移):视觉稳定的“防抖测试”
页面加载过程中,元素突然位移(比如图片加载出来把按钮挤下去了)。理想值:0.1以内。
CLS 高,用户容易点错按钮,比如本来要点“购买”,结果图片加载完,按钮被挤开,点到了“不感兴趣”。
二、怎么采集这些指标?用 web-vitals 库
Google 官方提供了 web-vitals 库,几行代码就能拿到 LCP、FID、CLS。
npm install web-vitals
import { getLCP, getFID, getCLS } from 'web-vitals';
function sendToAnalytics({ name, value, id }) {
// 上报到你的后端或第三方服务
navigator.sendBeacon('/api/perf', JSON.stringify({ name, value, id }));
}
getLCP(sendToAnalytics);
getFID(sendToAnalytics);
getCLS(sendToAnalytics);
注意:这些指标需要在页面加载完成后才能拿到,而且可能会多次更新(比如CLS会在整个页面生命周期中变化)。你可以选择只上报最终值,或者每次变化都上报(去重)。
三、其他重要指标:你自己更关心什么?
- TTFB(首字节时间):从请求到服务器返回第一个字节。影响LCP,但更偏后端。
- DOM Ready / Load 时间:传统指标,用于对比。
-
首屏时间(自定义):比如你的页面有一个“主要内容区”,可以通过
MutationObserver监听该区域出现的时间。
// 手动打点
const start = performance.now();
// 某个关键组件渲染完成后
const end = performance.now();
report('custom:firstContent', end - start);
- API 响应时间:在 axios 拦截器里记录每个接口耗时。
四、上报策略:别把服务器打满
性能指标上报不能像打点日志那么频繁。策略:
- 只上报一部分用户(采样),比如 10%。用随机数或用用户ID哈希。
-
批量上报:收集多个指标,页面关闭前一次性发走(用
sendBeacon)。 -
避免阻塞:用
requestIdleCallback或setTimeout低优先级上报。
if (Math.random() > 0.9) { // 10%采样
navigator.sendBeacon('/api/perf', JSON.stringify(data));
}
五、报警与可视化:指标变差,立刻知道
光采集不上报等于没采。你需要一个后端接收数据,然后做可视化+报警。
- 自建:用 Node + ClickHouse(或 InfluxDB)存储,Grafana 展示,设置阈值报警(比如 LCP P95 > 3s 发钉钉)。
- 第三方:Sentry(也能做性能监控)、DataDog、Google Analytics(有 Core Web Vitals 报告)、阿里云ARMS。
最简单的起步:把数据发到 Google Analytics(GA4),它有现成的 Web Vitals 报告。
import { getCLS, getFID, getLCP } from 'web-vitals';
import ga4 from 'react-ga4';
function sendToGA({ name, value, id }) {
ga4.event('web_vitals', {
event_category: 'Web Vitals',
event_label: id,
value: Math.round(name === 'CLS' ? value * 1000 : value),
non_interaction: true,
});
}
六、实战:完整的前端性能监控 SDK(简化版)
class PerfMonitor {
constructor(options) {
this.endpoint = options.endpoint;
this.sampleRate = options.sampleRate || 0.1;
this.init();
}
shouldReport() {
return Math.random() < this.sampleRate;
}
send(data) {
if (!this.shouldReport()) return;
navigator.sendBeacon(this.endpoint, JSON.stringify(data));
}
init() {
// Web Vitals
import('web-vitals').then(({ getLCP, getFID, getCLS }) => {
getLCS(metric => this.send(metric));
getFID(metric => this.send(metric));
getCLS(metric => this.send(metric));
});
// 自定义首屏时间
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
this.send({ type: 'domReady', value: performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart });
});
}
// 页面卸载时发送未发送的数据(可用Beacon队列)
}
}
new PerfMonitor({ endpoint: '/api/perf', sampleRate: 0.1 });
七、常见坑点
- CLS 在后台标签页不准确:用户切换标签页时,CLS 可能会误报。只在页面可见时收集。
- 移动端 vs PC:指标分开统计,因为网络和设备差异大。
- 缓存影响:已缓存的页面 LCP 会很快,应该区分首次访问和二次访问。
八、总结:让数据驱动你的优化
- 监控 LCP、FID、CLS,用
web-vitals。 - 加上业务自定义指标(首屏时间、API 耗时)。
- 采样上报,避免压力过大。
- 用 GA4 或自建系统可视化+报警。
- 定期查看指标趋势,倒退时立刻优化。
有了性能监控,你不再是“我觉得快”,而是“数据证明快”。老板问要不要优化,你甩出图表:“LCP 最近一周从2.1秒涨到3.5秒,用户流失率上升5%,建议立即优化图片。” 这才叫专业。