Learn Svelte - Server-side Rendering & SvelteKit
Series/Learn Svelte/Episode 21
Episode 21 of 24

Learn Svelte - Server-side Rendering & SvelteKit

This episode covers where pages are rendered: the differences between SSG, SSR, and hybrid rendering in SvelteKit, load functions and server data, islands architecture and partial hydration, and when to use SSR versus SSG.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

A web page can be rendered in many places: on the server, in the browser, or not rendered at all and stored as static HTML. The chosen strategy determines speed, SEO, and interactivity.

This episode covers SSG, SSR, and hybrid rendering in SvelteKit, load functions and server data, islands architecture and partial hydration, and when to use SSR versus SSG.

When you're done, you'll understand why one page can be static while another needs a server, and how SvelteKit blends both seamlessly.

The rendering strategy also affects operational cost: every SSR request uses server CPU, while static files are served almost for free. Choosing the right mode is both an architecture and a financial decision.

SSG, SSR, and Hybrid Rendering

Three Basic Strategies

SSG (static site generation) renders pages once at build time and serves them as static files. SSR (server-side rendering) renders on the server when requested. SvelteKit allows both at once — even within a single app.

There's one additional mode often overlooked: pages rendered on the server at build time and hydrated on the client (SSG plus hydration). This combination gives fast HTML with full interactivity.

Per-Page Behavior

Rendering mode is set per page through configuration in +page.js:

JSPrerender one page
export const prerender = true

With prerender = true, the page is produced as static HTML at build time. Other relevant values: ssr = false to disable server rendering, and csr = false to disable client hydration. This combination of values is how SvelteKit controls per-page mode without global configuration.

Load Functions and Server-side Data

Data Provided Before Rendering

Load functions provide data for a page before the component renders. Data can be fetched on the server or the client, depending on the file it's written in:

JSLoad function for server data
export async function load({ fetch }) {
  const res = await fetch("/api/posts")
  if (!res.ok) {
    throw new Error("Gagal memuat posting")
  }
  return { posts: await res.json() }
}

The fetch received by a load function works seamlessly on both server and client. Loaded data is passed to the page, and this process runs on the server when SSR is active — so the first HTML already contains content, not a spinner.

A load function can also call await parent() to inherit data from a layout above it, or return streamed data for parts that can be displayed sooner.

Splitting Data per Route

Data used only by a parent layout goes in a layout load function; page-specific data goes in a page load function. SvelteKit merges them without duplication, and the execution order can be managed with await parent from page to layout.

Data fetched on the server can also be marked as streaming, so slow parts of a page don't hold back fast ones. Users see first content sooner while the rest follows.

Islands Architecture and Partial Hydration

The Islands Concept

Islands architecture renders most of a page as static HTML and only hydrates the interactive parts. The result: less JavaScript downloaded and executed on the client.

The term "islands" first became popular in the server-rendered framework community, and it's now a pattern adopted across ecosystems because it saves significant JavaScript bytes.

Partial Hydration in SvelteKit

SvelteKit doesn't use islands literally, but it supports a similar approach. Prerendered pages still get interactivity on components that need state:

Interactive component on a static page
<script>
  let aktif = $state(false)
</script>
 
<button onclick={() => (aktif = !aktif)}>Buka menu</button>

This component lives among static markup. The main page is server-rendered while this button hydrates and responds to interaction — like an island in a sea of static HTML.

Combining prerender with interactive components makes blog or marketing pages feel static yet alive. Users get fast HTML; only the components needing state load their JavaScript.

When to Use SSR vs SSG

The Strengths of Each

SSG excels for content that rarely changes: blogs, documentation, and marketing pages. Its speed is unbeatable because HTML is ready and can be cached on a CDN. SSR excels for personal, dynamic data: dashboards, user-dependent pages, and frequently updated content.

Also watch build time: SSG builds every page at release, so a site with tens of thousands of pages needs longer builds than SSR, which builds one page once.

A Practical Hybrid Pattern

Start with prerender for everything predictable, and set prerender = false on dynamic routes. This hybrid pattern lowers server load while preserving a personal experience. Measure app behavior then adjust — no configuration is absolutely wrong.

For large content sites, combine SSG with incremental builds: only changed pages get rebuilt. This approach keeps SSG speed without sacrificing scale.

Conclusion

Key takeaways:

  • SSG, SSR, and hybrid modes can be combined in one app.
  • Set rendering mode per page with prerender, ssr, and csr.
  • Load functions provide data before a page renders.
  • Islands architecture minimizes hydrated JavaScript.
  • SSG for rarely changing content, SSR for personal and dynamic data.
  • Use the hybrid pattern as a balanced starting point.

Next, in episode 22 you'll learn observability & monitoring — monitoring frontend performance and errors, logging client issues and user metrics, real user monitoring and analytics, and production support and incident handling. The rendering strategy you choose can be monitored with real results.