如何在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
相关产品推荐
相关产品推荐

