Load Functions
Every serious app needs to fetch data before rendering a page. React’s ecosystem has handled this many ways over the years: react-router loaders, Next.js getServerSideProps, Next.js App Router server components. SvelteKit unifies the pattern into a single, predictable convention: a load function exported from a file next to your page.
Run this in a SvelteKit project (
npx sv create).
react-router loader vs SvelteKit +page.js load
Section titled “react-router loader vs SvelteKit +page.js load”react-router v6.4+ introduced loader functions — async functions that run before the route renders. SvelteKit’s +page.js load is the same idea, but the file is co-located with the page instead of embedded in a route config object.
// react-router v6.4 — route configimport { createBrowserRouter } from 'react-router-dom';import { useLoaderData } from 'react-router-dom';
async function postLoader({ params }) { const res = await fetch('/api/posts/' + params.id); return res.json();}
function PostPage() { const post = useLoaderData(); return <h1>{post.title}</h1>;}
const router = createBrowserRouter([ { path: '/posts/:id', element: <PostPage />, loader: postLoader, },]);// src/routes/posts/[id]/+page.jsexport async function load({ params, fetch }) { const res = await fetch('/api/posts/' + params.id); const post = await res.json(); return { post };}The SvelteKit +page.js load runs on both the server (initial request) and the client (SvelteKit navigations). This means you get server-rendered HTML on first load and fast client-side transitions on subsequent navigations — for free.
Receiving data in the page component
Section titled “Receiving data in the page component”Whatever load returns is available as data via \$props():
<script> let { data } = \$props(); // data.post is the object returned from load()<\/script>
<h1>{data.post.title}</h1><p>{data.post.body}</p>TypeScript: import PageLoad (for +page.js) or PageServerLoad (for +page.server.js) from the auto-generated ./$types file:
// +page.js (universal)import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, fetch }) => { const post = await fetch('/api/posts/' + params.id).then(r => r.json()); return { post };};Next.js getServerSideProps vs SvelteKit +page.server.js
Section titled “Next.js getServerSideProps vs SvelteKit +page.server.js”getServerSideProps is Next.js Pages Router’s server-only data loader — it runs exclusively on the server, can access databases and secrets, and passes data as props to the page component. SvelteKit’s +page.server.js is the direct equivalent.
// Next.js Pages Router — pages/posts/[id].tsxexport async function getServerSideProps({ params }) { const post = await db.post.findUnique({ where: { id: Number(params.id) }, }); return { props: { post } };}
export default function PostPage({ post }) { return <h1>{post.title}</h1>;}// src/routes/posts/[id]/+page.server.jsimport { db } from '$lib/db';
export async function load({ params, cookies }) { const post = await db.post.findUnique({ where: { id: Number(params.id) }, }); return { post };}The +page.server.js version:
- Runs only on the server — safe for DB queries, secrets, private env vars.
- Receives
cookiesin addition toparams,fetch, andurl. - Returns a plain object; SvelteKit serialises it and passes it to the client as
data.
+page.js vs +page.server.js — when to use which
Section titled “+page.js vs +page.server.js — when to use which”+page.js (universal) | +page.server.js (server-only) | |
|---|---|---|
| Runs on server | Yes (initial request) | Yes (always) |
| Runs on client | Yes (navigations) | No |
Access cookies | No | Yes |
| Access DB directly | Not recommended | Yes |
| Access private env vars | No | Yes |
fetch is available | Yes (enhanced) | Yes (enhanced) |
load function arguments
Section titled “load function arguments”Both universal and server load functions receive the same core arguments:
// +page.js or +page.server.jsexport async function load({ params, fetch, url, cookies }) { // params — route parameters, e.g. params.slug // fetch — SvelteKit-enhanced fetch (sets cookies, handles relative URLs) // url — the current URL as a URL object // cookies — (server only) read/write cookies}