记录一下那天晚上的排查过程。表单页的 INP 是 340ms,其他页面都在 100ms 以内,录制发现点击提交后主线程被一段手机号校验脚本占住,用户感觉按钮卡了一下。

刚开始盯着「提交时同步发起请求并阻塞渲染,直到返回才更新状态」,折腾了半个多小时,排掉了。

排查方向其实有限,先把可能性排一排。校验逻辑在点击事件里同步遍历整个表单字段。少数情况下是每次输入都触发全量正则匹配,事件没有做防抖。

不容易想到的是,第三方埋点在最外层监听 submit 并做了同步计算。

上来先用 Performance 录制定位长任务

curl -s https://www.example.com/form/ | grep -c 'addEventListener("submit"'

再往下检查点击处理函数里的同步计算

grep -n 'onsubmit' js/form.js | head

接着把校验改成空闲时执行

requestIdleCallback(() => validate(form));

提交改用异步并给出即时反馈

form.addEventListener('submit', async (e) => { e.preventDefault(); await submit(new FormData(form)); });

怎么算真的好了,看的是同一批现象。表单页 INP 降到 120ms 以下,点击提交后按钮立即给出加载状态,用户不再感到停顿。

容易忽略的是,INP 看的是交互到下一帧的延迟,同步校验哪怕只跑 200ms,用户也会明确感觉到卡。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189