Lesson 24 / 25

Performance Techniques

Preloading, streaming and lean updates.

Where the wins are

SvelteKit preloads code and data for links: the default template sets data-sveltekit-preload-data="hover" on the body, so data loading starts when the pointer hovers a link. Stream slow, non-critical data by returning un-awaited promises from server load functions. Avoid waterfalls: start independent requests in parallel with Promise.all, and keep parent layout loads light because child loads that call await parent() wait for them. In components, use keyed each blocks, $state.raw for large immutable data, $derived instead of effects, and lazy-load heavy components with dynamic import(). Prerender what never changes, set cache headers with setHeaders in load, and optimise images (for example with @sveltejs/enhanced-img).

Parallel loads, cache headers, lazy component

Dashboard route.

<!-- src/routes/dashboard/+page.server.ts
import type { PageServerLoad } from './$types';
import { getStats, getAlerts, getActivity } from '$lib/server/dashboard';

export const load: PageServerLoad = async ({ locals, setHeaders }) => {
  setHeaders({ 'cache-control': 'private, max-age=30' });
  const [stats, alerts] = await Promise.all([
    getStats(locals.user!.id),
    getAlerts(locals.user!.id)
  ]);
  return { stats, alerts, activity: getActivity(locals.user!.id) }; // streamed
};
-->

<!-- src/routes/dashboard/+page.svelte -->
<script lang="ts">
  let { data } = $props();
  let showChart = $state(false);
</script>

<p>{data.stats.users} users, {data.alerts.length} alerts</p>
<button onclick={() => (showChart = true)}>Show chart</button>
{#if showChart}
  {#await import('$lib/HeavyChart.svelte') then { default: HeavyChart }}
    <HeavyChart points={data.stats.series} />
  {/await}
{/if}

Serving a meal in courses

Streaming is serving the starter while the main course cooks: the guest starts eating sooner instead of waiting for the whole meal.

Quick check: How do you let slow, non-critical data arrive after the page first renders?

  • Set export const ssr = true
  • Move the query into an $effect on the server
  • Return an un-awaited promise from the server load and use {#await} in the page
  • Wrap the page in a {#key} block
Answer

Return an un-awaited promise from the server load and use {#await} in the page — SvelteKit streams promises returned from load.