Jehlani Luciano Logo

Streaming Performance

Guidelines for optimizing page load performance using Astro's HTML streaming in SSR.

astro
          
            ## Astro Streaming Performance Guidelines

1.  Context: This applies when using Astro's Server-Side Rendering (SSR / On-Demand Rendering) capabilities. SSR uses HTML streaming to send content chunks to the browser as they become available.

2.  Problem: Blocking Fetches: If you `await` long-running data fetches (e.g., `await fetch(...)`) in the main page component's frontmatter script (`---`), Astro must wait for _all_ those fetches to complete before it can start sending _any_ HTML to the browser. This blocks rendering and can lead to slower perceived page load times.

3.  Solution 1: Component Refactoring:

    - Identify slow or independent data fetches in your main page/layout component.
    - Move each slow fetch into its own smaller, dedicated `.astro` component.
    - Import and use these new components in your main page template where the data is needed.
    - Benefit: The main page can now stream its initial HTML (like `<head>`, `<body>`, headers) immediately. The smaller components fetch their data in parallel (or sequentially depending on placement), and Astro streams their rendered HTML to the browser as soon as each component's data is ready and it's rendered.

    _Example:_

    ```astro
    <!-- BEFORE: src/pages/index.astro (slow) -->
    ---
    const slowData1 = await fetch('...');
    const slowData2 = await fetch('...');
    ---
    <html>...
      <Part1 data={slowData1} />
      <Part2 data={slowData2} />
    ...</html>

    <!-- AFTER: src/pages/index.astro (faster) -->
    ---
    import FetchPart1 from '../components/FetchPart1.astro';
    import FetchPart2 from '../components/FetchPart2.astro';
    ---
    <html>...
      <FetchPart1 />
      <FetchPart2 />
    ...</html>

    <!-- src/components/FetchPart1.astro -->
    ---
    const slowData1 = await fetch('...');
    ---
    <Part1 data={slowData1} />
    ```

4.  Solution 2: Using Promises Directly in Template:

    - Instead of `await`ing the `fetch` in the script, assign the `Promise` returned by `fetch().then(...)` to a variable.
    - Place the promise variable directly within `{}` in the component template.
    - Benefit: Astro streams the HTML _up to_ the point where the promise is used. It then waits for that specific promise to resolve, streams the resolved value, and continues streaming the rest of the HTML. Fetches placed later in the template don't block earlier content.

    _Example:_

    ```astro
    <!-- src/pages/index.astro -->
    ---
    const dataPromise = fetch('...').then(res => res.json());
    ---
    <html>...
      <p>Content before data...</p>
      <div>{dataPromise.then(data => data.message)}</div>
      <p>Content after data...</p>
    ...</html>
    ```

5.  Goal: Maximize the amount of HTML that can be sent to the browser quickly, unblocking rendering while slower data fetches complete in the background, improving metrics like Time To First Byte (TTFB) and perceived load speed.

Reference: [Using streaming to improve page performance Recipe](https://docs.astro.build/en/recipes/streaming-improve-page-performance/)