You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router v4性能测量:如何统计从点击链接到路由渲染完成的耗时

用React Router v4 + Performance API 测量导航渲染耗时

我来给你一步步拆解怎么实现这个需求,咱们从点击链接的起点到路由组件渲染完成的终点,精准掐住每一段时间:

1. 在路由点击时打起始标记

React Router的Link组件本身支持onClick事件,咱们可以在这里触发performance.mark,记录导航的开始时间。如果你有很多链接,最好封装一个自定义的测量Link组件,避免重复代码:

import { Link } from 'react-router-dom';

const MeasuredLink = ({ to, ...props }) => {
  const handleClick = () => {
    // 先清除之前的同名标记,避免旧数据干扰
    performance.clearMarks('navigation-start');
    // 打起始标记
    performance.mark('navigation-start');
  };

  return <Link onClick={handleClick} to={to} {...props} />;
};

之后所有需要测量的导航都用这个MeasuredLink代替原生Link就行。

2. 在目标路由组件渲染完成时打结束标记

路由组件挂载完成(或者异步数据加载完成)就是导航完成的节点,咱们在这里打结束标记并计算耗时:

函数组件(用useEffect)

import { useEffect } from 'react';

const TargetPage = () => {
  useEffect(() => {
    // 清除之前的结束标记
    performance.clearMarks('navigation-end');
    performance.mark('navigation-end');

    // 计算从start到end的耗时
    performance.clearMeasures('navigation-duration');
    performance.measure(
      'navigation-duration',
      'navigation-start',
      'navigation-end'
    );

    // 获取测量结果
    const measure = performance.getEntriesByName('navigation-duration')[0];
    console.log(`导航渲染耗时:${measure.duration.toFixed(2)}ms`);

    // 这里可以把耗时上报到后台做性能分析
    // reportToBackend(measure.duration);

    // 清理标记和测量结果,避免内存占用
    return () => {
      performance.clearMarks('navigation-start');
      performance.clearMarks('navigation-end');
      performance.clearMeasures('navigation-duration');
    };
  }, []); // 空依赖确保只在组件挂载时执行一次

  return <div>目标页面内容</div>;
};

类组件(用componentDidMount)

import React from 'react';

class TargetPage extends React.Component {
  componentDidMount() {
    performance.clearMarks('navigation-end');
    performance.mark('navigation-end');

    performance.clearMeasures('navigation-duration');
    performance.measure(
      'navigation-duration',
      'navigation-start',
      'navigation-end'
    );

    const measure = performance.getEntriesByName('navigation-duration')[0];
    console.log(`导航渲染耗时:${measure.duration.toFixed(2)}ms`);
  }

  componentWillUnmount() {
    performance.clearMarks('navigation-start');
    performance.clearMarks('navigation-end');
    performance.clearMeasures('navigation-duration');
  }

  render() {
    return <div>目标页面内容</div>;
  }
}

3. 特殊场景的处理

  • 懒加载组件:如果你的路由用了React.lazy和Suspense,要等懒加载组件真正渲染完成再打结束标记。可以把结束标记放在懒加载组件的useEffect里,而不是Suspense的父组件。
  • 带异步数据的页面:如果页面需要加载接口数据才能渲染完成,那结束标记应该放在数据加载完成之后,比如在useEffect里等待数据请求resolve后再打mark:
    useEffect(() => {
      const fetchData = async () => {
        await fetch('/api/data');
        // 数据加载完成后打结束标记
        performance.mark('navigation-end');
        // 后续的measure逻辑...
      };
      fetchData();
    }, []);
    
  • 路由守卫(如PrivateRoute):如果有路由权限校验,要确保守卫逻辑完成后再进入目标组件,这时候起始标记还是在点击时打,结束标记依然在目标组件挂载时打即可,因为守卫的时间会被自动包含在测量范围内。

小提示

  • 记得在生产环境测试,开发环境的React DevTools或者热重载可能会影响耗时数据的准确性。
  • 大部分现代浏览器都支持performance.mark和performance.measure,不需要额外polyfill(IE10+支持)。
  • 如果要批量分析性能数据,可以把所有测量结果存在数组里,定时上报到后台。

内容的提问来源于stack exchange,提问作者adardesign

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:40:09