性能测量需绑定用户可感知的业务起止点:搜索起始于按钮点击、结束于列表DOM挂载且非空;商品页起始于路由就绪、结束于主图加载和标题渲染完成;须规范命名、配对mark/measurement,并用sendBeacon抽样上报。

直接用 performance.mark() 和 performance.measure() 就能测,但关键在标记时机是否真实反映业务起点和终点——不能靠“代码执行到哪儿就打哪儿”,而要绑定到用户可感知、逻辑可确认的事件节点上。
找准业务语义上的起止点
起始点不是函数调用开始,而是用户触发动作或系统明确进入该模块的瞬间;结束点不是 DOM 插入完成,而是内容真正可用(如关键节点渲染完毕、文本可见、交互就绪)。
- 搜索模块:起始打在「搜索」按钮
click回调开头,不是input输入时;结束打在接口响应解析完成、列表 DOM 已挂载且非空时,比如document.querySelector('#search-results li')存在且textContent非空后 - 商品详情页:起始打在路由跳转完成(
router.afterEach或useRoute().params.id可读取后),结束打在主图加载完成 + 标题文本渲染完毕(可用requestIdleCallback延迟检查,避免抢在 paint 前) - 避免常见错误:不在组件
mounted钩子立即打结束点——此时可能只是骨架屏;也不在fetch().then()立即打,因为数据还没进模板、DOM 还没更新
规范命名与配对使用 measure
每个 measure 必须对应两个已存在的 mark,且名称唯一、可追溯。浏览器不会报错,但缺一个 mark,measure 就查不到数据。
- 推荐命名格式:
{模块}_{阶段},例如product_detail_route_enter、product_detail_render_complete - 创建测量:
performance.measure('product_detail_total', 'product_detail_route_enter', 'product_detail_render_complete') - 验证是否打成功:
performance.getEntriesByName('product_detail_route_enter', 'mark').length > 0,同理检查结束 mark 和最终 measure 条目
安全上报与数据清理
测出来不等于能用上。真实环境中,未处理的上报逻辑会让数据大量丢失或拖慢页面。
立即学习“前端免费学习笔记(深入)”;
- 上报必须用
navigator.sendBeacon(),不要用fetch或XMLHttpRequest,尤其在beforeunload中 - 做简单抽样:例如对用户 ID 取模,
userId % 100 === 0才上报,兼顾覆盖率与服务压力 - 及时清理历史条目:
performance.clearMarks()和performance.clearMeasures()在每次上报后调用,防止 PerformanceEntry 缓存无限增长
不复杂但容易忽略:标记不在业务流程里“插针”,而在它真正开始和真正落地的边界上。对齐用户感知,才能让耗时数字有业务意义。



















