GitHub

Streaming pagelets

This page was sent before its parts were ready. Every pagelet waits for a slow “API”, is rendered at the same time as the others, and is flushed into its placeholder as soon as it is done. One of them fails and shows its fallback; one waits for a later phase.
  • defer() and content()

    The content is rendered when the pagelet is, not when the page is built.

  • BigPipe::stream()

    Flushes the page, then every pagelet as soon as it is rendered.

  • BigPipe::setParallel(true)

    Pagelets that wait with Pagelet::sleep() or await() do not hold up each other.

  • setFallback()

    A pagelet that throws is replaced by its fallback, the page goes on.

  • setPhase()

    A pagelet of a later phase is shown after the earlier ones.

  • refreshPagelet()

    A response renders a pagelet again and replaces it.

Controller.php
class FeedPagelet extends Pagelet
{
    protected mixed $fallback = '<p>The feed is not available.</p>';

    protected function content(): string
    {
        // Waits without blocking the other pagelets.
        $posts = Pagelet::await(fn () => $this->api->poll());

        return view('feed', ['posts' => $posts])->render();
    }
}

// The controller
BigPipe::setParallel(true);

return response()->stream(function () {
    echo view('page', ['feed' => new FeedPagelet()])->render();
    BigPipe::stream();             // every pagelet when it is ready
    echo '</body></html>';
}, 200, ['X-Accel-Buffering' => 'no']);
Try it
layout flushed at
20 ms
last pagelet rendered at
…
Profile #pagelet_profile
API
200 ms
rendered at
221 ms
shown at
…
Feed #pagelet_feed
API
1200 ms
rendered at
1423 ms
shown at
…
Statistics #pagelet_stats
API
700 ms
rendered at
2123 ms
shown at
…
Ads #pagelet_ads

The API failed: this is the fallback of the pagelet. The rest of the page is fine.

API
500 ms
rendered at
2624 ms
shown at
…
Suggestions phase 1
API
300 ms
rendered at
2926 ms
shown at
…

Five pagelets, one response

The layout was flushed first, then every pagelet as soon as it was rendered; the bars end where each one was. Suggestions is in phase 1: rendered early, it is sent after the others. Shown at is when the browser displayed it (with the Vite dev server, once the page is parsed). Switch to one after another and compare.