mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
By accident, the responses for server actions that fetch something and don't revalidate are currently not streamed to the browser until the `fetch` calls are fully resolved. In the simplest case this happens when a server action returns the response body of a `fetch` call. This is especially critical if that response is itself streaming, for example for a chat app. In that case the client didn't see any updates until the whole stream was resolved. It affected mostly dev mode (due to the HMR fetch cache), but also prod if the fetch was explicitly marked as cacheable. The cause of the issue is that we are awaiting `pendingRevalidates` (in which the cache-writing promise is stored) after executing the action and before rendering. However, when we skip rendering and return the action directly this is unnecessary and blocks the response. Instead, we can defer awaiting the `pendingRevalidates` using `waitUntil`, as we do after rendering. This is executed at the very end, before the response is closed.
21 lines
545 B
TypeScript
21 lines
545 B
TypeScript
import { setTimeout } from 'timers/promises'
|
|
|
|
const loremIpsum =
|
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.\n'
|
|
|
|
export async function GET() {
|
|
const encoder = new TextEncoder()
|
|
|
|
const stream = new ReadableStream({
|
|
async start(controller) {
|
|
for (let i = 0; i < 50; i++) {
|
|
await setTimeout(100)
|
|
controller.enqueue(encoder.encode(loremIpsum))
|
|
}
|
|
controller.close()
|
|
},
|
|
})
|
|
|
|
return new Response(stream, { headers: { 'Content-Type': 'text/plain' } })
|
|
}
|