现场是这样的。导航栏的下拉菜单在点击后要等 320ms 才展开,Chrome 的 INP 归因指向一次同步渲染,菜单项有八十多个,每次展开都重建整个列表。

中间走过弯路,把「鼠标移入移出都绑定事件,频繁触发重排」当成主因,改完现象没变。

这类报错背后常见的原因有几处,逐个排除就行。菜单节点一次性全部渲染,主线程被长任务占住;展开事件里同步读取了 offsetHeight,强制触发布局;第三方统计在点击回调里同步上报,阻塞了下一帧。

动手时先用性能面板看点击后的长任务

curl -s https://www.example.com/ | findstr /i "nav-menu"

然后把菜单渲染改成一次构建后复用

echo document.querySelector('.nav-menu').cloneNode(true);

移除回调里的同步布局读取

curl -s https://www.example.com/ | findstr /i offsetHeight

等前面都确认过,再把统计上报改成 sendBeacon

navigator.sendBeacon('/stat', data);

怎么算真的好了,看的是同一批现象。菜单改为复用并去掉同步布局后,点击响应降到 90ms,INP 进入良好区间。

INP 看的是点击到下一帧的延迟,渲染量大的组件要提前构建,别在事件回调里现算。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189