Result A
Waiting for the server
The shell is already here. This region is still waiting.
A waits 5 seconds; B waits 2. Both waits are deliberate. B finishes first.
Waiting for the server
The shell is already here. This region is still waiting.
Waiting for the server
The shell is already here. This region is still waiting.
Still waiting? Check that JavaScript is enabled, then replay the demo.
The Worker sends the document and both loading states first. Each result travels in a later patch; the browser waits for the patch's completion marker before replacing its fallback. The source below recreates this behavior.
import { Boundary } from "renku";
async function Result({ seconds }: { seconds: number }) {
// A deliberate wait for this demo. Your data work goes here.
await new Promise(resolve => setTimeout(resolve, seconds * 1000));
return @{ <p>Ready after {seconds} seconds.</p> };
}
export default function Streaming() @{
<section>
<Boundary fallback={<p>Waiting for 5 seconds…</p>}
error={<p>This result could not load.</p>}>
<Result seconds={5} />
</Boundary>
<Boundary fallback={<p>Waiting for 2 seconds…</p>}
error={<p>This result could not load.</p>}>
<Result seconds={2} />
</Boundary>
</section>
}Styling omitted. This demo uses cancellable server timers; pass context.signal to your own async work.
Without JavaScript, the shell and fallbacks remain readable. Keep essential content in the shell. Read the streaming guide →
Received from the server
2 seconds. I arrived first, while A was still waiting.
Received from the server
5 seconds. The shell and result B were already usable.