mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
[DevTools] Add byteSize field to ReactIOInfo and show this in the tooltip (#34221)
This is intended to be used by various client side resources where the transfer size is interesting to know how it'll perform in various network conditions. Not intended to be added by the server. For now it's only added internally by DevTools itself on img/css but I'll add it from Flight Client too in a follow up. This now shows this as the "transfer size" which is the encoded body size + headers/overhead. Where as the "fileSize" that I add to images is the decoded body size, like what you'd see on disk. This is what Chrome shows so it's less confusing if you compare Network tab and this view.
This commit is contained in:
parent
7a36dfedc7
commit
42b1b33a24
|
|
@ -3343,6 +3343,7 @@ export function attach(
|
||||||
}
|
}
|
||||||
let start = -1;
|
let start = -1;
|
||||||
let end = -1;
|
let end = -1;
|
||||||
|
let byteSize = 0;
|
||||||
// $FlowFixMe[method-unbinding]
|
// $FlowFixMe[method-unbinding]
|
||||||
if (typeof performance.getEntriesByType === 'function') {
|
if (typeof performance.getEntriesByType === 'function') {
|
||||||
// We may be able to collect the start and end time of this resource from Performance Observer.
|
// We may be able to collect the start and end time of this resource from Performance Observer.
|
||||||
|
|
@ -3352,6 +3353,8 @@ export function attach(
|
||||||
if (resourceEntry.name === href) {
|
if (resourceEntry.name === href) {
|
||||||
start = resourceEntry.startTime;
|
start = resourceEntry.startTime;
|
||||||
end = start + resourceEntry.duration;
|
end = start + resourceEntry.duration;
|
||||||
|
// $FlowFixMe[prop-missing]
|
||||||
|
byteSize = (resourceEntry.transferSize: any) || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3367,6 +3370,10 @@ export function attach(
|
||||||
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
||||||
owner: fiber, // Allow linking to the <link> if it's not filtered.
|
owner: fiber, // Allow linking to the <link> if it's not filtered.
|
||||||
};
|
};
|
||||||
|
if (byteSize > 0) {
|
||||||
|
// $FlowFixMe[cannot-write]
|
||||||
|
ioInfo.byteSize = byteSize;
|
||||||
|
}
|
||||||
const asyncInfo: ReactAsyncInfo = {
|
const asyncInfo: ReactAsyncInfo = {
|
||||||
awaited: ioInfo,
|
awaited: ioInfo,
|
||||||
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
||||||
|
|
@ -3431,6 +3438,7 @@ export function attach(
|
||||||
}
|
}
|
||||||
let start = -1;
|
let start = -1;
|
||||||
let end = -1;
|
let end = -1;
|
||||||
|
let byteSize = 0;
|
||||||
let fileSize = 0;
|
let fileSize = 0;
|
||||||
// $FlowFixMe[method-unbinding]
|
// $FlowFixMe[method-unbinding]
|
||||||
if (typeof performance.getEntriesByType === 'function') {
|
if (typeof performance.getEntriesByType === 'function') {
|
||||||
|
|
@ -3442,7 +3450,9 @@ export function attach(
|
||||||
start = resourceEntry.startTime;
|
start = resourceEntry.startTime;
|
||||||
end = start + resourceEntry.duration;
|
end = start + resourceEntry.duration;
|
||||||
// $FlowFixMe[prop-missing]
|
// $FlowFixMe[prop-missing]
|
||||||
fileSize = (resourceEntry.encodedBodySize: any) || 0;
|
fileSize = (resourceEntry.decodedBodySize: any) || 0;
|
||||||
|
// $FlowFixMe[prop-missing]
|
||||||
|
byteSize = (resourceEntry.transferSize: any) || 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3476,6 +3486,10 @@ export function attach(
|
||||||
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
||||||
owner: fiber, // Allow linking to the <link> if it's not filtered.
|
owner: fiber, // Allow linking to the <link> if it's not filtered.
|
||||||
};
|
};
|
||||||
|
if (byteSize > 0) {
|
||||||
|
// $FlowFixMe[cannot-write]
|
||||||
|
ioInfo.byteSize = byteSize;
|
||||||
|
}
|
||||||
const asyncInfo: ReactAsyncInfo = {
|
const asyncInfo: ReactAsyncInfo = {
|
||||||
awaited: ioInfo,
|
awaited: ioInfo,
|
||||||
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
|
||||||
|
|
@ -4704,16 +4718,15 @@ export function attach(
|
||||||
trackDebugInfoFromLazyType(nextFiber);
|
trackDebugInfoFromLazyType(nextFiber);
|
||||||
trackDebugInfoFromUsedThenables(nextFiber);
|
trackDebugInfoFromUsedThenables(nextFiber);
|
||||||
|
|
||||||
if (
|
if (nextFiber.tag === HostHoistable) {
|
||||||
nextFiber.tag === HostHoistable &&
|
|
||||||
prevFiber.memoizedState !== nextFiber.memoizedState
|
|
||||||
) {
|
|
||||||
const nearestInstance = reconcilingParent;
|
const nearestInstance = reconcilingParent;
|
||||||
if (nearestInstance === null) {
|
if (nearestInstance === null) {
|
||||||
throw new Error('Did not expect a host hoistable to be the root');
|
throw new Error('Did not expect a host hoistable to be the root');
|
||||||
}
|
}
|
||||||
|
if (prevFiber.memoizedState !== nextFiber.memoizedState) {
|
||||||
releaseHostResource(nearestInstance, prevFiber.memoizedState);
|
releaseHostResource(nearestInstance, prevFiber.memoizedState);
|
||||||
aquireHostResource(nearestInstance, nextFiber.memoizedState);
|
aquireHostResource(nearestInstance, nextFiber.memoizedState);
|
||||||
|
}
|
||||||
trackDebugInfoFromHostResource(nearestInstance, nextFiber);
|
trackDebugInfoFromHostResource(nearestInstance, nextFiber);
|
||||||
} else if (
|
} else if (
|
||||||
nextFiber.tag === HostComponent ||
|
nextFiber.tag === HostComponent ||
|
||||||
|
|
@ -5948,6 +5961,7 @@ export function attach(
|
||||||
description: getIODescription(resolvedValue),
|
description: getIODescription(resolvedValue),
|
||||||
start: ioInfo.start,
|
start: ioInfo.start,
|
||||||
end: ioInfo.end,
|
end: ioInfo.end,
|
||||||
|
byteSize: ioInfo.byteSize == null ? null : ioInfo.byteSize,
|
||||||
value: ioInfo.value == null ? null : ioInfo.value,
|
value: ioInfo.value == null ? null : ioInfo.value,
|
||||||
env: ioInfo.env == null ? null : ioInfo.env,
|
env: ioInfo.env == null ? null : ioInfo.env,
|
||||||
owner:
|
owner:
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ export type SerializedIOInfo = {
|
||||||
description: string,
|
description: string,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
|
byteSize: null | number,
|
||||||
value: null | Promise<mixed>,
|
value: null | Promise<mixed>,
|
||||||
env: null | string,
|
env: null | string,
|
||||||
owner: null | SerializedElement,
|
owner: null | SerializedElement,
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,7 @@ function backendToFrontendSerializedAsyncInfo(
|
||||||
description: ioInfo.description,
|
description: ioInfo.description,
|
||||||
start: ioInfo.start,
|
start: ioInfo.start,
|
||||||
end: ioInfo.end,
|
end: ioInfo.end,
|
||||||
|
byteSize: ioInfo.byteSize,
|
||||||
value: ioInfo.value,
|
value: ioInfo.value,
|
||||||
env: ioInfo.env,
|
env: ioInfo.env,
|
||||||
owner:
|
owner:
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,19 @@ function getShortDescription(name: string, description: string): string {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatBytes(bytes: number) {
|
||||||
|
if (bytes < 1_000) {
|
||||||
|
return bytes + ' bytes';
|
||||||
|
}
|
||||||
|
if (bytes < 1_000_000) {
|
||||||
|
return (bytes / 1_000).toFixed(1) + ' kB';
|
||||||
|
}
|
||||||
|
if (bytes < 1_000_000_000) {
|
||||||
|
return (bytes / 1_000_000).toFixed(1) + ' mB';
|
||||||
|
}
|
||||||
|
return (bytes / 1_000_000_000).toFixed(1) + ' gB';
|
||||||
|
}
|
||||||
|
|
||||||
function SuspendedByRow({
|
function SuspendedByRow({
|
||||||
bridge,
|
bridge,
|
||||||
element,
|
element,
|
||||||
|
|
@ -145,7 +158,13 @@ function SuspendedByRow({
|
||||||
<Button
|
<Button
|
||||||
className={styles.CollapsableHeader}
|
className={styles.CollapsableHeader}
|
||||||
onClick={() => setIsOpen(prevIsOpen => !prevIsOpen)}
|
onClick={() => setIsOpen(prevIsOpen => !prevIsOpen)}
|
||||||
title={longName + ' — ' + (end - start).toFixed(2) + ' ms'}>
|
title={
|
||||||
|
longName +
|
||||||
|
' — ' +
|
||||||
|
(end - start).toFixed(2) +
|
||||||
|
' ms' +
|
||||||
|
(ioInfo.byteSize != null ? ' — ' + formatBytes(ioInfo.byteSize) : '')
|
||||||
|
}>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
className={styles.CollapsableHeaderIcon}
|
className={styles.CollapsableHeaderIcon}
|
||||||
type={isOpen ? 'expanded' : 'collapsed'}
|
type={isOpen ? 'expanded' : 'collapsed'}
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ export type SerializedIOInfo = {
|
||||||
description: string,
|
description: string,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
|
byteSize: null | number,
|
||||||
value: null | Promise<mixed>,
|
value: null | Promise<mixed>,
|
||||||
env: null | string,
|
env: null | string,
|
||||||
owner: null | SerializedElement,
|
owner: null | SerializedElement,
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,7 @@ export type ReactIOInfo = {
|
||||||
+name: string, // the name of the async function being called (e.g. "fetch")
|
+name: string, // the name of the async function being called (e.g. "fetch")
|
||||||
+start: number, // the start time
|
+start: number, // the start time
|
||||||
+end: number, // the end time (this might be different from the time the await was unblocked)
|
+end: number, // the end time (this might be different from the time the await was unblocked)
|
||||||
|
+byteSize?: number, // the byte size of this resource across the network. (should only be included if affecting the client.)
|
||||||
+value?: null | Promise<mixed>, // the Promise that was awaited if any, may be rejected
|
+value?: null | Promise<mixed>, // the Promise that was awaited if any, may be rejected
|
||||||
+env?: string, // the environment where this I/O was spawned.
|
+env?: string, // the environment where this I/O was spawned.
|
||||||
+owner?: null | ReactComponentInfo,
|
+owner?: null | ReactComponentInfo,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user