[Flight] Add a cached 3rd-party component to the Flight fixture (#33443)

This should allow us to visualize what
https://github.com/facebook/react/pull/33438 is trying to convey.

An uncached 3rd-party component is displayed like this in the dev tools:

<img width="1072" alt="Screenshot 2025-06-05 at 12 57 32"
src="https://github.com/user-attachments/assets/d418ae23-d113-4dc9-98b8-ab426710454a"
/>

However, when the component is restored from a cache, it looks like
this:

<img width="1072" alt="Screenshot 2025-06-05 at 12 56 56"
src="https://github.com/user-attachments/assets/a0e34379-d8c0-4b14-8b54-b5c06211232b"
/>

The `Server Components ⚛` track is missing completely here, and the
`Loading profile...` phase also took way longer than without caching the
3rd-party component.

On `main`, the `Server Components ⚛` track is not missing:

<img width="1072" alt="Screenshot 2025-06-05 at 14 31 20"
src="https://github.com/user-attachments/assets/c35e405d-27ca-4b04-a34c-03bd959a7687"
/>

The cached 3rd-party component starts before the current render, and is
also not excluded here, which is of course expected without #33438.
This commit is contained in:
Hendrik Liebau 2025-06-05 17:19:54 +02:00 committed by GitHub
parent 93f1668045
commit b4477d3800
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,4 +1,7 @@
import * as React from 'react';
import {renderToPipeableStream} from 'react-server-dom-webpack/server';
import {createFromNodeStream} from 'react-server-dom-webpack/client';
import {PassThrough, Readable} from 'stream';
import Container from './Container.js';
@ -35,8 +38,50 @@ async function Bar({children}) {
return <div>{children}</div>;
}
async function ThirdPartyComponent() {
return new Promise(resolve =>
setTimeout(() => resolve('hello from a 3rd party'), 30)
);
}
// Using Web streams for tee'ing convenience here.
let cachedThirdPartyReadableWeb;
function fetchThirdParty(Component) {
if (cachedThirdPartyReadableWeb) {
const [readableWeb1, readableWeb2] = cachedThirdPartyReadableWeb.tee();
cachedThirdPartyReadableWeb = readableWeb1;
return createFromNodeStream(Readable.fromWeb(readableWeb2), {
moduleMap: {},
moduleLoading: {},
});
}
const stream = renderToPipeableStream(
<ThirdPartyComponent />,
{},
{environmentName: 'third-party'}
);
const readable = new PassThrough();
// React currently only supports piping to one stream, so we convert, tee, and
// convert back again.
// TODO: Switch to web streams without converting when #33442 has landed.
const [readableWeb1, readableWeb2] = Readable.toWeb(readable).tee();
cachedThirdPartyReadableWeb = readableWeb1;
const result = createFromNodeStream(Readable.fromWeb(readableWeb2), {
moduleMap: {},
moduleLoading: {},
});
stream.pipe(readable);
return result;
}
async function ServerComponent() {
await new Promise(resolve => setTimeout(() => resolve('deferred text'), 50));
return await fetchThirdParty();
}
export default async function App({prerender}) {