Consider this Next.js Server Component that streams a long operation result:
export default async function StreamExample() {
const stream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode('Loading...\n'));
setTimeout(() => {
controller.enqueue(new TextEncoder().encode('Data chunk 1\n'));
controller.close();
}, 1000);
}
});
const response = new Response(stream);
const body = response.body;
return (
<pre>{body ? 'Streaming started' : 'No stream'}</pre>
);
}What will the user see immediately when this component renders?
export default async function StreamExample() { const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode('Loading...\n')); setTimeout(() => { controller.enqueue(new TextEncoder().encode('Data chunk 1\n')); controller.close(); }, 1000); } }); const response = new Response(stream); const body = response.body; return ( <pre>{body ? 'Streaming started' : 'No stream'}</pre> ); }
Check what the variable body contains and how JSX renders it.
The body is a ReadableStream object, which is truthy, so the ternary renders 'Streaming started' immediately. The actual streamed text is not rendered here because the component does not consume the stream to display chunks.
Which code snippet correctly streams JSON chunks from a Next.js Server Component?
ReadableStream expects Uint8Array chunks, not strings or buffers.
ReadableStream's enqueue method requires a Uint8Array or similar binary chunk. Using new TextEncoder().encode() converts the JSON string to Uint8Array correctly.
Review this Next.js Server Component code:
export default async function StreamError() {
const stream = new ReadableStream({
start(controller) {
controller.enqueue('Hello');
controller.close();
}
});
const response = new Response(stream);
const text = await response.text();
return <pre>{text}</pre>;
}Why does this code cause a runtime error?
export default async function StreamError() { const stream = new ReadableStream({ start(controller) { controller.enqueue('Hello'); controller.close(); } }); const response = new Response(stream); const text = await response.text(); return <pre>{text}</pre>; }
Check the type of argument passed to controller.enqueue.
controller.enqueue requires a Uint8Array or similar binary chunk. Passing a string directly causes a TypeError at runtime.
Given this Next.js Server Component:
export default async function DelayedStream() {
const stream = new ReadableStream({
async start(controller) {
controller.enqueue(new TextEncoder().encode('Start\n'));
await new Promise(r => setTimeout(r, 500));
controller.enqueue(new TextEncoder().encode('Middle\n'));
await new Promise(r => setTimeout(r, 500));
controller.enqueue(new TextEncoder().encode('End\n'));
controller.close();
}
});
const response = new Response(stream);
const text = await response.text();
return <pre>{text}</pre>;
}What will the user see when this component renders?
export default async function DelayedStream() { const stream = new ReadableStream({ async start(controller) { controller.enqueue(new TextEncoder().encode('Start\n')); await new Promise(r => setTimeout(r, 500)); controller.enqueue(new TextEncoder().encode('Middle\n')); await new Promise(r => setTimeout(r, 500)); controller.enqueue(new TextEncoder().encode('End\n')); controller.close(); } }); const response = new Response(stream); const text = await response.text(); return <pre>{text}</pre>; }
Consider how await response.text() works with streams.
The await response.text() waits for the entire stream to finish before returning the full text. So the user sees all text at once after about 1 second.
In Next.js 14+, which streaming approach allows the browser to progressively render HTML chunks as they arrive from the server?
Think about how streaming HTML works in Next.js Server Components.
Returning a Response with a ReadableStream body from a Server Component enables Next.js to stream HTML chunks progressively to the browser, improving perceived load time.