Zum Inhalt springen

Server islands

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Server islands allow you to on-demand render dynamic or personalized “islands” individually, without sacrificing the performance of the rest of the page.

This means your visitor will see the most important parts of your page sooner, and allows your main content to be more aggressively cached, providing faster performance.

A server island is a normal server-rendered Astro component that is instructed to delay rendering until its contents are available.

Your page will be rendered immediately with any specified fallback content as a placeholder. Then, the component’s own contents are fetched on the client and displayed when available.

With an adapter installed to perform the delayed rendering, add the server:defer directive to any component on your page to turn it into its own island:

src/pages/index.astro
---
import Avatar from '../components/Avatar.astro';
---
<Avatar server:defer />

These components can do anything you normally would in an on-demand rendered page using an adapter, such as fetch content, and access cookies:

src/components/Avatar.astro
---
import { getUserAvatar } from '../sessions';
const userSession = Astro.cookies.get('session');
const avatarURL = await getUserAvatar(userSession);
---
<img alt="User avatar" src={avatarURL} />

Server island fallback content

Section titled Server island fallback content

When using the server:defer attribute on a component to delay its rendering, you can “slot” in default loading content using the included named "fallback" slot.

Your fallback content will be rendered along with the rest of the page initially on page load and will be replaced with your component’s content when available.

To add fallback content, add slot="fallback" on a child (other components or HTML elements) passed to your server island component:

---
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
<GenericAvatar slot="fallback" />
</Avatar>

This fallback content can be things like:

  • A generic avatar instead of the user’s own.
  • Placeholder UI such as custom messages.
  • Loading indicators such as spinners.

Server island implementation happens mostly at build-time where component content is swapped out for a small script.

Each of the islands marked with server:defer is split off into its own special route which the script fetches at run time. When Astro builds your site it will omit the component and inject a script in its place, and any content you’ve marked with slot="fallback".

When the page loads in the browser, these components will be requested to a special endpoint that renders them and returns the HTML. This means that users will see the most critical parts of the page instantly. Fallback content will be visible for a short amount of time before the dynamic islands are then loaded.

Each island is loaded independently from the rest. This means a slower island won’t delay the rest of your personalized content from being available.

This rendering pattern was built to be portable. It does not depend on any server infrastructure so it will work with any host you have, from a Node.js server in a Docker container to the serverless provider of your choice.

The data for server islands is retrieved via a GET request, passing props as an encrypted string in the URL query. This allows caching data with the Cache-Control HTTP header using standard Cache-Control directives.

However, the browser limits URLs to a maximum length of 2048 bytes for practical reasons and to avoid causing denial-of-service problems. If your query string causes your URL to exceed this limit, Astro will instead send a POST request that contains all props in the body.

POST requests are not cached by browsers because they are used to submit data, and could cause data integrity or security issues. Therefore, any existing caching logic in your project will break. Whenever possible, pass only necessary props to your server islands and avoid sending entire data objects and arrays to keep your query small.

Accessing the page URL in a server island

Section titled Accessing the page URL in a server island

In most cases you, your server island component can get information about the page rendering it by passing props like in normal components.

However, server islands run in their own isolated context outside of the page request. Astro.url and Astro.request.url in a server island component both return a URL that looks like /_server-islands/Avatar instead of the current page’s URL in the browser. Additionally, if you are prerendering the page you will not have access to information such as query parameters in order to pass as props.

To access information from the page’s URL, you can check the Referer header, which will contain the address of the page that is loading the island in the browser:

---
const referer = Astro.request.headers.get('Referer');
const url = new URL(referer);
const productId = url.searchParams.get('product');
---

Astro uses cryptography to encrypt props passed to server islands, protecting sensitive data from accidental exposure. This encryption relies on a new, random key that is generated on each build and embedded in the server bundle.

Most deploy hosts will handle keeping your front end and back end in sync automatically. However, you may need a constant encryption key if you are using rolling deployments, multi-region hosting or a CDN that caches pages containing server islands.

In environments with rolling deployments (e.g., Kubernetes) where your frontend assets (which encrypt props) and your backend functions (which decrypt props) may be temporarily using different keys, or when a CDN is still serving pages built with an old key, encrypted props passed to your server island cannot be decrypted.

In these situations, use the Astro CLI to generate a reusable, encoded encryption key to set as an environment variable in your build environment:

Terminal window
astro create-key

Use this value to configure the ASTRO_KEY environment variable (e.g. in a .env file) and include it in your CI/CD or host’s build settings. This ensures the same key is always reused in the generated bundle so that encryption and decryption remain in sync.

Wirke mit Community Sponsor