页面卡了但 Lighthouse 一直绿?这个 API 把真正拖慢帧率的东西抓出来了
你的 Lighthouse 分数一直绿,队友都说”性能没问题”,但用户就是抱怨页面卡——这个问题折磨了我三年。直到我发现 Lighthouse 看的是考场成绩,而真正卡在哪儿它根本不知道。
Chrome 从 114 开始支持了一个新 API:Long Animation Frames API,简称 LoAF。它专门干一件事——把那些拖慢帧率的长周期一个一个捞出来,精确到毫秒级。
Long Animation Frame 的阈值是 100ms——超过这个时间的一帧就算”长帧”。LoAF 会记录这一帧的完整信息:帧总时长、渲染耗时、脚本执行时间和具体函数、以及 CSS 和布局的时间占比。
用起来很简单:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('长帧检测到:', {
duration: entry.duration, // 帧总时长 ms
renderDuration: entry.renderDuration, // 渲染耗时
styleAndLayoutDuration: entry.styleAndLayoutDuration, // 样式+布局
scripts: entry.scripts.map(s => ({
name: s.name,
duration: s.duration,
startTime: s.startTime,
sourceLocation: s.sourceLocation
}))
});
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
这就是关键所在:LoAF 告诉你的是哪个脚本、哪个函数占用了多长时间,而不是笼统的”主线程阻塞”。
LoAF 和 Long Tasks API 有什么区别?Long Tasks API(50ms 阈值)只告诉你”有任务阻塞了”,LoAF 说的是”这一帧里发生了什么”。LoAF 能区分渲染阶段和脚本阶段,能看到具体哪个函数调用了多久,精度完全不在一个量级。
落地方式很简单。首先,确认浏览器支持情况:Chrome 114+、Edge 114+ 支持,Firefox 在实现中,Safari 技术预览版也有支持。可以用 if ('PerformanceLongAnimationFrameTiming' in self) 做渐进增强。
然后,把监测代码加进去,用 PerformanceObserver 收集长帧数据,超过阈值就上报:
const observer = new PerformanceObserver((list) => {
for (const frame of list.getEntries()) {
// 帧时长超过 150ms 触发告警
if (frame.duration > 150) {
reportFrame({
duration: frame.duration,
scripts: frame.scripts.map(s => s.name),
timestamp: Date.now()
});
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
这样做的意义是:Lighthouse 跑的是实验室数据,不是你真实用户的机器。LoAF 拿到的是现场数据——用户的 CPU 负载、标签页数量、扩展程序影响,这些才是真正的性能真相。
Chrome DevTools 现在也能直接看到长帧了,打开 Performance 面板,录制约 5 秒的操作,找到红色标记的 Long Animation Frame 条目,点开就能看到具体是哪个脚本在作祟。
这个 API 真正解决了 Lighthouse 和 DevTools 之间的空白:Lighthouse 给你分数,DevTools 给实验室 trace,而 LoAF 给你真实用户在生产环境里遇到的长帧数据。下次有人再说”性能没问题,Lighthouse 全绿”的时候,你知道怎么回应了。
评论区
登录后可评论。