Загрузка данных: функция load

Функция load в +page.js/+page.server.js загружает данные для страницы до её отрисовки и отдаёт их как проп data.

«Сначала данные, потом разметка.» Загрузчик гарантирует, что страница рендерится уже с готовыми данными — без мерцания пустого экрана.

Страницам почти всегда нужны данные: список статей, профиль пользователя, товары. SvelteKit предлагает аккуратный механизм — функцию load. Вы создаёте рядом с +page.svelte файл +page.js (или +page.server.js) и экспортируете из него load. То, что она вернёт, попадёт в страницу как проп data — уже к моменту рендера.

Есть два варианта загрузчика. +page.js — универсальный: код выполняется и на сервере (при первой загрузке), и на клиенте (при навигации). +page.server.js — только серверный: здесь безопасно обращаться к базе данных, использовать секретные ключи, читать файлы. Выбор зависит от того, нужен ли доступ к серверным ресурсам.

// src/routes/blog/[slug]/+page.server.js
export async function load({ params }) {
  const post = await db.getPost(params.slug); // безопасно: только на сервере
  if (!post) throw error(404, 'Статья не найдена');
  return { post };
}
<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
  let { data } = $props(); // то, что вернул load
</script>

<h1>{data.post.title}</h1>
<article>{data.post.body}</article>

Загрузчик получает полезный контекст: params (динамические сегменты URL), fetch (умная обёртка, которая на сервере не делает лишних запросов), url и другое. Разделяйте данные грамотно: глобальные вещи (текущий пользователь) грузите в +layout.server.js, а специфичные для страницы — в её собственном загрузчике. Важно: возвращаемые данные должны быть сериализуемыми — при навигации они передаются с сервера на клиент.

Как это работает под капотом

При запросе SvelteKit сначала вызывает load, ждёт данные, затем рендерит страницу с этими данными. При клиентской навигации он вызывает load снова, но рендерит уже без перезагрузки страницы. Смоделируем этот порядок «загрузить, потом отрисовать».

// Порядок: load -> затем render с данными
async function load(params) {
  // имитируем запрос к 'базе'
  await new Promise(r => setTimeout(r, 0));
  return { post: { title: 'Привет, SvelteKit', slug: params.slug } };
}
function render(data) {
  console.log('рендер страницы с заголовком:', data.post.title);
}

(async () => {
  const data = await load({ slug: 'hello' }); // СНАЧАЛА данные
  render(data);                                // ПОТОМ разметка
})();

Попробуй сам ▶ — вставь код в консоль браузера (F12 → Console) и нажми Enter, чтобы увидеть вывод.

  запрос /blog/hello
        |
        v
  load({ params }) -> данные { post }
        |
        v
  +page.svelte получает data
        |
        v
  HTML с готовыми данными -> браузер

Частые ошибки

  • Обращаться к базе или секретам в +page.js. Это попадёт в браузер; используйте +page.server.js.
  • Возвращать несериализуемое из load. Функции и классы не переживут передачу на клиент.
  • Грузить всё в одном загрузчике. Глобальное — в лейаут, специфичное — в страницу.

Best practices

  • Серверные ресурсы и секреты — только в +page.server.js.
  • Используйте переданный fetch внутри load — он оптимизирован для SSR.
  • Бросайте error(404, ...) для отсутствующих сущностей — SvelteKit покажет страницу ошибки.

Где брать данные: слои загрузки

На реальных проектах быстро становится ясно, что данные удобно загружать на разных уровнях. Глобальные вещи, нужные каждой странице, — кто сейчас залогинен, какие у него настройки, в какой теме показывать сайт — логично грузить один раз в лейаутном загрузчике +layout.server.js, и они станут доступны всем вложенным страницам. Специфичные для конкретной страницы данные — текст статьи, карточку товара, список комментариев — грузит её собственный load. Такое разделение избавляет от дублирующих запросов и держит код опрятным. Важно и правильно выбирать между универсальным и серверным загрузчиком: всё, что касается базы данных, секретных ключей или файловой системы, должно жить только в +page.server.js, иначе чувствительный код утечёт в браузер. Помните и про сериализуемость: данные из загрузчика при клиентской навигации передаются с сервера на клиент, поэтому возвращать оттуда функции или экземпляры классов нельзя. Освоив эти правила, вы будете загружать данные эффективно и безопасно.

Итог: load загружает данные до рендера и отдаёт их как проп data. +page.js работает на сервере и клиенте, +page.server.js — только на сервере, для безопасного доступа к ресурсам.

Проверьте себя
1. Что происходит со значением, которое возвращает функция load?
AОно логируется в консоль
BОно попадает в страницу как проп data до рендера
CОно сохраняется в localStorage
DОно игнорируется
2. Чем +page.server.js отличается от +page.js?
AНичем, это синонимы
B+page.server.js выполняется только на сервере — там безопасно обращаться к БД и секретам
C+page.server.js работает только в браузере
D+page.js нельзя использовать с load