Skip to content

Async components and server data

A generated element renderer becomes asynchronous in either of these cases:

  • The Svelte component awaits during server rendering.
  • Its adjacent server preparation hook returns a promise.

Choose the source of the async work based on what the browser needs to repeat.

Use Svelte’s async support when waiting belongs to the component’s render. The component code and its imports take part in both browser and server builds. The browser runs that work again during hydration because svebcomponents cannot serialize component-local state.

Enable compilerOptions.experimental.async in the component package’s Svelte configuration. Enable the same setting in a SvelteKit host.

Add <entry>.ssr.ts next to a component entry when you need server-only code or want to pass a prepared value into hydration. For src/ProfileCard.svelte, create src/ProfileCard.ssr.ts:

import type { SsrPrepare } from "@svebcomponents/ssr";
import { loadProfile } from "./profile.server.js";
const prepare: SsrPrepare = ({ props, setProperty }) => {
if (props.profile !== undefined) return;
return loadProfile().then((profile) => {
setProperty("profile", profile);
});
};
export default prepare;

props contains the values the host supplied. setProperty() changes the props before Svelte renders. In a hydratable build, the server renderer serializes JSON-compatible rich values for the generated element extension, so hydration starts with the same data. Functions, symbols, and cyclic objects cannot cross this handoff.

Keep the synchronous return when the host already supplied the value. Hosts that cannot await can still render that request through their synchronous path.

@svebcomponents/build includes the adjacent hook in the server output and keeps its dependencies out of the browser bundle.