Skip to content

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 (react-router)
// react-router v6.4 — route config
import { 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,
},
]);
SvelteKit +page.js
// src/routes/posts/[id]/+page.js
export 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.

Whatever load returns is available as data via \$props():

src/routes/posts/[id]/+page.svelte
<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 (getServerSideProps)
// Next.js Pages Router — pages/posts/[id].tsx
export 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>;
}
SvelteKit +page.server.js
// src/routes/posts/[id]/+page.server.js
import { 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 cookies in addition to params, fetch, and url.
  • 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 serverYes (initial request)Yes (always)
Runs on clientYes (navigations)No
Access cookiesNoYes
Access DB directlyNot recommendedYes
Access private env varsNoYes
fetch is availableYes (enhanced)Yes (enhanced)

Both universal and server load functions receive the same core arguments:

// +page.js or +page.server.js
export 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
}
What is the difference between +page.js and +page.server.js in SvelteKit?
How does a SvelteKit page component receive data returned from its load() function?
Which load() argument is only available in +page.server.js, not +page.js?