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

如何在ReactJS中获取网络传输的精确数据量?

在ReactJS应用中精确测量网络请求传输数据量

问题背景

我正在开发一款ReactJS应用,出于性能监控需求,需要测量网络传输的精确数据量,具体要获取应用发起的网络请求的传输大小。

现有尝试

我尝试使用Performance API,通过performance.getEntriesByType('resource')方法获取资源计时,但transferSize属性的结果与实际传输大小并不总是一致,无法提供所需的精确数据。

示例代码:

window.addEventListener('load', () => {
  const resources = performance.getEntriesByType('resource');
  const totalSize = resources.reduce((acc, resource) => acc + resource.transferSize, 0);
  console.log('Total transferred size:', totalSize);
});

需求

  • 在ReactJS应用中获取网络请求精确传输数据量的可靠方法或库。
  • 可实现该目标的示例代码或方案。

解决方案

方法1:拦截XMLHttpRequest和fetch请求

通过重写原生的XMLHttpRequest和fetch方法,直接获取请求的实际传输大小,这种方式能覆盖绝大多数应用内发起的请求。

实现代码(封装为React自定义Hook)

import { useEffect } from 'react';

export const useNetworkSizeMonitor = () => {
  useEffect(() => {
    let totalTransferred = 0;

    // 拦截XMLHttpRequest
    const originalXHR = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function() {
      this.addEventListener('load', () => {
        // 优先读取响应头的Content-Length
        const contentLength = this.getResponseHeader('Content-Length');
        if (contentLength) {
          totalTransferred += parseInt(contentLength, 10);
        } else {
          // 无Content-Length时计算响应文本字节数
          totalTransferred += this.responseText?.length || 0;
        }
        console.log('累计传输大小:', totalTransferred);
      });
      originalXHR.apply(this, arguments);
    };

    // 拦截fetch请求
    const originalFetch = window.fetch;
    window.fetch = async (...args) => {
      const response = await originalFetch(...args);
      // 克隆响应避免原响应被消耗
      const clonedResponse = response.clone();
      const blob = await clonedResponse.blob();
      totalTransferred += blob.size;
      console.log('累计传输大小:', totalTransferred);
      return response;
    };

    // 组件卸载时恢复原生方法
    return () => {
      XMLHttpRequest.prototype.send = originalXHR;
      window.fetch = originalFetch;
    };
  }, []);
};

// 在组件中使用示例
function App() {
  useNetworkSizeMonitor();

  return (
    <div className="App">
      {/* 应用内容 */}
    </div>
  );
}

方法2:使用PerformanceObserver实时监听资源

相比一次性获取资源条目,PerformanceObserver能实时捕获页面加载后动态发起的请求,结合encodedBodySize可获取更准确的传输数据:

import { useEffect } from 'react';

export const usePerformanceNetworkMonitor = () => {
  useEffect(() => {
    let totalSize = 0;

    const observer = new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        if (entry.entryType === 'resource') {
          // encodedBodySize为压缩后的响应体大小,符合传输数据量需求
          totalSize += entry.encodedBodySize;
          console.log(`${entry.name} 传输大小: ${entry.encodedBodySize}`);
          console.log('累计传输大小:', totalSize);
        }
      }
    });

    observer.observe({ entryTypes: ['resource'] });

    return () => {
      observer.disconnect();
    };
  }, []);
};

注意事项

  • transferSize包含响应头+响应体的总大小,encodedBodySize仅为压缩后的响应体大小,可根据监控需求选择。
  • 跨域请求若未配置Timing-Allow-Origin头,Performance API部分属性会返回0,此时拦截请求的方法更可靠。
  • 若需覆盖所有资源请求(含第三方脚本、图片),可结合两种方法使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:50:05