performance.mark() 是 web api 中用于在性能时间线中插入命名时间戳的方法,仅打点不计算耗时;必须配合 performance.measure() 才能得出真实耗时,且名称需合法、避免重复或误清除,否则无法在 devtools 或 rum 中正确采集。

什么是 performance.mark(),它真能测前端性能?
能,但不是万能的。它只记录一个命名的时间戳,不自动计算耗时,也不触发浏览器渲染或网络请求测量——本质是打点工具,类似在代码里埋个“这里我关注了”。真实耗时得靠 performance.measure() 配合两个 mark 才能算出来。
常见误用:只调用 performance.mark('start') 就以为能出数据,结果控制台查不到任何耗时,因为没 measure,也没导出。
- 必须成对使用:
mark('init-start')+mark('init-end'),再用measure('init-duration', 'init-start', 'init-end') - mark 名称不能含空格或特殊字符(如
'load data'会报错),推荐用短横线或驼峰:'loadData' - 同一名称多次调用会覆盖前一次时间戳,除非你明确想更新标记点
怎么把 mark 数据拿到手?别只盯着 console.time()
console.time() 是调试用的,不进 Performance API,没法和 Lighthouse、DevTools 的「Performance」面板联动,也不能被 RUM(真实用户监控)SDK 自动采集。performance.mark() 写入的是标准 PerformanceEntry 缓存,可编程读取:
performance.mark('api-fetch-start');
fetch('/api/data').then(() => {
performance.mark('api-fetch-end');
performance.measure('api-fetch-time', 'api-fetch-start', 'api-fetch-end');
// 立即读取(仅限当前上下文,异步任务可能还没 flush)
const entries = performance.getEntriesByName('api-fetch-time');
console.log(entries[0].duration); // 比如 324.78
});
注意:getEntriesByName() 只返回已 commit 的条目,但部分浏览器(尤其旧版 Safari)对 mark/measure 的 flush 有延迟;生产环境建议用 performance.getEntriesByType('measure') 批量捞,再过滤名称。
React/Vue 里打 mark 容易漏掉什么?
框架的异步更新机制会让 mark 时间点“漂移”——比如在 setState 后立刻 mark('render-end'),实际 DOM 还没更新,这个 mark 就失去了意义。
- React 中,想标“渲染完成”,应配合
useEffect或ReactDOM.flushSync(谨慎用);更稳妥的是用performanceObserver监听paint类型 entry - Vue 3 的
nextTick()后打 mark 更接近真实渲染结束点:nextTick(() => performance.mark('vnode-mounted')) - 避免在 computed 或 render 函数里频繁调用 mark——它本身轻量,但高频打点会污染 Performance 面板,也影响
getEntries()查询效率
为什么 DevTools 里看不到你的 mark?
最常见原因是:没在「Performance」面板录制期间执行 mark。DevTools 默认不持续监听,必须手动点「录制」(● 按钮),再触发业务逻辑,mark 才会被捕获并显示在「Timings」轨道里。
另一个隐藏坑:performance.clearMarks() 或 performance.clearMeasures() 如果被误调,会清空所有已记录项,导致后续 getEntries() 返回空数组——检查是否在初始化脚本或重试逻辑里无意识清除了。
另外,某些构建工具(如 Vite 生产模式)或 CDN 会剥离 console.* 和 performance.* 调用,务必确认代码实际运行在目标环境中,而不是被 tree-shaking 掉了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











