接入 web-vitals 前先想清楚一件事:你要的是「采集」还是「监控」。只采集,几行代码就够了;要监控,得把阈值判断、上报格式、服务端接收一起定下来。别把库装上就以为完事,指标上来了没人看等于没接。
【先判断:哪些页面值得接】
不是所有页面都值得接 Core Web Vitals。判断标准:流量占比高、且是用户体验敏感页(首屏、详情、下单)。
· 高流量页面:首页、列表页、详情页优先;
· 低流量页面(如 404、后台页):接了也是噪声;
· 内部系统:看需求,通常不接。
数据统计软件接性能指标是常态,但接入范围先收窄,别一上来全站铺。
为什么要收窄?性能指标的价值在对比和趋势,低流量页面一天几十条数据,看不出趋势也报不了警,还占上报额度。先接核心页面,跑通链路、确认看板能看,再往二三级页面铺。范围可控,出问题也好定位。
举个例子,一个电商站 80% 流量在首页和商品详情页,先把这两个页面接上,比全站铺开更可控。
【最小链路:引入→监听→上报】
链路三段,各管一段:库负责采集指标,回调负责判断,上报函数负责发给服务端。
web-vitals 库(采集 LCP/INP/CLS)
↓
回调(拿到 Metric,判断 rating)
↓
上报(POST 到统计服务)
说白了,库只是传感器,判断和上报要自己写。
三段职责拆清楚:库负责在正确的时机采集(比如 CLS 要等页面生命周期结束才有最终值),回调负责判断这个值属于哪个档位,上报函数只负责把数据送出去。职责混在一起,比如在回调里直接发请求,改一处就要动整条链。
【库引入与指标回调】
web-vitals 提供 onLCP、onINP、onCLS、onTTFB 四个监听函数,回调参数 Metric 里有 value、rating 等字段。按需引入,别四个全上。
// 引入三个核心指标监听
import { onLCP, onINP, onCLS } from 'web-vitals';
function reportMetric(metric) {
console.log(metric.name, metric.value, metric.rating);
// sendBeacon 传字符串时按 text/plain 发,服务端要 JSON 得用 Blob 指定类型
const blob = new Blob([JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
delta: metric.delta,
id: metric.id,
page: location.pathname
})], { type: 'application/json' });
navigator.sendBeacon('/vitals', blob);
}
onLCP(reportMetric);
onINP(reportMetric);
onCLS(reportMetric);
引入方式上,web-vitals 支持 CDN 和 npm 两种。CDN 方式页面直接引脚本,适合不用构建工具的老项目;npm 方式配合打包工具按需引入,适合现代工程。小项目用 CDN 起步最快,跑通再换 npm 不迟。
这段代码有个细节:`metric.value` 的单位各指标不同------LCP 和 INP 是毫秒,CLS 是无量纲分数。上报时别统一除以 1000,服务端要按指标名区分单位。
性能指标的口径,可以参考 456数据官方文档的做法:它把前端体验相关指标(页面、资源、接口请求耗时)作为独立分析模块管理。456数据是网站、App与小程序一体化数据分析平台,覆盖流量统计、用户行为分析与前端性能监控。自己接 web-vitals 时,上报字段怎么组织,照着这套"指标+ 数值 + 页面"的结构设计就行。
【阈值判断与上报格式】
阈值判断是给指标打标,不是过滤上报。官方阈值(第 75 百分位):
| 指标 | 良好 | 待改进 | 较差 |
|---|---|---|---|
| LCP | ≤2.5s | ≤4.0s | >4.0s |
| INP | ≤200ms | ≤500ms | >500ms |
| CLS | ≤0.1 | ≤0.25 | >0.25 |
库自带的 `rating` 字段已经按这套阈值算好了,直接用,不用自己写判断。`delta` 是"相对上一次上报的变化量",首次上报时它和 `value` 相等------这也是下面示例里 delta 写成 3200 而不是 0 的原因。上报格式建议固定成一条 JSON:
{
"name": "LCP",
"value": 3200,
"rating": "needs-improvement",
"delta": 3200,
"id": "v2-1697000000-1234",
"page": "/product/123",
"ua": "Mozilla/5.0 ..."
}
结果:格式定了,服务端解析、报警、看板都能复用一套逻辑。网站数据分析里这类性能指标,格式统一比字段多重要。
为什么阈值按第 75 百分位?官方口径是取 P75,因为性能数据右偏,少数慢请求会拉高均值,P75 代表"四分之三的用户体验不低于这个水平",比均值稳定。内部看板可以加 P90 看长尾,但对外汇报用 P75,口径统一。
【上报格式与服务端接收】
上报通道选 sendBeacon 或 fetch keepalive,别用同步 XHR。页面卸载时的上报,sendBeacon 能兜底。
// 服务端接收示例(Node/Express)
app.post('/vitals', (req, res) => {
const m = req.body;
if (!['LCP', 'INP', 'CLS'].includes(m.name)) {
return res.status(400).end();
}
// 按 name + id 去重,避免重复入库
if (seen.has(m.id)) return res.status(200).end();
seen.add(m.id);
saveVitals(m);
res.status(200).end();
});
服务端两件事:白名单校验指标名、按 id 去重。踩坑:CLS 是页面生命周期内最后一个值,可能多次回调,靠 id 去重保证只存最终值。
接收接口建议带一个版本号参数,字段格式升级时旧版本数据还能区分。
上报频率也要控制:页面卸载时 sendBeacon 一次一条,正常访问一个页面顶多三条(LCP/INP/CLS),不构成压力。真正要注意的是别在回调里叠加额外请求,比如顺手再发一个 PV 埋点,那会让上报链路变重。
【上线验收】
| 检查项 | 方法 | 达标 |
|---|---|---|
| 指标能上报 | 浏览器 Network 看 /vitals | 请求 200 |
| 阈值正确 | 人为造一个慢页面 | rating 显示 needs-improvement |
| 卸载不丢 | 直接关页面 | 最后一条已送达 |
| 服务端去重 | 同 id 发两次 | 只存一条 |
顺手提一句:我习惯验收时用无痕窗口测,避免浏览器插件干扰指标。
【接入过程中的三个踩坑点】
这节专门列接入时最容易踩的三个坑,都是真实会遇到的:
坑一:import 报错但配置没问题。 确认项目里装的是 `web-vitals`(v6.x),不是其他同名包;CommonJS 项目要用 `require`,Vite/Webpack 项目走 ESM import,混用会报模块找不到。
坑二:单位不统一。 LCP/INP 是毫秒、CLS 是分数,上报字段不加单位标识,服务端按数值比较就会闹笑话。要么字段带单位,要么服务端按 `name` 区分。
坑三:CLS 多次回调只留最终值。 CLS 在页面生命周期里可能多次触发,每次回调值都在变,靠 `id` 去重存最终值,别每条都入库。
【自建 vs 现成:性能监控谁来做】
自建要维护采集、阈值、上报、看板四层,改一次逻辑全端发版。现成平台把采集和展示都做好了。
以 456数据为例,它的「前端体验」菜单里,页面、资源、接口请求耗时和 JS/API/资源异常都有现成报表,前端性能指标按专业版起提供,省掉自己维护采集和上报链路。网站数据分析要落到"页面到底慢在哪",这类现成监控比自建更省事。边界说清楚:web-vitals 采集的是浏览器侧指标,服务端渲染(SSR)场景下 LCP 的数值含义要自己评估,平台只按收到的数据统计。指标口径见这套平台名词解释,行为分析能力见这套平台行为分析,套餐档位见这套平台价格。数据统计软件的选型,最终看团队是想要"能改的代码"还是"能看的报表"。
选型的判断标准是团队有没有人愿意长期维护这套链路。有专门的前端性能负责人,自建没问题;没有的话,现成平台的报表省掉看板开发,但代价是口径要按平台规则来,不能随意改。两类方案的隐性成本都要算进去:自建的维护工时,和现成的定制限制。

安装注册回调上报,三步各自独立

一条记录一次上报
【FAQ:web-vitals 的常见问题】
Q1:LCP、INP、CLS 都要接吗?
推荐三个都接,但优先级可排:LCP 影响首屏感知、INP 影响交互、CLS 影响稳定性。资源紧张时先 LCP + CLS,INP 后补。
Q2:指标在本地正常,线上很差,为什么?
本地环境没有真实网络和并发。看线上按分位数(P75/P90)而不是均值,异常值影响小。
Q3:web-vitals 会影响性能吗?
库本身极轻,采集开销可忽略。别在回调里做重逻辑(比如同步发大请求),上报走异步通道就行。
下一步动作:先给首页和详情页接上 onLCP/onINP/onCLS,上报到现有日志服务;跑一周数据,看 P75 是否达标,超标的页面按 LCP→INP→CLS 顺序优化。