[Flight] Bypass caches in Flight fixture if requested (#33445)

This commit is contained in:
Hendrik Liebau 2025-06-06 06:42:58 +02:00 committed by GitHub
parent dddcae7a11
commit b1759882c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 15 deletions

View File

@ -101,6 +101,9 @@ async function renderApp(req, res, next) {
} else if (req.get('Content-type')) { } else if (req.get('Content-type')) {
proxiedHeaders['Content-type'] = req.get('Content-type'); proxiedHeaders['Content-type'] = req.get('Content-type');
} }
if (req.headers['cache-control']) {
proxiedHeaders['Cache-Control'] = req.get('cache-control');
}
const requestsPrerender = req.path === '/prerender'; const requestsPrerender = req.path === '/prerender';

View File

@ -50,7 +50,7 @@ const {readFile} = require('fs').promises;
const React = require('react'); const React = require('react');
async function renderApp(res, returnValue, formState) { async function renderApp(res, returnValue, formState, noCache) {
const {renderToPipeableStream} = await import( const {renderToPipeableStream} = await import(
'react-server-dom-webpack/server' 'react-server-dom-webpack/server'
); );
@ -97,7 +97,7 @@ async function renderApp(res, returnValue, formState) {
key: filename, key: filename,
}) })
), ),
React.createElement(App) React.createElement(App, {noCache})
); );
// For client-invoked server actions we refresh the tree and return a return value. // For client-invoked server actions we refresh the tree and return a return value.
const payload = {root, returnValue, formState}; const payload = {root, returnValue, formState};
@ -105,7 +105,7 @@ async function renderApp(res, returnValue, formState) {
pipe(res); pipe(res);
} }
async function prerenderApp(res, returnValue, formState) { async function prerenderApp(res, returnValue, formState, noCache) {
const {unstable_prerenderToNodeStream: prerenderToNodeStream} = await import( const {unstable_prerenderToNodeStream: prerenderToNodeStream} = await import(
'react-server-dom-webpack/static' 'react-server-dom-webpack/static'
); );
@ -152,7 +152,7 @@ async function prerenderApp(res, returnValue, formState) {
key: filename, key: filename,
}) })
), ),
React.createElement(App, {prerender: true}) React.createElement(App, {prerender: true, noCache})
); );
// For client-invoked server actions we refresh the tree and return a return value. // For client-invoked server actions we refresh the tree and return a return value.
const payload = {root, returnValue, formState}; const payload = {root, returnValue, formState};
@ -161,14 +161,17 @@ async function prerenderApp(res, returnValue, formState) {
} }
app.get('/', async function (req, res) { app.get('/', async function (req, res) {
const noCache = req.get('cache-control') === 'no-cache';
if ('prerender' in req.query) { if ('prerender' in req.query) {
await prerenderApp(res, null, null); await prerenderApp(res, null, null, noCache);
} else { } else {
await renderApp(res, null, null); await renderApp(res, null, null, noCache);
} }
}); });
app.post('/', bodyParser.text(), async function (req, res) { app.post('/', bodyParser.text(), async function (req, res) {
const noCache = req.headers['cache-control'] === 'no-cache';
const {decodeReply, decodeReplyFromBusboy, decodeAction, decodeFormState} = const {decodeReply, decodeReplyFromBusboy, decodeAction, decodeFormState} =
await import('react-server-dom-webpack/server'); await import('react-server-dom-webpack/server');
const serverReference = req.get('rsc-action'); const serverReference = req.get('rsc-action');
@ -201,7 +204,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
// We handle the error on the client // We handle the error on the client
} }
// Refresh the client and return the value // Refresh the client and return the value
renderApp(res, result, null); renderApp(res, result, null, noCache);
} else { } else {
// This is the progressive enhancement case // This is the progressive enhancement case
const UndiciRequest = require('undici').Request; const UndiciRequest = require('undici').Request;
@ -217,11 +220,11 @@ app.post('/', bodyParser.text(), async function (req, res) {
// Wait for any mutations // Wait for any mutations
const result = await action(); const result = await action();
const formState = decodeFormState(result, formData); const formState = decodeFormState(result, formData);
renderApp(res, null, formState); renderApp(res, null, formState, noCache);
} catch (x) { } catch (x) {
const {setServerState} = await import('../src/ServerState.js'); const {setServerState} = await import('../src/ServerState.js');
setServerState('Error: ' + x.message); setServerState('Error: ' + x.message);
renderApp(res, null, null); renderApp(res, null, null, noCache);
} }
} }
}); });

View File

@ -47,8 +47,8 @@ async function ThirdPartyComponent() {
// Using Web streams for tee'ing convenience here. // Using Web streams for tee'ing convenience here.
let cachedThirdPartyReadableWeb; let cachedThirdPartyReadableWeb;
function fetchThirdParty(Component) { function fetchThirdParty(noCache) {
if (cachedThirdPartyReadableWeb) { if (cachedThirdPartyReadableWeb && !noCache) {
const [readableWeb1, readableWeb2] = cachedThirdPartyReadableWeb.tee(); const [readableWeb1, readableWeb2] = cachedThirdPartyReadableWeb.tee();
cachedThirdPartyReadableWeb = readableWeb1; cachedThirdPartyReadableWeb = readableWeb1;
@ -79,16 +79,16 @@ function fetchThirdParty(Component) {
return result; return result;
} }
async function ServerComponent() { async function ServerComponent({noCache}) {
await new Promise(resolve => setTimeout(() => resolve('deferred text'), 50)); await new Promise(resolve => setTimeout(() => resolve('deferred text'), 50));
return await fetchThirdParty(); return fetchThirdParty(noCache);
} }
export default async function App({prerender}) { export default async function App({prerender, noCache}) {
const res = await fetch('http://localhost:3001/todos'); const res = await fetch('http://localhost:3001/todos');
const todos = await res.json(); const todos = await res.json();
const dedupedChild = <ServerComponent />; const dedupedChild = <ServerComponent noCache={noCache} />;
const message = getServerState(); const message = getServerState();
return ( return (
<html lang="en"> <html lang="en">