Skip to content

Commit 42b1b33

Browse files
authored
[DevTools] Add byteSize field to ReactIOInfo and show this in the tooltip (facebook#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.
1 parent 7a36dfe commit 42b1b33

File tree

6 files changed

+45
-8
lines changed

6 files changed

+45
-8
lines changed

packages/react-devtools-shared/src/backend/fiber/renderer.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,6 +3343,7 @@ export function attach(
33433343
}
33443344
let start = -1;
33453345
let end = -1;
3346+
let byteSize = 0;
33463347
// $FlowFixMe[method-unbinding]
33473348
if (typeof performance.getEntriesByType === 'function') {
33483349
// We may be able to collect the start and end time of this resource from Performance Observer.
@@ -3352,6 +3353,8 @@ export function attach(
33523353
if (resourceEntry.name === href) {
33533354
start = resourceEntry.startTime;
33543355
end = start + resourceEntry.duration;
3356+
// $FlowFixMe[prop-missing]
3357+
byteSize = (resourceEntry.transferSize: any) || 0;
33553358
}
33563359
}
33573360
}
@@ -3367,6 +3370,10 @@ export function attach(
33673370
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
33683371
owner: fiber, // Allow linking to the <link> if it's not filtered.
33693372
};
3373+
if (byteSize > 0) {
3374+
// $FlowFixMe[cannot-write]
3375+
ioInfo.byteSize = byteSize;
3376+
}
33703377
const asyncInfo: ReactAsyncInfo = {
33713378
awaited: ioInfo,
33723379
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
@@ -3431,6 +3438,7 @@ export function attach(
34313438
}
34323439
let start = -1;
34333440
let end = -1;
3441+
let byteSize = 0;
34343442
let fileSize = 0;
34353443
// $FlowFixMe[method-unbinding]
34363444
if (typeof performance.getEntriesByType === 'function') {
@@ -3442,7 +3450,9 @@ export function attach(
34423450
start = resourceEntry.startTime;
34433451
end = start + resourceEntry.duration;
34443452
// $FlowFixMe[prop-missing]
3445-
fileSize = (resourceEntry.encodedBodySize: any) || 0;
3453+
fileSize = (resourceEntry.decodedBodySize: any) || 0;
3454+
// $FlowFixMe[prop-missing]
3455+
byteSize = (resourceEntry.transferSize: any) || 0;
34463456
}
34473457
}
34483458
}
@@ -3476,6 +3486,10 @@ export function attach(
34763486
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
34773487
owner: fiber, // Allow linking to the <link> if it's not filtered.
34783488
};
3489+
if (byteSize > 0) {
3490+
// $FlowFixMe[cannot-write]
3491+
ioInfo.byteSize = byteSize;
3492+
}
34793493
const asyncInfo: ReactAsyncInfo = {
34803494
awaited: ioInfo,
34813495
// $FlowFixMe: This field doesn't usually take a Fiber but we're only using inside this file.
@@ -4704,16 +4718,15 @@ export function attach(
47044718
trackDebugInfoFromLazyType(nextFiber);
47054719
trackDebugInfoFromUsedThenables(nextFiber);
47064720
4707-
if (
4708-
nextFiber.tag === HostHoistable &&
4709-
prevFiber.memoizedState !== nextFiber.memoizedState
4710-
) {
4721+
if (nextFiber.tag === HostHoistable) {
47114722
const nearestInstance = reconcilingParent;
47124723
if (nearestInstance === null) {
47134724
throw new Error('Did not expect a host hoistable to be the root');
47144725
}
4715-
releaseHostResource(nearestInstance, prevFiber.memoizedState);
4716-
aquireHostResource(nearestInstance, nextFiber.memoizedState);
4726+
if (prevFiber.memoizedState !== nextFiber.memoizedState) {
4727+
releaseHostResource(nearestInstance, prevFiber.memoizedState);
4728+
aquireHostResource(nearestInstance, nextFiber.memoizedState);
4729+
}
47174730
trackDebugInfoFromHostResource(nearestInstance, nextFiber);
47184731
} else if (
47194732
nextFiber.tag === HostComponent ||
@@ -5948,6 +5961,7 @@ export function attach(
59485961
description: getIODescription(resolvedValue),
59495962
start: ioInfo.start,
59505963
end: ioInfo.end,
5964+
byteSize: ioInfo.byteSize == null ? null : ioInfo.byteSize,
59515965
value: ioInfo.value == null ? null : ioInfo.value,
59525966
env: ioInfo.env == null ? null : ioInfo.env,
59535967
owner:

packages/react-devtools-shared/src/backend/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ export type SerializedIOInfo = {
239239
description: string,
240240
start: number,
241241
end: number,
242+
byteSize: null | number,
242243
value: null | Promise<mixed>,
243244
env: null | string,
244245
owner: null | SerializedElement,

packages/react-devtools-shared/src/backendAPI.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ function backendToFrontendSerializedAsyncInfo(
221221
description: ioInfo.description,
222222
start: ioInfo.start,
223223
end: ioInfo.end,
224+
byteSize: ioInfo.byteSize,
224225
value: ioInfo.value,
225226
env: ioInfo.env,
226227
owner:

packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSuspendedBy.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ function getShortDescription(name: string, description: string): string {
7676
return '';
7777
}
7878

79+
function formatBytes(bytes: number) {
80+
if (bytes < 1_000) {
81+
return bytes + ' bytes';
82+
}
83+
if (bytes < 1_000_000) {
84+
return (bytes / 1_000).toFixed(1) + ' kB';
85+
}
86+
if (bytes < 1_000_000_000) {
87+
return (bytes / 1_000_000).toFixed(1) + ' mB';
88+
}
89+
return (bytes / 1_000_000_000).toFixed(1) + ' gB';
90+
}
91+
7992
function SuspendedByRow({
8093
bridge,
8194
element,
@@ -145,7 +158,13 @@ function SuspendedByRow({
145158
<Button
146159
className={styles.CollapsableHeader}
147160
onClick={() => setIsOpen(prevIsOpen => !prevIsOpen)}
148-
title={longName + ' — ' + (end - start).toFixed(2) + ' ms'}>
161+
title={
162+
longName +
163+
' — ' +
164+
(end - start).toFixed(2) +
165+
' ms' +
166+
(ioInfo.byteSize != null ? ' — ' + formatBytes(ioInfo.byteSize) : '')
167+
}>
149168
<ButtonIcon
150169
className={styles.CollapsableHeaderIcon}
151170
type={isOpen ? 'expanded' : 'collapsed'}

packages/react-devtools-shared/src/frontend/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ export type SerializedIOInfo = {
207207
description: string,
208208
start: number,
209209
end: number,
210+
byteSize: null | number,
210211
value: null | Promise<mixed>,
211212
env: null | string,
212213
owner: null | SerializedElement,

packages/shared/ReactTypes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ export type ReactIOInfo = {
237237
+name: string, // the name of the async function being called (e.g. "fetch")
238238
+start: number, // the start time
239239
+end: number, // the end time (this might be different from the time the await was unblocked)
240+
+byteSize?: number, // the byte size of this resource across the network. (should only be included if affecting the client.)
240241
+value?: null | Promise<mixed>, // the Promise that was awaited if any, may be rejected
241242
+env?: string, // the environment where this I/O was spawned.
242243
+owner?: null | ReactComponentInfo,

0 commit comments

Comments
 (0)