Skip to main content

Документация

Введение permalink

Важное замечание

SvelteKit ещё в ранней стадии разработки, и некоторые вещи могут поменяться, когда мы дойдём до релиза 1.0. Этот документ всё ещё дорабатывается. Если у вас появятся вопросы, обратитесь за помощью в русскоязычный канал в Telegram.

Прочтите руководство по миграции для помощи при переходе с Sapper.

Что такое SvelteKit?

SvelteKit — это фреймворк для создания высокопроизводительных веб-приложений.

Создание приложения с учётом всех современных передовых практик — невероятно сложная задача. Эти практики включают в себя оптимизацию сборки, так что вы загружаете только минимальный необходимый код; поддержку работы без сети; предзагрузку данных страницы до того, как пользователь перейдет на следующую страницу; и настраиваемый рендеринг, который позволяет генерировать HTML на сервере или в браузере во время выполнения или во время сборки. Все эти скучные вещи SvelteKit сделает за вас, а вы можете сотредоточиться на творческой части проекта.

SvelteKit использует Vite вместе со Svelte plugin, что даёт множество возможностей и молниеносную разработку с горячей заменой модулей (HMR), где изменения вашего кода мгновенно отражаются в браузере.

Чтобы понять это руководство, знать Svelte не обязательно, но желательно. Если коротко, Svelte — это фреймворк, который компилирует ваши компоненты в высокооптимизированный ванильный JavaScript. Прочтите вводную статью в блоге Svelte и учебник Svelte, чтобы узнать о нём побольше.

Начало работы

Самый простой способ создать приложение SvelteKit — запустить команду npm init:

npm init svelte my-app
cd my-app
npm install
npm run dev

Первая команда создаст базовый проект в каталоге my-app, а также спросит о настройке некоторых базовых инструментов, вроде TypeScript. Обратитесь в раздел FAQ, чтобы узнать о некоторых особенностях настройки дополнительных инструментов. Остальные команды установят необходимые зависимости и запустят проект на localhost:3000.

Вот два наших основных принципа:

  • Каждая страница вашего приложения является компонентом Svelte
  • Вы создаёте новые страницы путём добавления компонентов в директорию src/routes. Они будут рендериться на сервере, так что время первой загрузки приложения для пользователя будет максимально быстрым, а уже затем клиентское приложение возьмёт управление на себя.

Попробуйте поредактировать файлы, чтобы понять, как все работает, и, возможно, даже не придется читать остальную часть этого руководства!

Настройка редактора

Мы рекомендуем использовать Visual Studio Code (он же VS Code) с расширением Svelte, но поддерживается также и множество других редакторов.

Веб-стандарты permalink

В этой документации вы увидите ссылки на стандартные Web API, на основе которого SvelteKit строит. Вместо того, чтобы заново изобретать колесо, мы используем платформу, что означает, что ваши существующие навыки веб-разработки применимы к SvelteKit. И наоборот, время, потраченное на изучение SvelteKit, поможет вам стать лучшим веб-разработчиком в другом месте.

Эти API доступны во всех современных браузерах и во многих небраузерных средах, таких как Cloudflare Workers, Deno и Vercel Edge Functions. Во время разработки и в адаптерах для сред на основе NodeJS (включая AWS Lambda) они доступны через полифиллы, где это необходимо (пока - Node быстро добавляет поддержку большего количества веб-стандартов).

В частности, вы освоитесь со следующим:

Fetch APIs

SvelteKit использует fetch для получения данных из сети. Он доступен в хуках и эндпоинтах, а также в браузере.

Специальная версия fetch доступна в функциях load для вызова эндпоинтов непосредственно во время рендеринга на стороне сервера, без вызова HTTP, сохраняя при этом учетные данные. (Чтобы сделать учетные данные в коде на стороне сервера за пределами load, вы должны явно передать заголовки cookie и/или authorization.) Это также позволяет делать относительные запросы, но для выборки на стороне сервера обычно требуется полный URL-адрес.

Помимо самой fetch, Fetch API включает в себя следующие интерфейсы:

Request

Экземпляр Request доступен в хуках и эндпоинтах как event.request. Он содержит полезные методы, такие как request.json() и request.formData(), например, для получения данных, которые были размещены на эндпоинте.

Response

Экземпляр Response возвращается из await fetch(...) . По сути, приложение SvelteKit - это машина для превращения Request в Response.

Headers

Интерфейс Headers позволяет читать входящие request.headers и устанавливать исходящие response.headers:

// @errors: 2461
/// file: src/routes/what-is-my-user-agent.js
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get(event) {
// log all headers
    console.log(...event.request.headers);

    return {
        body: {
            // retrieve a specific header
            userAgent: event.request.headers.get('user-agent')
        }
    };
}

URL APIs

URL-адреса представлены интерфейсом URL, который включает в себя полезные свойства, такие как origin и pathname (и, в браузере, hash). Этот интерфейс отображается в различных местах — event.url в хуках и эндпоинтах, $page.url в pages, from и to в [beforeNavigate и afterNavigate] (#moduli-$app-navigation) и так далее.

URLSearchParams

Где бы вы ни столкнулись с URL-адресом, вы можете получить доступ к параметрам запроса через url.searchParams, который является экземпляром URLSearchParams:

// @filename: ambient.d.ts
declare global {
    const url: URL;
}

export {};

// @filename: index.js
// ---cut---
const foo = url.searchParams.get('foo');

Web Crypto

Web Crypto API доступен через глобальный объект "crypto". Он используется внутри для заголовков Политика безопасности контента, но вы также можете использовать его для таких вещей, как генерация UUID:

const uuid = crypto.randomUUID();

Маршруты permalink

Сердцем SvelteKit является роутер основанный на файловой системе. Это означает, что структура вашего приложения определяется структурой файлов его исходников – в частности содержимым папки src/routes.

Можно указать другую директорию в файле конфигурации проекта.

Существует два типа маршрутов — страницы и эндпоинты.

Страницы обычно отдают HTML-код для отображения пользователю ( а также CSS и JavaScript, необходимые странице). По умолчанию они отрисовываются как на сервере, так и на клиенте, но это поведение можно настроить.

Эндпоинты запускаются только на сервере (или при сборке сайта, если используется предварительная отрисовка). Это то место, где можно выполнять запросы к базам данных или API с приватной авторизацией, а также вывести иные данные которые доступны на сервере. Страницы могут получать данные от эндпоинтов. По умолчанию эндпоинты возвращают ответ в формате JSON, но могут также возвращать данные в любых других форматах.

Страницы

Страницы — это компоненты Svelte, описанные в файлах .svelte(или любой файл с расширением, указанным в config.extensions). По умолчанию, когда пользователь впервые посещает приложение, ему будет отправлена сгенерированная на сервере версия запрошенной страницы, а также некоторый JavaScript, который выполняет 'гидратацию' страницы и инициализирует роутер на стороне клиента. С этого момента навигация на другие страницы будет полностью выполняться на стороне клиента обеспечивая очень быстрое перемещение, что типично для клиентских приложений, где некоторая часть разметки не требует перерисовки.

Имя файла определяет маршрут. Например, src/routes/index.svelte — корневой файл вашего сайта:

/// file: src/routes/index.svelte
<svelte:head>
	<title>Добро пожаловать!</title>
</svelte:head>

<h1>Приветствую вас на моём сайте!</h1>

<a href="/about">О сайте</a>

Файл с именем src/routes/about.svelte или src/routes/about/index.svelte будет соответствовать маршруту /about:

/// file: src/routes/about.svelte
<svelte:head>
	<title>О сайте</title>
</svelte:head>

<h1>Информация о сайте</h1>
<p>Это самый лучший сайт!</p>

<a href="/">Главная</a>

Обратите внимание, что SvelteKit использует элементы <a> для навигации между маршрутами, а не компонент <Link>, специфичный для платформы.

Динамические параметры задаются при помощи квадратных скобок [...]. Например, можно определить страницу, отображающую статью из блога, таким образом – src/routes/blog/[slug].svelte. Доступ к этим параметрам можно получить с помощью функции load или через хранилище page.

Маршрут может иметь несколько динамических параметров, например src/routes/[category]/[item].svelte или даже src/routes/[category]-[item].svelte. (Параметры "не жадные"; в неоднозначном случае, таком как x-y-z, category будет x, а item будет y-z.)

Эндпоинты

Эндпоинты - это модули, записанные в файлах .js (или .ts), которые экспортируют функции request handler, соответствующие HTTP методам. Они могут читать и записывать данные, доступные только на сервере (например, в базе данных или в файловой системе).

/// file: src/routes/items/[id].js
// @filename: ambient.d.ts
type Item = {};
declare module '$lib/database' {
	export const get: (id: string) => Promise<Item>;
}

// @filename: __types/[id].d.ts
import type { RequestHandler as GenericRequestHandler } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<{ id: string }, Body>;

// @filename: index.js
// ---cut---
import db from '$lib/database';

/** @type {import('./__types/[id]').RequestHandler} */
export async function get({ params }) {
	// `params.id` берётся из [id].js
 	const item = await db.get(params.id);

	if (item) {
		return {
			body: { item }
		};
	} 

	return {
 		status: 404
 	};
}

Не беспокойтесь об импорте $lib, мы перейдем к этому позже.

Тип функции get выше взят из файла ./[id].d.ts, сгенерированного SvelteKit (внутри вашего outDir с использованием опции rootDirs, который обеспечивает безопасность типа при доступе к params. Дополнительную информацию см. в разделе сгенерированные типы.

Цель обработчика запроса – вернуть объект { status, headers, body }, который будет ответом на полученный запрос, где status является кодом ответа HTTP:

  • 2xx — успешный ответ (по умолчанию 200)
  • 3xx — перенаправление (используется совместно с заголовком location)
  • 4xx — ошибка от клиента
  • 5xx — ошибка на сервере

Эндпоинты страницы

Если эндпоинт имеет то же имя файла, что и страница (за исключением расширения), страница получает свойства от эндпоинта - через fetch во время навигации на стороне клиента или через прямой вызов функции во время SSR.

Например страница src/routes/items/[id].svelte, может получить свойства из body в конечной точке выше:

/// file: src/routes/items/[id].svelte
<script>
	// свойство будет задано ответом от эндпоинта
	export let item;
</script>

<h1>{item.title}</h1>

Поскольку страница и маршрут имеют один и тот же URL-адрес, вам нужно будет включить заголовок accept: application/json, чтобы получить JSON из конечной точки, а не HTML со страницы. Вы также можете получить необработанные данные, добавив /__data.json к URL-адресу, например /items/[id]/__data.json.

Автономные эндпоинты

Как мы видели ранее, чаще всего эндпоинты связаны со страницей, для которой передают данные. Однако они могут существовать и отдельно от страниц. Автономные эндпоинты имеют большую гибкость в отношении типа поля body — кроме объекта, они также могут вернуть строку или Uint8Array.

Поддержка потоковых запросов и ответов на подходе.

Автономные эндпоинты доступны с расширением файла или без него:

filename endpoint
src/routes/data/index.json.js /data.json
src/routes/data.json.js /data.json
src/routes/data/index.js /data
src/routes/data.js /data

POST, PUT, PATCH, DELETE

Эндпоинты могут обрабатывать любой HTTP-метод, не только GET, путём экспорта соответствующей функции:

// @noErrors
export function post(event) {...}
export function put(event) {...}
export function patch(event) {...}
export function del(event) {...} // `delete` - зарезервированное слово

Как и get, все эти функции могут возвращать объект body, который будет передан странице в качестве значений её свойств. Ответы со статусом 4xx/5xx на GET-запросы приведут к отображению страницы с ошибкой. Аналогичные ответы на запросы других HTTP-методов этого не сделают, что позволяет, например, передать и отрисовать ошибки валидации формы.

/// file: src/routes/items.js
// @filename: ambient.d.ts
type Item = {
	id: string;
};
type ValidationError = {};

declare module '$lib/database' {
	export const list: () => Promise<Item[]>;
	export const create: (request: Request) => Promise<[Record<string, ValidationError>, Item]>;
}

// @filename: __types/items.d.ts
import type { RequestHandler as GenericRequestHandler } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<{}, Body>;


// @filename: index.js
// ---cut---
import * as db from '$lib/database'; 

/** @type {import('./__types/items').RequestHandler} */
export async function get() {
 	const items = await db.list();
	return {
		body: { items }
	};
}

/** @type {import('./items').RequestHandler} */
export async function post({ request }) {
	const [errors, item] = await db.create(request);

	if (errors) {
		// возвращаем ошибки валидации
		return {
			status: 400,
			body: { errors }
		};
	}
	// перенаправляем на страницу новой штуки
	return {
		status: 303,
		headers: {
			location: `/items/${item.id}`
		}
	};
}
/// file: src/routes/items.svelte
<script>
	// У страницы всегда есть доступ к свойствам из `get`...
	export let items;

	// ...также добавляются свойства из `post`, если страница  
	// отрисовывается по POST-запросу, например после
	// формы ниже
	export let errors;
</script>

{#each items as item}
	<Preview item={item}/>
{/each}

<form method="post">
	<input name="title">

	{#if errors?.title}
		<p class="error">{errors.title}</p>
	{/if}

	<button type="submit">Создать штуку</button>
</form>

Получение данных запроса

Объект request является экземпляром стандартного класса Request, поэтому получить данные из тела запроса не составит труда:

// @filename: ambient.d.ts
declare global {
	const create: (data: any) => any;
}

export {};

// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function post({ request }) {
	const data = await request.formData(); // или .json(), или .text()
	
	await create(data);
 	return { status: 201 };
}

Эндпоинты могут устанавливать Cookie, возвращая объект заголовков с set-cookie. Чтобы установить несколько Cookie одновременно, верните массив:

// @filename: ambient.d.ts
const cookie1: string;
const cookie2: string;

// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get() {
	return {
		headers: {
			'set-cookie': [cookie1, cookie2]
		}
	};
}

Переназначение HTTP методов

HTML-формы поддерживают только методы GET и POST. Вы можете указать другие допустимые методы, например PUT и DELETE, указав их в файле конфигурации, а затем добавлять параметр _method=МЕТОД (укажите нужный метод) в аттрибуте формы action:

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		methodOverride: {
			allowed: ['PUT', 'PATCH', 'DELETE']
		}
	}
};

export default config;
<form method="post" action="/todos/{id}?_method=PUT">
	<!-- элементы формы -->
</form>

Использование нативного поведения <form> гарантирует, что ваше приложение продолжит работать при сбое или отключении JavaScript.

Приватные модули

Файлы и каталоги, чьи имена начинаются с _ или . (кроме .well-known) по умолчанию являются приватными, т.е. они не создают маршруты (но могут быть импортированы файлами, которые это делают). В конфигурации проекта с помощью опции routes можно указать, какие модули считать приватными, а какие будут создавать маршруты.

Расширенная маршрутизация

Rest-параметры

Если количество сегментов маршрута неизвестно, вы можете использовать синтаксис rest - например, вы можете реализовать средство просмотра файлов GitHub таким образом...

/[org]/[repo]/tree/[branch]/[...file]

И в данном случае запрос для маршрута /sveltejs/kit/tree/master/documentation/docs/01-routing.md будет преобразован в следующие параметры, доступные на этой странице:

// @noErrors
{
	org: 'sveltejs',
	repo: 'kit',
	branch: 'master',
	file: 'documentation/docs/01-routing.md'
}

src/routes/a/[...rest]/z.svelte будет соответствовать /a/z (т.е. параметра вообще нет), а также /a/b/z и /a/b/c/z и так далее. Убедитесь, что значение параметра rest является допустимым, например, с помощью сопоставления.

Сопоставление

Маршрут, такой как src/routes/archive/[page], будет соответствовать /archive/3, но он также будет соответствовать /archive/potato. Мы этого не хотим. Вы можете убедиться, что параметры маршрута правильно сформированы, добавив matcher, который принимает строку параметров ("3" или "potato") и возвращает true, если он действителен - в каталог params...

/// file: src/params/integer.js
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function validate(param) {
	return /^\d+$/.match(param);
}

...и расширение ваших маршрутов:

-src/routes/archive/[page]
+src/routes/archive/[page=integer]

Если путь не совпадает, SvelteKit попытается соответствовать другим маршрутам (используя порядок сортировки, указанный ниже), прежде чем в конечном итоге вернуть 404.

Сопоставления запускаются как на сервере, так и в браузере.

Сортировка

Это нужно, чтобы несколько маршрутов соответствовали данному пути. Например, каждый из этих маршрутов будет соответствовать /foo-abc:

src/routes/[...catchall].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/foo-[c].svelte

SvelteKit должен знать, какой маршрут запрашивается. Для этого он сортирует их по следующим правилам...

  • Более конкретные маршруты имеют более высокий приоритет
  • Автономные эндпоинты имеют более высокий приоритет, чем страницы с той же спецификой
  • Параметры в сопоставлении маршрутов с ([name=type]) имеют более высокий приоритет, чем параметры без ([name])
  • Rest parameters имеют наименьшее приоритет
  • Ties разрешаются в алфавитном порядке

...Результат этого порядка – /foo-abc вызовет src/routes/foo-[bar].svelte, а не менее конкретный маршрут:

src/routes/foo-[c].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/[...catchall].svelte

Макеты permalink

До сих пор мы рассматривали страницы как полностью автономные компоненты — при переходе между страницами существующий компонент уничтожался, а новый занимал его место.

Но во многих приложениях есть элементы, которые должны быть видны на каждой странице, такие как навигация или подвал. Вместо того, чтобы повторять их на каждой странице, мы можем использовать компоненты макета.

Чтобы создать макет, который будет применяться к каждой странице приложения, создайте файл с именем src/routes/__layout.svelte. По умолчанию макет (SvelteKit использует такой, если не найдет этого файла) выглядит следующим образом:

<slot></slot>

Мы можем добавить любую разметку, стили и поведение, которые мы хотим. Единственное требование — компонент должен иметь <slot> для содержимого страницы. Например, давайте добавим панель навигации:

/// file: src/routes/__layout.svelte
<nav>
	<a href="/">Главная</a>
	<a href="/about">О сайте</a>
	<a href="/settings">Настройки</a>
</nav>

<slot></slot>

Если мы создадим страницы для /, /about и /settings...

/// file: src/routes/index.svelte
<h1>Главная</h1>
/// file: src/routes/about.svelte
<h1>О сайте</h1>
/// file: src/routes/settings.svelte
<h1>Настройки</h1>

...навигация всегда будет видна, и переход между тремя страницами приведёт только к замене содержимого элемента <h1>.

Вложенные макеты

Предположим, что у нас не просто одна страница /settings, а есть и вложенные страницы, вроде /settings/profile и /settings/notifications с общим подменю (для реального примера см. github.com/settings).

Мы можем создать макет, который применяется только к страницам, расположенным ниже /settings (при этом останется и корневой макет с навигацией):

/// file: src/routes/settings/__layout.svelte
<h1>Настройки</h1>

<div class="submenu">
	<a href="/settings/profile">Профиль</a>
	<a href="/settings/notifications">Уведомления</a>
</div>

<slot></slot>

Именованные макеты

Некоторым частям вашего приложения может понадобиться что-то отличное от макета по умолчанию. В этих случаях можно создать именованные макеты...

/// file: src/routes/__layout-foo.svelte
<div class="foo">
	<slot></slot>
</div>

...а затем используйте их, ссылаясь на имя макета (foo, в примере выше) в имени файла:

/// file: src/routes/my-special-page@foo.svelte
<h1>I am inside __layout-foo</h1>

Область применения

Именованные макеты могут быть созданы на любой глубине и будут применяться к любым компонентам в том же поддереве. Например, __layout-foo будет применяться к /x/one и /x/two, но не /x/three или /four:

src/routes/
├ x/
│ ├ __layout-foo.svelte
│ ├ one@foo.svelte       # ✅ page has `@foo`
│ ├ two@foo.svelte       # ✅ page has `@foo`
│ └ three.svelte         # ❌ page does not have `@foo`
└ four@foo.svelte        # ❌ page has `@foo`, but __layout-foo is not 'in scope'

Цепи наследования

Макеты сами могут наследовать от именованных макетов, из того же каталога или родительского каталога. Например, x/y/__layout@root.svelte является макетом по умолчанию для /x/y (что означает /x/y/one, /x/y/two и /x/y/three наследуют от него), потому что у него нет имени. Поскольку он указывает @root, он унаследует непосредственно от ближайшего __layout-root.svelte, пропуская __layout.svelte и x/__layout.svelte.

src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root.svelte

В случае, когда __layout-root.svelte содержит только <slot />, это фактически означает, что можно 'сбросить' на пустой макет для любой страницы или вложенного макета в приложении, добавив @root.

Если родитель не указан, макет унаследует от ближайшего макета по умолчанию (т.е. безымянного) макета above в дереве. В некоторых случаях полезно, чтобы именованный макет унаследовал от макета по умолчанию наряду с ним в дереве, например, __layout-root.svelte, наследующий от __layout.svelte. Можно сделать это, явно указав @default, разрешив /x/y/one и братьям и сестрам использовать макет приложения по умолчанию без использования x/__layout.svelte:

src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
-└ __layout-root.svelte
+└ __layout-root@default.svelte

default является зарезервированным именем - другими словами, нельзя назвать файл __layout-default.svelte.

Страницы ошибок

Если страница не смогла загрузиться (см Загрузка данных), SvelteKit отобразит страницу ошибки. Вы можете настроить вид этой страницы, создав компонент __error.svelte рядом с вашим макетом и страницами:

Например, если не удалось загрузить src/routes/settings/notifications/index.svelte, SvelteKit отрисует src/routes/settings/notifications/__error.svelte в том же макете, если он существует. В противном случае он отрисует src/routes/settings/__error.svelte в родительском макете или src/routes/__error.svelte в корневом макете.

В SvelteKit есть страница ошибок по умолчанию, если он не найдет файла src/routes/__error.svelte, но рекомендуется сделать свою.

Если в компоненте__error.svelte есть функция load, она будет вызываться со свойствами error и status:

<script context="module">
	/** @type {import('@sveltejs/kit').Load} */
	export function load({ error, status }) {
		return {
			props: {
				title: `${status}: ${error.message}`
			}
		};
	}
</script>

<script>
	export let title;
</script>

<h1>{title}</h1>

Макеты также имеют доступ к error и status через хранилище страниц

Во избежание того, чтобы пользователям стала доступна чувствительная информация, текст ошибок будет очищен от технических подробностей в продакшн режиме работы приложения.

404s

Вложенные страницы ошибок отображаются только тогда, когда возникает ошибка при рендеринге определенной страницы. В случае запроса, который не соответствует ни одному существующему маршруту, SvelteKit вместо этого отобразит общий 404. Например, учитывая эти маршруты...

src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte

...Файл marx-brothers/__error.svelte не будет отображаться, если вы посетите /marx-brothers/karl. Если вы хотите отобразить вложенную страницу ошибки, вы должны создать маршрут, соответствующий любому запросу /marx-brothers/*, и вернуть из него 404:

src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
+│ ├ [...path].svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
/// file: src/routes/marx-brothers/[...path].svelte
<script context="module">
/** @type {import('./__types/[...path]').Load} */
export function load({ params }) {
	return {
		status: 404,
		error: new Error(`Not found: /marx-brothers/${params.path}`)
	};
}
</script>

Загрузка данных permalink

Компонент, определяющий страницу или макет, может экспортировать функцию load, которая запускается до создания компонента. Эта функция выполняется как во время рендеринга на стороне сервера, так и в клиенте и позволяет извлекать данные и манипулировать ими до рендеринга страницы, что позволяет обойтись без индикаторов загрузки на странице.

Функция load может не понадобиться, если данные для страницы поставляются с её эндпоинта. Это полезно, когда нужно больше гибкости, например, для загрузки данных с внешнего API, которая может выглядеть так:

/// file: src/routes/blog/[slug].svelte
<script context="module">
	/** @type {import('./__types/[slug]').Load} */
	export async function load({ params, fetch, session, stuff }) {
		const url = `https://cms.example.com/article/${params.slug}.json`;
 		const response = await fetch(url);

		return {
			status: response.status,
 			props: {
 				article: response.ok && (await response.json())
 			}
		};
	}
</script>

Обратите внимание на <script context="module"> — это необходимо, потому что load выполняется до визуализации компонента. Код для каждого экземпляра компонента должен быть размещен во втором теге <script>.

Как и в случае с эндпоинтами, страницы могут импортировать сгенерированные типы - ./[slug] в приведенном выше примере - чтобы убедиться, что params правильно набраны.

load в SvelteKit является эквивалентом функциям getStaticProps или getServerSideProps в Next.js или asyncData в Nuxt.js, за исключением того, что она работает как на сервере, так и на клиенте. В приведенном выше примере, если пользователь нажимает на ссылку на эту страницу, данные будут загуржены с cms.example.com, не проходя через наш сервер.

Функция load получает в аргументах метод fetch, который имеет следующие специальные свойства:

  • имеет доступ к файлам cookie на сервере
  • может делать запросы к собственным эндпоинтам приложения без выполнения HTTP-запроса
  • при использовании делает копию ответа и встраивает её в страницу при первом запросе для гидратации

load может применяться только в компонентах страниц и макетов (но не в компонентах, которые они импортируют) и по умолчанию работает как на сервере, так и в браузере.

Код, который вызывается внутри функции load:

  • должен использовать только свой метод fetch, а не нативный fetch
  • не должен ссылаться на window, document или любые другие объекты, специфичные для браузера
  • не должен содержать каких-либо ключей для API или иных секретов, которые будут доступны клиенту, а вместо этого вызывать эндпоинт, который использует любые необходимые секреты

Рекомендуется не хранить состояние каждого запроса в глобальных переменных, а вместо этого использовать их только для межсекторальных проблем, таких как кэширование и хранение подключений к базе данных.

Мутирование любого общего состояния на сервере повлияет на всех клиентов, а не только на текущего.

Получаемые значения

Функция load получает объект, содержащий 8 полей — url, params, props, fetch, session, stuff, status, и error. Функция load является реактивной и будет повторно запущена при изменении значений её параметров, но только в том случае, если они используются в теле функции. В частности, если в функции используются url, session или stuff, она будут повторно запущена всякий раз, когда их значения изменятся. Также это произойдет при изменении любых отдельных свойств объекта params.

Обратите внимание, что деструктурирование параметров в объявлении функции уже означает их использование в функции.

url

url - это экземпляр URL, содержащий такие свойства, как origin, hostname, pathname и searchParams (который содержит разобранную строку запроса в виде объекта URLSearchParams). url.hash недоступен во время load, так как он недоступен на сервере.

В некоторых средах этот параметр получается из заголовков запроса во время рендеринга на стороне сервера.Если вы используете adapter-node, например, вам может потребоваться настроить адаптер, чтобы URL был правильным.

params

params получается из url.pathname и имени файла маршрута.

Например, для имени файла маршрута src/routes/a/[b]/[...c] и значении url.pathname равным /a/x/y/z, объект params будет выглядеть следующим образом:

{
	"b": "x",
	"c": "y/z"
}

props

Если страница, которую вы загружаете, имеет эндпоинт, то возвращаемые из него данные для свойств страницы доступны внутри функции load как объект props. Для компонентов макета и страниц без эндпоинтов props будет пустым объектом.

fetch

fetch эквивалентен родному веб-API fetch, с несколькими дополнительными функциями:

  • его можно использовать для выполнения авторизованных запросов на сервере, так как он наследует заголовки cookie и authorization для запроса страницы
  • он может делать относительные запросы на сервере (обычно fetch требует URL-адрес с источником при использовании в контексте сервера)
  • запросы на эндпоинты поступают непосредственно в функцию обработчика во время рендеринга на стороне сервера, без накладных расходов на HTTP-вызов
  • во время рендеринга на стороне сервера ответ будет захвачен и встроен в визуализированный HTML
  • во время гидратации ответ будет считываться из HTML, гарантируя согласованность и предотвращая дополнительный сетевой запрос

Cookie будут переданы только в том случае, если целевой хост совпадает с хостом текущего приложения SvelteKit или его поддоменом.

session

session может использоваться для передачи данных от сервера в текущий запрос, например идентификатор авторизованного пользователя. По умолчанию значение равно undefined. См. getSession в разделе Хуки, чтобы узнать как использовать этот объект.

stuff

Объект stuff передаётся из макетов дочерним макетам и страницам, и может содержать то, что нужно сделать доступным ниже. Для корневого компонента __layout.svelte он будет равен {}, но если функция load этого компонента возвращает объект со свойством stuff, оно будет доступно для всех функций load из дочерних компонентов.

status

status - это код состояния HTTP при отображении страницы ошибки или null в противном случае.

error

error - это ошибка, которая была выдана (или возвращена из предыдущей load) при отображении страницы ошибки или null в противном случае.

Возвращаемые значения

Если из load возвращается промис, страница не будет отображаться, пока промис не исполнится. У возвращаемого объекта может быть несколько свойств, все они опциональны:

status, error, redirect и cache игнорируются при отображении страниц ошибок.

status

Код ответа HTTP сервера. Если возвращается error – он должен быть из диапазонов 4xx или 5xx; при возвращении свойства redirect код нужно установить в диапазон 3xx. По умолчанию код ответа равен 200.

error

Если при выполнении функции load что-то пошло не так, поместите в это свойство объект Error или просто строку, описывающую проблему, не забыв указать код ответа в свойстве status равным числу в диапазонах 4xx или 5xx.

redirect

Если страница должна перенаправить пользователя на другую страницу (например, эта страница устарела, или пользователь должен сначала авторизоваться или ещё что-то), поместите в это свойство строку, содержащую путь по которому нужно переместить пользователя. Не забудьте указать код ответа в свойстве status равным числу в диапазоне 3xx.

Строка redirect должна быть правильно закодированным URI. Допустимы как абсолютные, так и относительные URI.

cache

cache: {
	"maxage": 300,
	"private": false
}

Чтобы кэшировать страницы, верните объект cache, содержащий свойство maxage, установленное в number, описывающий максимальный возраст страницы в секундах. При необходимости также включите свойство boolean private, указывающее, должен ли результирующий заголовок Cache-Control быть private или public (это означает, что он может быть кэширован CDN в дополнение к отдельным браузерам).

Если cache.private является undefined, SvelteKit установит его автоматически, используя следующую эвристику: если функция load делает fetch учетных данных или страница использует session, она считается частной.

Это свойство может быть использовано только для страниц, но не для макетов.

props

Если функция load возвращает объект props, то он будет передан компоненту как его свойства, когда он будет отрисован.

stuff

Поля из этого объекта будут добавлены к существующим полям объекта stuff, который будет предан в функции load всех дочерних компонентов страниц и макетов.

Полный объект stuff можно использовать в компонентах используя $page.stuff из хранилища страницы. Таким образом для страниц обеспечивается механизм передачи данных "вверх", в макеты.

dependencies

Массив строк, представляющих URL-адреса, от которых зависит страница, которые впоследствии могут быть использованы с invalidate, чтобы вызвать повторный запуск load. Вам нужно добавить их в зависимости, только если вы используете пользовательский API-клиент; URL-адреса, загруженные с предоставленной функцией fetch, добавляются автоматически.

URL-адреса могут быть абсолютными или относительно загружаемой страницы и должны быть [закодированы] (https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding).

Хуки permalink

Необязательный файл src/hooks.js (или src/hooks.ts, или src/hooks/index.js) может экспортировать четыре функции, которые будут запускаться на сервере — handle, handleError, getSession и externalFetch.

Расположение этого файла может быть настроено в опции config.kit.files.hooks

handle

Эта функция запускается каждый раз, когда сервер SvelteKit получает request и формирует response. Это может происходить во время работы приложения или во время предварительной отрисовки. Она получает объект event, представляющий запрос, и функцию resolve, которая вызывает маршрутизатор SvelteKit и генерирует ответ (отображает страницу или вызывает эндпоинт). Это позволяет изменять заголовки или тело ответов или полностью обойти SvelteKit (например, для программной реализации эндпоинтов).

/// file: src/hooks.js
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
	if (event.url.pathname.startsWith('/custom')) {
		return new Response('custom response');
	}

	const response = await resolve(event);
	return response;
}

Запросы статический ресурсов, включая предварительно отрисованные страницы, не обрабатываются SvelteKit.

Если не реализовано, по умолчанию используется ({ event, resolve }) => resolve(event). Чтобы добавить пользовательские данные к запросу, который передается конечным точкам, заполните объект event.locals, как показано ниже.

/// file: src/hooks.js
// @filename: ambient.d.ts
type User = {
	name: string;
}

declare namespace App {
 	interface Locals {
 		user: User;
 	}
 	interface Platform {}
 	interface Session {}
 	interface Stuff {}
}

const getUserInformation: (cookie: string | null) => Promise<User>;

// declare global {
// 	const getUserInformation: (cookie: string) => Promise<User>;
// }

// @filename: index.js
 // ---cut---
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
 	event.locals.user = await getUserInformation(event.request.headers.get('cookie'));

	const response = await resolve(event);
	response.headers.set('x-custom-header', 'potato');

	return response;
}

Можно добавить вызов нескольких функций handle используя хелпер sequence.

В resolve можно передать второй необязательный параметр, который даёт больше контроля над тем, как будет отображаться ответ. Этот параметр является объектом, который может иметь следующие поля:

  • ssr: boolean (default true) - если false, отображает пустую страницу 'shell' вместо рендеринга на стороне сервера
  • transformPage(opts: { html: string }): string — применяет пользовательские преобразования к HTML
/// file: src/hooks.js
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
 	const response = await resolve(event, {
 		ssr: !event.url.pathname.startsWith('/admin'),
 		transformPage: ({ html }) => html.replace('old', 'new')
 	});

 	return response;
}

Отключение отрисовки на стороне сервера фактически превращает приложение SvelteKit в одностраничное приложение или SPA. В большинстве ситуаций это не рекомендуется (см. термин SSR). Решите, действительно ли уместно его полностью отключать или сделайте это выборочно, а не для всех запросов.

handleError

Если ошибка возникает во время рендеринга, эта функция будет вызвана с параметрами error и event. Это позволяет отправлять данные в сервис отслеживания ошибок или форматировать сообщение для вывода в консоли.

Если, в режиме разработки, возникает синтаксическая ошибка в коде Svelte, будет добавлен параметр frame, указывающий на местоположение ошибки.

Если данный хук не задан, SvelteKit отобразит ошибку с форматированием по умолчанию.

/// file: src/hooks.js
// @filename: ambient.d.ts
const Sentry: any;

// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').HandleError} */
export async function handleError({ error, event }) {
	// пример интеграции с https://sentry.io/
	Sentry.captureException(error, { event });
}

handleError вызывается только в случае, если ошибка не была поймана ранее в коде. Также хук не вызывается, когда страницы и эндпоинты явно отвечают кодами состояния 4xx и 5xx.

getSession

Эта функция принимает объект event и возвращает объект session, который доступен на клиенте и, следовательно, должен быть безопасным для предоставления пользователям. Он запускается всякий раз, когда SvelteKit выполняет рендеринг страницы на сервере.

Если функция не задана, объект сессии будет равен {}.

/// file: src/hooks.js
// @filename: ambient.d.ts
declare namespace App {
	interface Locals {
		user: {
			name: string;
			email: string;
			avatar: string;
			token: string;
		}
	}
	interface Session {
		user?: {
			name: string;
			email: string;
			avatar: string;
		}
	}
}

type MaybePromise<T> = T | Promise<T>;

// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
 	return event.locals.user
 		? {
			user: {
				// передайте только поля нужные на клиенте —
				// исключите любые другие поля объекта user
				// вроде токенов, паролей и т.п.
				name: event.locals.user.name,
				email: event.locals.user.email,
				avatar: event.locals.user.avatar
			}
 		  }
 		: {};
}

Объект session должен быть сериализуемым, то есть не должен содержать вещей вроде функций или классов, только встроенные в JavaScript типы данных.

externalFetch

Эта функция позволяет изменять (или заменять) запрос fetch для внешнего ресурса внутри функции load, которая выполняется на сервере (или во время предварительной отрисовки).

Например, когда есть страница с функцией load, которая на клиенте делает запрос на публичный URL-адрес(например https://api.yourapp.com) какого-либо внутреннего сервиса, то во время отрисовки на сервере имеет смысл выполнить запрос к сервису локально, минуя прокси-серверы и балансировщики.

/** @type {import('@sveltejs/kit').ExternalFetch} */
export async function externalFetch(request) {
	if (request.url.startsWith('https://api.yourapp.com/')) {
	// копируем исходный запрос, но заменяем URL-адрес
	request = new Request(
		request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
		request
	);
}
	return fetch(request);
}

Модули permalink

В SvelteKit есть несколько модулей, которые доступны в приложении.

$app/env

/// <reference types="@sveltejs/kit" />
// ---cut---
import { amp, browser, dev, mode, prerendering } from '$app/env';
  • amp равен либо true, либо false в зависимости от соответствующего значения в конфигурации проекта
  • browser будет равен true или false если приложение запущено соответственно в браузере или на сервере
  • dev равен true в режиме разработки, false в рабочем режиме
  • mode - это Vite mode, по-умолчанию development в режиме разработки или production во время сборки, если иное не настроено в config.kit.vite.mode.
  • prerendering равен true во время предварительной отрисовки, иначе false

$app/navigation

/// <reference types="@sveltejs/kit" />
// ---cut---
import {
	afterNavigate,
 	beforeNavigate,
 	disableScrollHandling,
 	goto,
 	invalidate,
 	prefetch,
 	prefetchRoutes
 } from '$app/navigation';
  • afterNavigate(({ from, to }: { from: URL, to: URL }) => void) - функция жизненного цикла, которая запускается при первоначальной отрисовке компонента, а также при каждой последующей навигации, пока компонент остается в отрисованным.
  • beforeNavigate(({ from, to, cancel }: { from: URL, to: URL | null, cancel: () => void }) => void) — функция, которая запускается всякий раз, когда происходит навигация, будь то нажатие на ссылку, вызов goto или перемещение по истории браузера. Также она будет запущена и при переходе на внешние сайты. Если пользователь закрывает страницу, то в to будет значение null. Вызов cancel остановит выполнение перехода.
  • disableScrollHandling запретит SvelteKit применить его обычное управление прокруткой страницы, если вызывается когда страница обновляется после перехода (например, в onMount или действии). Лучше избегать использования этой функции, чтобы не дезориентировать пользователей.
  • goto(href, { replaceState, noscroll, keepfocus, state }) возвращает Promise, который резолвится при навигации SvelteKit к указанному href (ошибка в навигации отклоняет промис). Второй аргумент является необязательным:
    • replaceState (boolean, по умолчанию false) Если true, заменит текущую запись history, а не создаст новую через pushState
    • noscroll (boolean, по умолчанию false) Если true, браузер сохранит свое положение прокрутки, а не прокрутит в верхнюю часть страницы после навигации
    • keepfocus (boolean, по умолчанию false) Если true, текущий сфокусированный элемент сохранит фокус после навигации. В противном случае фокус будет сброшен
    • state (объект, по умолчанию {}) Состояние новой/обновленной записи истории
  • invalidate(href) перезапускает все функции load, которые нужны для текущей активной страницы для повторной загрузки необходимых ресурсов. Возвращает объект Promise, который разрешается, когда страница обновится новыми данными.
  • prefetch(href) программно выполняет упреждающую загрузку указанной страницы, что означает: а) обеспечение полной загрузки кода для страницы и б) вызов метода load страницы с соответствующими параметрами. Это поведение, аналогично случаю, когда пользователь касается на сенсорном экране или проводит курсором над элементом <a> с установленным атрибутом sveltekit:prefetch. Если следующий переход будет по пути href, то будет использовано значение, которое вернула функция load, что сделает перемещение мгновенным. Возвращает объект Promise, который разрешается, когда упреждающая загрузка будет завершена.
  • prefetchRoutes(routes) — программно выполняет упреждающую загрузку кода для маршрутов, которые ещё не были загружены до этого. Обычно используется для ускорения переходов по нижестоящим маршрутам. Если не передавать аргументов, то будут предзагружены все маршруты, но можете указать маршруты по любому подходящему пути, например, /about (для src/routes/about.svelte) или /blog/* (для src/routes/blog/[slug].svelte). В отличие от prefetch не вызывает функцию load для каждой из загружаемых страниц. Возвращает объект Promise, который разрешается, когда упреждающая загрузка всех маршрутов будет завершена.

$app/paths

/// <reference types="@sveltejs/kit" />
// ---cut---
import { base, assets } from '$app/paths';
  • base — строка с путём, относительно корня (т.е. начинается с /), которая соответствует параметру config.kit.paths.base в конфигурации проекта
  • assets — путь от корня или абсолютный путь который соответствует параметру config.kit.paths.assets (после его разрешения относительно base)

Если указано значение config.kit.paths.assets, во время выполнения svelte-kit dev или svelte-kit preview оно будет подменяться на '/_svelte_kit_assets', так как статические ресурсы ещё не размещены по их окончательному URL-адресу.

$app/stores

/// <reference types="@sveltejs/kit" />
// ---cut---
import { getStores, navigating, page, session, updated } from '$app/stores';

Эти хранилища зависят от контекста, так как они добавляются в контекст корневого компонента приложения. Это значит, что хранилища session и page будут уникальны для каждого запроса на сервер и не будут предоставлять одну и ту же информацию в нескольких запросах сразу. Поэтому можно безопасно хранить в session данные конкретного пользователя.

По этой причине доступ к хранилищу можно получить только во время инициализации компонента, как и в случае с любой функцией, которая использует метод getContext внутри.

  • getStores — это удобная функция-оболочка вокруг getContext, которая возвращает { navigating, page, session, updated }. Её необходимо вызывать на верхнем уровне или синхронно во время инициализации компонента или страницы.

Хранилища сами определяют нужный контекст, когда выполняется подписка на них, что означает, что вы можете импортировать и использовать их непосредственно в компонентах без лишней обвязки. Тем не менее, их его всё ещё нужно вызывать синхронно при инициализации компонента или страницы, когда не используется префикс $. Вместо этого используйте getStores, чтобы безопасно асинхронно выполнить .subscribe.

  • navigating - это хранилище. В процессе перехода при навигации его значением становится объект { from, to }, где from и to являются экземплярами URL. Когда переход завершается, его значение возвращается к null.
  • page содержит объект с текущими url, params, stuff, status и error.
  • session – хранилище, начальное значение которого получается из функции getSession. Значение в хранилище можно изменять, но эти изменения не будут сохранены на сервере – при необходимости это нужно имплементировать самостоятельно.
  • updated - это хранилище, начальное значение которого равно false. Если в конфигурации задан version.pollInterval, SvelteKit будет периодически проверять новую версию приложения на сервере и как только обнаружит её, обновит значение хранилища до true. Вызов метода updated.check() принудительно проверит новую версию на сервере, независимо от настроек опроса.

$lib

Это простой псевдоним для директории src/lib, или иной директории указанной в config.kit.files.lib. Он позволит обращаться к общим компонентам и утилитам без использования множества ../../../../ в путях импорта.

$service-worker

Этот модуль доступен только в сервис-воркерах.

/// <reference types="@sveltejs/kit" />
// ---cut---
import { build, files, timestamp } from '$service-worker';
  • build – массив строк URL-путей до файлов сгенерированных Vite, используется для кеширования при помощи функции cache.addAll(build)
  • files - это массив строк URL, представляющих файлы в вашем каталоге static или любой другой каталог, указанный config.kit.files.assets. Вы можете настроить, какие файлы включаются из каталога static, используя config.kit.serviceWorker.files
  • timestamp – результат вызова функции Date.now() во время сборки. Полезно для генерации уникальных имён для кешей внутри сервис-воркера, что позволит инвалидировать устаревшие кеши у клиентов при запуске новой версии приложения.

@sveltejs/kit/hooks

Этот модуль содержит хелпер-функцию sequence для создания последовательности из нескольких вызовов в handle.

/// file: src/hooks.js
/// <reference types="@sveltejs/kit" />
// ---cut---
import { sequence } from '@sveltejs/kit/hooks';

/** @type {import('@sveltejs/kit').Handle} */
async function first({ event, resolve }) {
  console.log('первая пред-обработка');
 	const result = await resolve(event);
 	console.log('первая пост-обработка');
 	return result;
}

/** @type {import('@sveltejs/kit').Handle} */
async function second({ event, resolve }) {
  console.log('вторая пред-обработка');
 	const result = await resolve(event);
 	console.log('вторая пост-обработка');
 	return result;
}

export const handle = sequence(first, second);

Пример выше распечатает:

первая пред-обработка
вторая пред-обработка
вторая пост-обработка
первая пост-обработка

Сервис-воркеры permalink

Сервис-воркеры выступают в роли прокси-серверов, которые обрабатывают сетевые запросы внутри вашего приложения. Это позволяет сделать приложение, которое сможет работать в Offline-режиме, но даже если поддержка работы без сети не требуется(или она невозможна из-за особенностей работы приложения), то сервис-воркер может ускорить навигацию кешированием JS и CSS файлов приложения.

Если в проекте SvelteKit есть файл src/service-worker.js (или src/service-worker.ts, или src/service-worker/index.js) он будет собран в Vite и автоматически зарегистрирован. Вы можете отключить автоматическую регистрацию, если вам нужно зарегистрировать сервис-воркера со своей собственной логикой (например, запросить у пользователя обновление, настроить периодические обновления, использовать workbox и т. д.).

Вы можете изменить местоположение сервис-воркера и отключить автоматическую регистрацию в конфигурации вашего проекта.

Внутри сервис-воркера есть доступ к модулю $service-worker.

Файл сервис-воркера должен пройти через процесс сборки, поскольку браузеры ещё не поддерживают import в этом контексте. Кроме того сервис-воркер зависит от манифеста сборки клиентской части приложения. В следствие чего, сервис-воркеры работают только в рабочей сборке, но не в режиме разработки. Чтобы протестировать его работу локально, запустите проект командой svelte-kit preview.

Атрибуты ссылок permalink

sveltekit:prefetch

SvelteKit использует разделение кода, чтобы разбить приложение на небольшие фрагменты (по одному на маршрут), обеспечивая быстрое время запуска.

Для динамических маршрутов, таких как src/routes/blog/[slug].svelte, этого недостаточно. Чтобы отобразить сообщение в блоге, нужно получить для него данные, и мы не сможем этого сделать, пока не узнаем значение slug. В худшем случае это может вызвать задержку, поскольку браузер будет ждать данные от сервера.

Сгладить ситуацию можно предварительно собрав данные, добавив атрибут sveltekit:prefetch...

<a sveltekit:prefetch href="blog/what-is-sveltekit">Что такое SvelteKit?</a>

...который заставит SvelteKit запустить функцию load как только пользователь наведёт курсор мыши на ссылку или коснётся её на мобильном устройстве, вместо того, чтобы дожидаться события click, которое выполнит переход на страницу. Обычно это даст нам дополнительную пару сотен миллисекунд, что как раз является той разницей, которая существует между быстрым пользовательским интерфейсом, и тем, который кажется медленным.

Обратите внимание, что предварительная загрузка данных не будет работать, если значение router установлено в false.

Вы также можете программно вызвать prefetch из $app/navigation.

sveltekit:reload

По умолчанию среда выполнения SvelteKit перехватывает клики по элементам <a> и блокирует обычную навигацию браузера для относительных URL-адресов, соответствующих одному из маршрутов страниц. Иногда нужно сообщить SvelteKit, что определённые ссылки должны обрабатываться с помощью обычной навигации браузера. Примерами этого могут быть ссылка на другую страницу в вашем домене, которая не является частью вашего приложения SvelteKit, или ссылка на эндпоинт.

Добавление атрибута sveltekit:reload к ссылке...

<a sveltekit:reload href="path">Path</a>

... запустит навигацию браузера с перезагрузкой страницы при нажатии на ссылку.

Ссылки с атрибутом rel="external" получат такую же обработку. Кроме того, они будут проигнорированы во время пререндера.

sveltekit:noscroll

При переходе по внутренним ссылкам SvelteKit придерживается поведения навигации браузера по умолчанию: он изменяет положение прокрутки на 0,0, чтобы пользователь находился в самом верхнем левом углу страницы (если только ссылка не содержит #hash, тогда он перейдёт к элементу с соответствующим идентификатором).

В некоторых случаях такое поведение нежелательно. Добавление атрибута sveltekit:noscroll...

<a href="path" sveltekit:noscroll>Path</a>

... предотвратит прокрутку после перехода по ссылке.

События permalink

SvelteKit по команде sveltekit:start запускает пользовательские события на объекте window после гидратации приложения:

Возможно, вам не понадобится их использовать, но они могут быть полезны, например, в интеграционных тестах.

Адаптеры permalink

Прежде чем развернуть готовое приложение SvelteKit на сервере или сервисе, его необходимо адаптировать под то окружение, в котором оно будет работать. Адаптеры - это небольшие плагины, которые на вход принимают созданное приложение и на выходе генерируют приложение, подготовленное для развертывания в определенном окружении.

По умолчанию проекты настроены на использование @sveltejs/adapter-auto, который сам определяет окружение и выбирает соответствующий адаптер, где это возможно. Если же требуемая платформа пока не поддерживается, можно подключить один из адаптеров от сообщества или написать свой.

См. adapter-auto README для получения информации о добавлении поддержки новых окружений.

Поддерживаемые платформы

SvelteKit предлагает ряд официально поддерживаемых адаптеров.

Вы можете выполнить развертывание на следующих платформах с адаптером по умолчанию, adapter-auto:

Node.js

Чтобы создать простой Node-сервер, установите пакет @sveltejs/adapter-node и обновите svelte.config.js:

/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';

После этого svelte-kit build сгенерирует автономное приложение Node в директории build. Вы можете передать адаптерам параметры, например указать директорию для полученного приложения:

/// file: svelte.config.js
import adapter from '@sveltejs/adapter-node';

export default {
	kit: {
-		adapter: adapter()
+		adapter: adapter({ out: 'my-output-directory' })
	}
};

Статические сайты

Большинство адаптеров будут генерировать статический HTML для любых страниц, которые возможно предварительно отрисовать. В некоторых случаях, когда можно предварительно отрисовать всё приложение, используйте @sveltejs/adapter-static для генерации статического HTML кода для всех страниц. Полностью статический сайт может быть размещен на самых разных платформах и хостингах, включая GitHub Pages.

/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-static';

Также adapter-static можно использовать для создания одностраничных приложений (SPA), указав корневую страницу.

Вы должны убедиться, что trailingSlash настроен соответствующим образом для вашей среды. Если ваш хост не отображает /a.html при получении запроса на /a, вам нужно будет установить trailingSlash: 'always' для создания /a/index.html.

Контекст платформы

Некоторые адаптеры могут иметь доступ к дополнительной информации о запросе. Например, Cloudflare Workers может получить доступ к объекту env, содержащему пространства имен KV и т. д. Эта информация может быть передана как свойство platform в объекте RequestEvent, который используется в хуках и эндпоинтах. Ознакомьтесь с документацией нужного адаптера, чтобы узнать больше.

Адаптеры сообщества

Для других платформ существуют дополнительные адаптеры от сообщества. После установки соответствующего адаптера с помощью менеджера пакетов обновите svelte.config.js:

/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from 'svelte-adapter-[x]';

Создание адаптера

Мы рекомендуем скопировать и взять за основу адаптер для платформы, которая близка к нужной.

Пакеты адаптеров должны реализовывать следующий API, который создает Adapter:

// @filename: ambient.d.ts
const AdapterSpecificOptions = any;

// @filename: index.js
// ---cut---
/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
    const adapter = {
        name: 'adapter-package-name',
        async adapt(builder) {
          // имплементация адаптера
        }
    };

    return adapter;
}

Типы для Adapter и его параметры доступны в types/config.d.ts.

Есть ряд вещей, которые должны быть выполнены внутри метода adapt:

  • Очищает директорию готовой сборки
  • Записывает вывод SvelteKit с помощью builder.writeClient, builder.writePrerendered, builder.writeServer и builder.writeStatic
  • Создаёт код, который:
    • Импортирует Server из ${builder.getServerDirectory()}/index.js
    • Создаёт экземпляр приложения со сгенерированным методом builder.generateManifest({ relativePath }) манифестом.
    • Слушает запросы с платформы и преобразует их в стандартный Request, при необходимости вызывает функцию server.respond(request, { getClientAddress }) для создания Response и отвечает ей
    • Глобально настроит fetch для работы на целевой платформе. SvelteKit предоставляет хелпер @sveltejs/kit/install-fetch для платформ, которые могут использовать node-fetch
  • При необходимости, соберает модули приложения в единый бандл, чтобы избежать установки зависимостей на целевой платформе
  • Помещает статические файлы пользователя и сгенерированные JS/CSS в правильное место для целевой платформы

При возможности, мы рекомендуем помещать готовое приложение в директорию build/, а любые промежуточные данные в директории '.svelte-kit/' + имя_адаптера.

API адаптера может меняться до версии 1.0.

Параметры страницы permalink

По умолчанию SvelteKit сначала отрисовывает любой компонент на сервере и отправляет его клиенту в формате HTML. Затем он снова отрисует компонент в браузере, чтобы сделать его интерактивным в процессе, который называется гидратация. Поэтому необходимо следить, чтобы компоненты могли работать как на сервере, так и в браузере. В конце SvelteKit инициализирует клиентский роутер, который берет на себя последующие переходы между страниц.

Каждый из этих шагов можно контролировать как во всём приложении сразу, так и отдельно для каждой страницы. Обратите внимание, что все настройки, которые указываются для конкретных страниц, помещаются в блок script с атрибутом context="module" и применяются только к страницам, но не к макетам.

В случае конфликта глобальных настроек и настроек отдельной страницы, последние будут иметь приоритет.

router

В SvelteKit есть клиентский роутер, который отслеживает переходы (клик по ссылке или по кнопкам истории браузера) и обновляет содержимое страницы, при этом не происходит перезагрузки страницы, как при обычной навигации в браузере.

В некоторых случаях может потребоваться отключить клиентский роутер параметром browser.router в конфигурации приложения или для отдельной страницы, экспортировав router:

<script context="module">
	export const router = false;
</script>

Это отключит роутер для всех переходов с текущей страницы, даже если он уже используется в приложении.

hydrate

По умолчанию SvelteKit гидратирует полученный с сервера HTML, чтобы получить интерактивную страницу. Некоторым страницам совершенно не нужен JavaScript – например, различного рода посты в блоге или страницы 'О сайте'. В таких случаях можно отключить гидратацию при загрузке приложения глобальным параметром browser.hydrate в конфигурации или для конкретной страницы, экспортировав константу hydrate:

<script context="module">
	export const hydrate = false;
</script>

Если и hydrate и router будут оба равны false, SvelteKit вообще не добавит на страницу никакого JavaScript кода. Если рендеринг на стороне сервера отключен в handle, hydrate должен быть true, иначе содержимое не будет отображаться.

prerender

Иногда некоторые страницы приложения могут быть представлены в виде простого HTML-файла, созданного во время сборки. Эти страницы могут быть предварительно отрисованы выбранным адаптером.

Предварительная отрисовка происходит автоматически для любой страницы с аннотацией prerender:

<script context="module">
	export const prerender = true;
</script>

Кроме того, вы можете установить config.kit.prerender.default в true и предварительно отрисовать все, кроме страниц, которые явно помечены как not prerenderable:

<script context="module">
	export const prerender = false;
</script>

Если все ваше приложение подходит для предварительного рендеринга, вы можете использовать adapter-static, который выведет файлы, подходящие для использования с любым статическим веб-сервером.

Отрисовка начнется с корня приложения и будут сгенерированы HTML-файлы для всех найденных страниц, подходящих для пререндера. Каждая страница сканируется на предмет элементов <a>, которые указывают на другие страницы, которые тоже могут быть отрисованы - поэтому нет необходимости явно указывать какие именно страницы нужно обработать. При необходимости, список страниц, которые должны быть предварительно отрисованы, можно задать в параметре entries в разделе конфигурации prerender.

Когда не делать пререндер

Основное правило таково: для того, чтобы страница могла быть предварительно отрисована, любые два пользователя, попадающие на одну и ту же страницу приложения, должны получать с сервера одно и то же содержимое.

Не все страницы подходят для пререндеринга. Любое содержимое, которое отрисовано таким образом, видно всем пользователям. Конечно, можно получать персональные данные в onMount на такой странице, но это может ухудшить пользовательский опыт, поскольку придется дожидаться получения данных, наблюдая индикатор загрузки.

Обратите внимание, что предварительную отрисовка всё ещё можно сделать для приложения с динамическими маршрутами, как в нашем примере src/routes/blog/[slug].svelte. Адаптер adapter-static будет обрабатывать запросы к серверу внутри функций load, поэтому данные, поступающие из src/routes/blog/[slug].json.js тоже будут сохранены.

Во время предварительной отрисовки нет доступа к объекту url.searchParams. Если его необходимо использовать на странице, убедитесь, что обращение к нему происходит только в браузере (например, в функции onMount).

Конфликты маршрутов

Поскольку пререндер создаёт отражение всех маршрутов в виде файлового дерева, то невозможно иметь два эндпоинта, где возникает ситуация, что директория и файл в одном и том же месте будут иметь одинаковое имя. Например, src/routes/foo/index.js и src/routes/foo/bar.js будут пытаться создать файлы foo и foo/bar, что приведёт к ошибке.

По этой причине, рекомендуется всегда добавлять расширение к имени файла — например, src/routes/foo/index.json.js и src/routes/foo/bar.json.js будут сохранены как foo.json и foo/bar.json, которые не будут мешать друг другу.

Для маршрутов страниц этой проблемы не возникает, поскольку создаётся файл foo/index.html, а не foo.

Создание пакетов permalink

svelte-kit package в настоящее время является экспериментальным и не подпадает под действие правил семантического управления версиями. Несовместимые с обратной связью изменениями могут произойти в любом будущем выпуске.

Кроме создания web-приложений SvelteKit можно использовать также и для библиотек компонентов.

Содержимое папки src/routes является основой для приложения. А папка src/lib просто хранит файлы внутренних библиотек.

Библиотека компонентов в SvelteKit имеет точно такую же структуру папок, но src/lib становится основой библиотеки, а src/routesможет быть использована для документации или демо-сайта, показывающего работу библиотеки. Также можно использовать эту папку как "песочницу" во время разработки компонента.

Запуск команды svelte-kit package сгенерирует пакет в новой папке package (которую можно настроить), содержащий следующие файлы:

  • Все файлы из папки src/lib, если не указаны какие-либо параметры include/exclude. Компоненты Svelte будут предварительно обработаны, файлы TypeScript будут преобразованы в JavaScript.
  • Определения типов (файлыd.ts), которые генерируются для файлов Svelte, JavaScript и TypeScript. Для этого вам нужно установить typescript >= 4.0.0 и svelte2tsx >= 0.4.1. Определения типов размещаются рядом с их реализацией, рукописные файлы d.ts копируются как есть. Можно отключить генерацию этих файлов, но мы настоятельно рекомендуем не делать этого.
  • Файл package.json, скопированный из корня проекта, со всеми полями, кроме поля "scripts". Список зависимостей "dependencies" тоже будет скопирован, поэтому добавляйте пакеты, которые нужны для документации или демо-сайта, в поле "devDependencies". Также будут добавлены поля "type": "module" и "exports", если в исходном файле их нет.

Поле "exports" содержит файлы, которые будут доступны из модуля. По умолчанию сюда попадут все файлы из папкиsrc/lib, только если их имя(или имя папки, в которых они содержатся) не начинаются с символа нижнего подчёркивания. Это поведение можно изменить. Если имеется файл src/lib/index.js или src/lib/index.svelte, то он станет корнем пакета.

Например, если имеется компонент src/lib/Foo.svelte и модуль src/lib/index.js, который реэкспортирует его, то пользователь вашего пакета сможет импортировать компонент любым из двух способов:

// @filename: ambient.d.ts
declare module 'your-library';

// @filename: index.js
// ---cut---
import { Foo } from 'your-library';
// @filename: ambient.d.ts
declare module 'your-library/Foo.svelte';

// @filename: index.js
// ---cut---
import Foo from 'your-library/Foo.svelte';

Публикация

Для публикации полученного пакета выполните команду:

npm publish ./package

Приведенный выше package относится к сгенерированному имени каталога, измените его соответствующим образом, если вы указываете иную директорию в package.dir.

Ограничения

Это относительно экспериментальная функция, которая ещё не полностью реализована. Все файлы, кроме файлов Svelte (предварительно обработанных) и файлов TypeScript (переработанных в JavaScript), копируются как есть.

svelte-kit CLI permalink

SvelteKit включает в себя утилиту для создания и запуска вашего приложения.

В шаблоне проекта по умолчанию команды svelte-kit dev, svelte-kit build, svelte-kit preview имеют псевдонимы – соответственно npm run dev, npm run build и npm start. Также можно вызвать CLI-утилиту с помощью npx:

npx svelte-kit dev

svelte-kit dev

Запускает сервер для разработки. Принимает следующие параметры:

  • -p/--port — порт, на котором запустить сервер
  • -o/--open — открыть вкладку браузера после запуска сервера
  • --host — открыть доступ к серверу из сети.

Используйте это с осторожностью!

  • --https — запустить HTTPS-сервер используя самоподписанный SSL сертификат. Полезно для тестирования функций, поддерживающих только HTTPS, на внешнем устройстве.

Эта команда завершится неудачей, если указанный (или по умолчанию) порт недоступен. Чтобы использовать альтернативный порт вместо сбоя, установите параметр config.kit.vite.server.strictPort в false.

svelte-kit build

Создаёт готовую к работе версию приложения и запускает нужный адаптер, если он указан в файле конфигурации. Команда принимает один параметр:

  • --verbose — выводить больше информации

svelte-kit preview

После сборки приложения командой svelte-kit build, можно запустить его локально с помощью команды svelte-kit preview (вне зависимости от используемого адаптера). Эта команда предназначена для тестирования собранного приложения локально. При запуске приложения на рабочем сервере вы всегда должны использовать адаптер.

Как и svelte-kit dev, эта команда принимает следующие параметры:

  • -p/--port
  • -o/--open
  • --host
  • --https

svelte-kit package

svelte-kit package в настоящее время является экспериментальным и не подпадает под действие правил семантического управления версиями. Несовместимые с обратной связью изменениями могут произойти в любом будущем выпуске.

Для авторов пакетов см. Создание пакетов. Скрипт svelte-kit package принимает следующие опции:

  • -w/--watch — наблюдать изменения файлов в папке src/lib и пересобирать пакет.

Конфигурация permalink

Конфигурация проекта находится в файле svelte.config.js. Все значения необязательны. Полный список параметров со значениями по умолчанию показан здесь:

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// параметры для svelte.compile (https://svelte.dev/docs#svelte_compile)
	compilerOptions: {},

	// массив расширений, которые будут считаться компонентами Svelte
	extensions: ['.svelte'],

	kit: {
		adapter: undefined,
		appDir: '_app',
		browser: {
 			hydrate: true,
 			router: true
 		},
		csp: {
 			mode: 'auto',
 			directives: {
 				'default-src': undefined
 				// ...
 			}
 		},
		files: {
			assets: 'static',
			hooks: 'src/hooks',
			lib: 'src/lib',
			params: 'src/params',
			routes: 'src/routes',
			serviceWorker: 'src/service-worker',
			template: 'src/app.html'
		},
		floc: false,
		inlineStyleThreshold: 0,
		methodOverride: {
 			parameter: '_method',
 			allowed: []
 		},
		outDir: '.svelte-kit',
		package: {
 			dir: 'package',
 			// кроме файлов .d.ts и начинающихся с нижнего подчеркивания
 			exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
 			files: () => true,
 			emitTypes: true
 		},
		paths: {
			assets: '',
			base: ''
		},
		prerender: {
			concurrency: 1,
			crawl: true,
			default: false,
			enabled: true,
			entries: ['*'],
 			onError: 'fail'
		},
		routes: (filepath) => !/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/.test(filepath),
		serviceWorker: {
			register: true,
 			files: (filepath) => !/\.DS_Store/.test(filepath)
 		},
		trailingSlash: 'never',
		version: {
 			name: Date.now().toString(),
 			pollInterval: 0
 		},
		vite: () => ({})
	},

	// SvelteKit использует vite-plugin-svelte. Здесь можно указать его параметры.
	// Список параметров см. на https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md

	// Параметры для svelte.preprocess (https://svelte.dev/docs#svelte_preprocess)
	preprocess: null
};

export default config;

adapter

Требуется при запуске svelte-kit build и определяет, как преобразуется вывод для разных платформ. См. Адаптеры.

alias

Объект, содержащий ноль или более псевдонимов, используемых для замены значений в инструкциях import. Эти псевдонимы автоматически передаются в Vite и TypeScript.

Например, вы можете добавить псевдонимы в папку components и utils:

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		alias: {
			$components: 'src/components',
			$utils: 'src/utils'
		}
	}
};

Встроенный псевдоним $lib контролируется config.kit.files.lib, поскольку он используется для упаковки.

appDir

Директория относительно paths.assets в которой будут находиться скомпилированные JS/CSS файлы и импортированные статические ресурсы. Имена файлов в этой директории будут содержать хеши на основе их содержимого, то есть эти файлы можно кэшировать на неопределённый срок. Значение параметра не должно начинаться или заканчиваться на /.

browser

Объект, содержащий ноль или более из следующих значений типа boolean:

  • hydrate — следует ли гидратировать серверный HTML с помощью клиентского приложения. Устанавливайте этот параметр в false только в исключительных случаях.
  • router - включает или отключает клиентский роутер по всему приложению.

csp

Объект, содержащий ноль или более из следующих значений:

  • mode - 'hash', 'nonce' или 'auto'
  • directives — объект, содержащий пары [директива]: значения[].

Настройка Content Security Policy. CSP помогает защитить пользователей от XSS-атак, ограничивая места, из которых могут загружаться ресурсы. Например, такая конфигурация...

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		csp: {
			directives: {
				'script-src': ['self']
			}
		}
	}
}

export default config;

...позволит предотвратить загрузку скриптов с внешних сайтов. Для любых инлайновых стилей и генерируемых скриптов SvelteKit автоматически дополнит указанные директивы нужным хешем(в зависимости от mode).

При предварительной отрисовке страниц заголовок CSP добавляется с помощью тега <meta http-equiv> (учтите, что в этом случае директивы frame-ancestors, report-uri и sandbox будут игнорироваться).

При значении mode: 'auto', SvelteKit будет использовать аттрибуты nonce для динамических страниц и аттрибуты hashe для предварительно отрисованных. Использование аттрибута nonce с предварительно отрисованными страницами небезопасно а, значит, запретно.

endpointExtensions

Массив расширений файлов, которые SvelteKit будет рассматривать как эндпоинты. Файлы с расширениями, которые не соответствуют ни config.extensions, ни config.kit.endpointExtensions, будут игнорироваться маршрутизатором.

files

Объект, содержащий следующие строковые параметры(все опциональны):

  • assets — место для размещения статических файлов, которые должны иметь стабильные URL-адреса и не подвергаться обработке, например favicon.ico и manifest.json
  • hooks — путь к файлу хуков (см. Хуки)
  • lib — внутренняя библиотека вашего приложения, доступная во всей кодовой базе как $lib
  • params - каталог, содержащий сопоставление параметров
  • routes — файлы, которые определяют структуру вашего приложения (Маршруты)
  • serviceWorker — файл сервис-воркера
  • template — расположение шаблона для HTML-ответов сервера

floc

Google FLoC — это технология таргетированной рекламы, которую Electronic Frontier Foundation сочла вредной для конфиденциальности пользователей. Браузеры, отличные от Chrome отказались её реализовать.

SvelteKit по умолчанию отключает использование FLoC в приложении, также как это делают другие сервисы, например GitHub Pages. Если для параметра floc не установлено значение true, к ответу сервера будет добавлен такой заголовок:

Permissions-Policy: Interest-cohort = () 

Это может применяться только при серверном рендеринге — заголовки для предварительно отрисованных страниц (например, созданных с помощью adapter-static) определяются платформой хостинга.

inlineStyleThreshold

Встраивание CSS-стилей на странице внутри блока <style> в теге <head>. Параметр указывает максимальный размер файла, который будет встроен в страницу. Содержимое всех CSS-файлов, которые необходимы данной странице и по размеру меньше указанного значения, будет слито и помещено в блок <style>.

Установка данного параметра приведет к меньшему количеству первоначальных запросов и может улучшить метрику Первой Отрисовки Контента. Но при этом получаемый HTML возрастает в размере, а эффективность кэширования в браузере снижается.

methodOverride

См. HTTP методы. Объект, содержащий ноль или более из следующего:

  • parameter - имя параметра запроса, используемое для передачи требуемого значения метода
  • allowed - массив методов HTTP, которые могут быть использованы при переопределении исходного метода запроса

outDir

Каталог, в который SvelteKit записывает файлы во время dev и build. Вы должны исключить этот каталог из системы управления версиями.

package

Опции, связанные с созданием пакетов.

  • dir - директория для готового пакета
  • emitTypes - по умолчанию svelte-kit package автоматически сгенерирует файлы определений типов .d.ts для пакета. Хоть этот параметр и можно отключить, но мы считаем, что для качества экосистемы нужно всегда генерировать файлы определений типов. Убедитесь, что есть веская причина устанавливать значение равным false (например, если имеются определения типов, написанные вручную).
  • exports - функция вида (filepath: string) => boolean. Когда возвращает true, путь к файлу будет включён в поле exports в package.json. Любые существующие значения в исходном package.json будут объединены с полученными из exports значениями
  • files - функция вида (filepath: string) => boolean. Когда возвращает true, файл по указанному пути будет обработан и скопирован в папку, определенной в параметре dir

Для удобного сопоставления путей в функциях значений exports и files, можно использовать различные внешние библиотеки:

// @filename: ambient.d.ts
declare module 'micromatch';

/// file: svelte.config.js
// @filename: index.js
// ---cut---
import mm from 'micromatch';

/** @type {import('@sveltejs/kit').Config} */
const config = {
   kit: {
   	package: {
   		exports: (filepath) => {
   			if (filepath.endsWith('.d.ts')) return false;
   			return mm.isMatch(filepath, ['!**/_*', '!**/internal/**'])
   		},
   		files: mm.matcher('!**/build.*')
   	}
   }
};

export default config;

paths

Объект, содержащий следующие строковые параметры(все опциональны):

  • assets — абсолютный путь, откуда будут загружаться статические файлы приложения. Это может быть полезно в случае, когда эти файлы находятся в каком-либо внешнем хранилище.
  • base — путь относительно корня, который должен начинаться, но не заканчиваться на / (например, /base-path), если только это не пустая строка. Указывает, где будет находиться приложение и позволяет запускать приложение из поддиректории основного домена.

prerender

См. Предварительная отрисовка. Объект, содержащий следующие параметры(все опциональны):

  • concurrency - сколько страниц может отрисовываться одновременно. Хоть JS и однопоточный, но в случаях, когда производительность отрисовки зависит от сети (например, загрузка контента с удалённой CMS), это поможет ускорить процесс, поскольку во время ожидания ответа сети будут обрабатываться другие задачи.

  • crawl — определяет, должен ли SvelteKit находить страницы для предварительной отрисовки, переходя по ссылкам с исходных страниц

  • default - установите значение true для предварительной отрисовки страниц не содержащих export const prerender = false

  • enabled — установите в false, чтобы полностью отключить предварительную отрисовку

  • entries — массив страниц для предварительной отрисовки или начала сканирования (при crawl: true). Строка * включает все нединамические маршруты (т.е. страницы без [параметр])

  • onError

    • 'fail' — (по умолчанию) прерывает сборку при обнаружении ошибки маршрутизации при переходе по ссылке

    • 'continue' — позволяет продолжить сборку, несмотря на ошибки маршрутизации

    • function — пользовательский обработчик ошибок, в котором можно вывести сообщение, вызвать исключение или прервать сборку, а также совершить любые другие действия, основываясь на полученных аргументах

      import static from '@sveltejs/adapter-static';
      
      /** @type {import('@sveltejs/kit').PrerenderErrorHandler} */
      const handleError = ({ status, path, referrer, referenceType }) => {
      	if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
      	console.warn(`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`);
      };
      

    /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { adapter: static(), prerender: { onError: handleError } } };

    export default config;

routes

Функция вида (filepath: string) => boolean, которая определяет, какие файлы создают маршруты, а какие рассматриваются как приватные модули.

serviceWorker

Объект, содержащий ноль или более из следующих значений:

  • register - если установлено значение false, отключит автоматическую регистрацию сервис-воркера
  • files - функция вида (filepath: string) => boolean. Когда возвращает true, запрошенный файл будет доступен в $service-worker.files.

trailingSlash

Следует ли удалять, добавлять или игнорировать конечные слэши при разрешении URL-адресов (обратите внимание, что это относится только к страницам, а не к эндпоинтам).

  • 'never' - перенаправит /x/ на /x
  • 'always' - перенаправит /x на /x/
  • 'ignore'- ничего не делать. /x и /x/ будут рассматриваться эквивалентно

Этот параметр влияет также и на предварительную отрисовку. Для соответствия с работой web-серверов при сохранении отрисованной страницы с адресом /about, когда параметр trailingSlash имеет значение always, будет создана директория с индексным файлом about/index.html, в иных случаях просто файл about.html.

Игнорирование конечных слэшей не рекомендуется — семантика относительных путей в двух случаях различается (./y от /x будет /y, а от /x/ станет /x/y). Кроме того, /x и /x/ рассматриваются как отдельные URL-адреса, что вредно для SEO. При использовании этой опции, убедитесь, что логика добавления или удаления конечных слэшей из request.path реализована в функции handle.

version

Объект, содержащий ноль или более из следующих значений:

  • name - текущая весрия приложения в виде строки
  • pollInterval - интервал в миллисекундах для опроса новой версии

Навигация на стороне клиента может сбоить, когда на сервер загружена новая версия приложения, а люди всё ещё используют ранее загруженную версию. Если данные для следующей страницы уже загружены с сервера, они могут быть устаревшими. В таком случае может быть запрошен более не существующий JavaScript-файл. SvelteKit решает эту проблему, отключая клиентский роутер и выполняя переход с перезагрузкой страницы, когда обнаруживает, что значение версии приложения, указанное в name, изменилось (по умолчанию в качестве версии используется метка времени сборки).

При установке значения pollInterval отличным от ноля, SvelteKit будет периодически опрашивать сервер на наличие новой версии и установит значение хранилища updated в true, когда она будет обнаружена.

vite

Объект конфигурации Vite или функция, которая его возвращает. Вы можете использовать плагины Vite и Rollup в параметре pluginsдля более продвинутой сборки приложения,например, использовав оптимизацию изображений, Tauri, WASM, Workbox и прочее. Некоторые параметры сборки установить невозможно, они используются внутри SvelteKit и определяются его параметрами.

Types permalink

@sveltejs/kit

Все API в Sveltekit полностью типизированны. Следующие типы могут быть импортированы из @sveltejs/kit

TYPES

App namespace

Можно сказать Sveltekit, как тизировать объекты внутри вашего приложения, объявив пространство имен App. По умолчанию новый проект будет иметь файл под названием src/app.d.ts, содержащий следующее:

/// <reference types="@sveltejs/kit" />
declare namespace App {
 	interface Locals {}
 	interface Platform {}
 	interface Session {}
 	interface Stuff {}
}

После заполнения этих интерфейсов, вы получите безопасное использование типов в event.locals, event.platform, session и stuff:

App.Locals

Интерфейс, который определяет event.locals, доступ к которому можно получить в хуках (handle, handleError и getSession) и эндпоинтах.

App.Platform

Если текущий адаптер предоставляет контекст платформы через event.platform, укажите его здесь.

App.Session

Интерфейс, который определяет объект session, как аргумента для функций load, так и значения хранилища session.

App.Stuff

Интерфейс, который определяет объект stuff во входных и выходных данных функции load, а так же в значении свойства stuff в хранилище page.

Сгенерированные типы

Типы RequestHandler и Load принимают аргумент Params, позволяя вам ввести объект params. Например, этот эндпоинт ожидает параметры foo, bar и baz:

/// file: src/routes/[foo]/[bar]/[baz].js
// @errors: 2355
/** @type {import('@sveltejs/kit').RequestHandler<{
 *   foo: string;
 *   bar: string;
 *   baz: string
 * }>} */
export async function get({ params }) {
// ...
}

Излишне говорить, что это громоздко записывать и менее портативно (если бы вы переименовали каталог [foo] в [qux], тип больше не отражал бы реальность).

Чтобы решить эту проблему, SvelteKit генерирует файлы .d.ts для каждой из ваших конечных точек и страниц:

/// file: .svelte-kit/types/src/routes/[foo]/[bar]/__types/[baz].d.ts
/// link: false
import type { RequestHandler as GenericRequestHandler, Load as GenericLoad } from '@sveltejs/kit';

export type RequestHandler<Body = any> = GenericRequestHandler<
{ foo: string; bar: string; baz: string },
Body
>;

export type Load<
 	InputProps extends Record<string, any> = Record<string, any>,
 	OutputProps extends Record<string, any> = InputProps
> = GenericLoad<{ foo: string; bar: string; baz: string }, InputProps, OutputProps>;

Эти файлы можно импортировать в конечные точки и страницы в качестве братьев и сестер благодаря опции rootDirs в конфигурации TypeScript:

/// file: src/routes/[foo]/[bar]/[baz].js
// @filename: __types/[baz].d.ts
import type { RequestHandler as GenericRequestHandler, Load as GenericLoad } from '@sveltejs/kit';

export type RequestHandler<Body = any> = GenericRequestHandler<
{ foo: string, bar: string, baz: string },
Body
>;

// @filename: index.js
// @errors: 2355
// ---cut---
/** @type {import('./__types/[baz]').RequestHandler} */
export async function get({ params }) {
// ...
}
<script context="module">
/** @type {import('./__types/[baz]').Load} */
export async function load({ params, fetch, session, stuff }) {
	// ...
}
</script>

Чтобы это сработало, ваш собственный tsconfig.json или jsconfig.json должен расширяться от сгенерированного .svelte-kit/tsconfig.json (где .svelte-kit - ваш outDir):

{ "extends": "./.svelte-kit/tsconfig.json" }

tsconfig.json

Сгенерированный файл .svelte-kit/tsconfig.json содержит смесь опций. Некоторые из них генерируются программно на основе конфигурации вашего проекта и, как правило, не должны быть переопределены без уважительной причины:

// file: .svelte-kit/tsconfig.json
{
 	"compilerOptions": {
 		"baseUrl": "..",
 		"paths": {
 			"$lib": "src/lib",
 			"$lib/*": "src/lib/*"
 		},
 		"rootDirs": ["..", "./types"]
 	},
 	"include": ["../src/**/*.js", "../src/**/*.ts", "../src/**/*.svelte"],
 	"exclude": ["../node_modules/**", "./**"]
}

Другие необходимы для правильной работы SvelteKit, а также должны оставаться нетронутыми, если вы не знаете, что делаете:

// file: .svelte-kit/tsconfig.json
{
	"compilerOptions": {
		// это гарантирует, что типы явно
		// импортируется с `import type`, который
		// необходимо, так как svelte-preprocess не может
		// в противном случае правильно компилируйте компоненты
		"importsNotUsedAsValues": "error",

		// Vite компилирует один модуль TypeScript
		// за раз, а не компилировать
		// весь график модуля
		"isolatedModules": true,

		// TypeScript не может "видеть", когда вы
		// используйте импортированное значение в вашем
		// разметка, поэтому нам это нужно
		"preserveValueImports": true,

		// Настройки для праивильной работы
 		// `svelte-kit build` и `svelte-kit package`
 		"lib": ["esnext", "DOM"],
 		"moduleResolution": "node",
 		"module": "esnext",
 		"target": "esnext"
	}
}

SEO permalink

Самым важным аспектом SEO является создание высококачественного контента, который широко связан со всем Интернетом. Тем не менее, есть несколько технических соображений для создания сайтов, которые хорошо ранжируются.

Из коробки

SSR

В то время как поисковые системы в последние годы стали лучше индексировать контент, отображаемый с помощью клиентского JavaScript, контент, отображаемый на стороне сервера, индексируется чаще и надежнее. SvelteKit использует SSR по умолчанию, и хотя вы можете отключить его в handle, вы должны оставить его включенным, если у вас нет веской причины не делать этого.

Рендеринг SvelteKit легко настраивается, и при необходимости вы можете реализовать динамический рендеринг. Обычно это не рекомендуется, поскольку SSR имеет и другие преимущества помимо SEO.

Производительность

Такие сигналы, как Core Web Vitals, влияют на ранжирование в поисковых системах. Поскольку Svelte и SvelteKit создают минимальные накладные расходы, проще создавать высокопроизводительные сайты. Вы можете проверить производительность своего сайта с помощью Google PageSpeed ​​Insights или Lighthouse.

Нормализованные URL

SvelteKit перенаправляет пути с косой чертой в конце на пути без косой черты (или наоборот, в зависимости от вашей конфигурации), поскольку повторяющиеся URL-адреса вредны для SEO.

Ручная настройка

<title> and <meta>

Каждая страница должна иметь хорошо написанные и уникальные элементы <title> и <meta name="description"> внутри <svelte:head>. Руководство по написанию описательных заголовков и описаний, а также другие рекомендации по обеспечению понятности контента для поисковых систем можно найти в документации Google [Lighthouse SEO-аудиты] (https://web.dev/lighthouse-seo/).

Распространенным шаблоном является возврат связанных с SEO stuff из функций загрузки страницы, а затем их использование (как $page.stuff) в <svelte:head> в вашем корневом макете.

Структурированные данные

Структурированные данные помогают поисковым системам понять содержание страницы. Если вы используете структурированные данные вместе с svelte-preprocess, вам нужно будет явно сохранить данные ld+json (это может измениться в будущем ):

/// file: svelte.config.js
// @filename: ambient.d.ts
declare module 'svelte-preprocess';

// @filename: index.js
// ---cut---
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	preprocess: preprocess({
		preserve: ['ld+json'],
		// ...
	})
};

export default config;

Карта сайта

Карта сайта помогает поисковым системам определять приоритетность страниц вашего сайта, особенно если у вас большой объем контента. Вы можете создать карту сайта динамически, используя эндпоинт:

/// file: src/routes/sitemap.xml.js
export async function get() {
	return {
		headers: {
			'Content-Type': 'application/xml'
		},
		body: `
			<?xml version="1.0" encoding="UTF-8" ?>
			<urlset
				xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
				xmlns:xhtml="https://www.w3.org/1999/xhtml"
				xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0"
				xmlns:news="https://www.google.com/schemas/sitemap-news/0.9"
				xmlns:image="https://www.google.com/schemas/sitemap-image/1.1"
				xmlns:video="https://www.google.com/schemas/sitemap-video/1.1"
			>
				<!-- <url> elements go here -->
			</urlset>
		`.trim()
	};
}

AMP

Печальная реальность современной веб-разработки заключается в том, что иногда необходимо создать Ускоренную мобильную страницу (AMP) версию вашего сайта. В SvelteKit это можно сделать, принудив следующие параметры конфигурация...

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// комбинация этих опций
		// отключает JavaScript
		browser: {
			hydrate: false,
			router: false
		},

		// так как <link rel="stylesheet"> не
		// разрешено, все стили инлайнятся
		inlineStyleThreshold: Infinity
	}
};

export default config;

...и преобразование HTML с помощью transformPage вместе с transform, импортированным из @sveltejs/amp:

import * as amp from '@sveltejs/amp';

/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
	return resolve(event, {
		transformPage: ({ html }) => amp.transform(html)
	});
}

Рекомендуется использовать хук handle для проверки преобразованного HTML с помощью amphtml-validator, но только если вы предварительно отрисовываете страницы, так как это очень медленно.

Файлы ресурсов permalink

Импортирование

Vite автоматически обработает импортированные файлы для повышения производительности. Хэши будут добавлены к именам файлов, чтобы их можно было кэшировать, а ресурсы, меньшие, чем assetsInlineLimit, будут встроены.

<script>
	import logo from '$lib/assets/logo.png';
</script>

<img alt="The project logo" src={logo} />

Если вы предпочитаете ссылаться на файлы ресурсов непосредственно в разметке, можно использовать препроцессор, такой как [svelte-preprocess-import-assets] (https://github.com/bluwy/svelte-preprocess-import-assets) или [svelte-image] (https://github.com/matyunya/svelte-image).

Для файлов ресурсов, включенных через CSS функцию url(), можно найти опцию experimental.useVitePreprocess:

// svelte.config.js
export default {
	experimental: {
		useVitePreprocess: true
	}
};

Оптимизация

Можно использовать сжатые форматы изображений, такие как .webp или .avif, или отзывчивые изображения, которые отдают разные размеры в зависимости от экрана вашего устройства. Для изображений, которые статически включены в проект, можно использовать препроцессор, такой как [svelte-image] (https://github.com/matyunya/svelte-image) или плагин Vite, такой как [vite-imagetools](https://github.com/JonasKruckenberg/

Переход с Sapper permalink

SvelteKit является преемником Sapper и разделяет многие элементы своего дизайна.

Если у вас есть существующее приложение Sapper, которое вы планируете перенести на SvelteKit, вам нужно будет внести ряд изменений. Возможно, вам будет полезно просмотреть некоторые примеры во время миграции.

package.json

type: "module"

Добавьте "type": "module" в свой package.json. Вы можете сделать этот шаг отдельно от остальных в рамках инкрементной миграции, если вы используете Sapper 0.29.3 Или новее.

dependencies

Удалите polka или express, если вы используете один из них, и любое промежуточное программное обеспечение, такое как sirv или compression.

devDependencies

Удалите sapper из вашего devDependencies и замените его на @sveltejs/kit и любой адаптер, который вы планируете использовать (см. следующий раздел).

scripts

Любые скрипты, которые ссылаются на sapper, должны быть обновлены:

  • sapper build должен стать [svelte-kit build](- sapper export должен стать svelte-kit build с помощью статического адаптера

) с помощью узла адаптер

Файлы проекта

Основная часть вашего приложения в src/routes может быть оставлена там, где оно находится, но несколько файлов проекта необходимо будет переместить или обновить.

Конфигурация

Ваш webpack.config.js или rollup.config.js следует заменить на svelte.config.js, как описано здесь. Параметры препроцессора Svelte следует переместить в config.preprocess.

Вам нужно будет добавить адаптер. sapper build примерно эквивалентен adapter-node, в то время как sapper export примерно эквивалентен adapter-static, хотя вы можете предпочесть использовать адаптер, предназначенный для платформы, на которую развертываете.

Если вы использовали плагины для типов файлов, которые не обрабатываются автоматически Vite, вам нужно будет найти эквиваленты Vite и добавить их в Vite config.

src/client.js

Этот файл не имеет эквивалента в SvelteKit. Любая пользовательская логика (помимо sapper.start(...)) должна быть выражена в файле __layout.svelte внутри обратного вызова onMount.

src/server.js

При использовании adapter-node эквивалентом является пользовательский сервер. В противном случае этот файл не имеет прямого эквивалента, так как приложения SvelteKit могут работать в бессерверных средах. Тем не менее, вы можете использовать хуки для реализации логики сеанса.

src/service-worker.js

Большинство импортов из @sapper/service-worker имеют эквиваленты в $service-worker:

  • файлы не изменились
  • routes был удален
  • shell теперь build
  • timestamp теперь version

src/template.html

Файл src/template.html должен быть переименован в src/app.html.

Удалите %sapper.base%, %sapper.scripts% и %sapper.styles%. Замените %sapper.head% на %sveltekit.head% и %sapper.html% на %sveltekit.body%. <div id="sapper"> больше не нужен.

src/node_modules

Распространенным шаблоном в приложениях Sapper является размещение внутренней библиотеки в каталоге внутри src/node_modules. Это не работает с Vite, поэтому вместо этого мы используем src/lib.

Страницы и макеты

Переименованные файлы

Ваш пользовательский компонент страницы ошибок должен быть переименован с _error.svelte в __error.svelte. Любые файлы _layout.svelte также должны быть переименованы в __layout.svelte. Префикс двойного подчеркивания зарезервирован для SvelteKit; ваши собственные приватные модули по-прежнему обозначаются одним префиксом _ (настраивается через конфигурацию routes).

Импорты

Импорт goto, prefetch и prefetchRoutes из @sapper/app должен быть заменен идентичным импортом из $app/navigation.

Импорт stores из @sapper/app должен быть заменен — см. раздел Хранилища ниже.

Любые файлы, которые вы ранее импортировали из каталогов в src/node_modules, необходимо будет заменить импортом $lib.

Предзагрузка

Как и раньше, страницы и макеты могут экспортировать функцию, которая позволяет загружать данные до начала рендеринга.

Эта функция была переименована с preload в load, и ее API изменился. Вместо двух аргументов — «page» и «session» — есть один аргумент, который включает в себя оба, а также fetch (который заменяет this.fetch), так и новый объект stuff.

Больше нет объекта this, и, следовательно, нет this.fetch, this.error или this.redirect. Вместо того, чтобы возвращать реквизит напрямую, load теперь возвращает объект, который содержит props, наряду с различными другими вещами.

Наконец, если на вашей странице есть метод «load», обязательно верните что-то, иначе вы получите «Не найдено».

Хранилища

В Sapper вы получите ссылки на предоставленные магазины следующим образом:

// @filename: ambient.d.ts
declare module '@sapper/app';

// @filename: index.js
// ---cut---
import { stores } from '@sapper/app';
const { preloading, page, session } = stores();

Хранилища page и session все еще существуют; preloading было заменено хранилищем navigating, которое содержит свойства from и to. page теперь имеет свойства url и params, но не имеет path или query.

Вы получаете к ним доступ по-разному в SvelteKit. stores теперь getStores, но в большинстве случаев это не нужно, так как вы можете импортировать navigating, page и session непосредственно из $app/stores.

Маршрутизация

Маршруты Regex больше не поддерживаются. Вместо этого используйте сопоставление маршрутов.

Сегменты

Ранее компоненты макета получал свойство segment, указывающее на дочерний сегмент. Это было удалено; теперь можно использовать более гибкое значение $page.url.pathname, чтобы получить сегмент.

URLs

В Sapper все относительные URL-адреса разрешались по базовому URL-адресу — обычно /, если не использовалась опция basepath, а не по отношению к текущей странице.

Это вызвало проблемы и в SvelteKit относительные URL-адреса разрешаются для текущей страницы (или целевой страницы для URL-адресов fetch в функциях load). В большинстве случаев проще использовать URL-адреса относительно корня (т.е. начинается с /), так как их значение не зависит от контекста.

Атрибуты ссылок

  • sapper:prefetch теперь sveltekit:prefetch
  • sapper:noscroll теперь sveltekit:noscroll

Эндпоинты

В Sapper «маршруты сервера», теперь называемые эндпоинтами, получили объекты req и res, предоставляемые модулем Node http (или дополненными версиями, предоставляемыми такими фреймворками, как Polka и Express).

SvelteKit разработан так, чтобы быть независимым в отношении того, где работает приложение - оно может работать на сервере Node, но в равной степени может работать на бессерверной платформе или в Cloudflare Worker. По этой причине вы больше не взаимодействуете напрямую с req и res. Ваши конечные точки должны быть обновлены в соответствии с новой подписью.

Для поддержки этого поведения, независимого от среды, fetch теперь доступен в глобальном контексте, поэтому вам не нужно импортировать node-fetch, cross-fetch или аналогичные реализации выборки на стороне сервера, чтобы использовать его.

Интеграции

Подробную информацию об интеграциях см. в разделе FAQ.

HTML minifier

Sapper по умолчанию включает html-minifier. SvelteKit не включает это, но его можно добавить в качестве хука:

// @filename: ambient.d.ts
/// <reference types="@sveltejs/kit" />
declare module 'html-minifier';

// @filename: index.js
// ---cut---
import { minify } from 'html-minifier';
import { prerendering } from '$app/env';

const minification_options = {
	collapseBooleanAttributes: true,
	collapseWhitespace: true,
	conservativeCollapse: true,
	decodeEntities: true,
	html5: true,
	ignoreCustomComments: [/^#/],
	minifyCSS: true,
	minifyJS: false,
	removeAttributeQuotes: true,
	removeComments: true,
	removeOptionalTags: true,
	removeRedundantAttributes: true,
	removeScriptTypeAttributes: true,
	removeStyleLinkTypeAttributes: true,
	sortAttributes: true,
	sortClassName: true
};

/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
	const response = await resolve(event);

	if (prerendering && response.headers.get('content-type') === 'text/html') {
		return new Response(minify(await response.text(), minification_options), {
			status: response.status,
			headers: response.headers
		});
	}

	return response;
}

Обратите внимание, что prerendering имеет значение false при использовании svelte-kit preview для тестирования производственной сборки сайта, поэтому для проверки результатов минимизирования вам нужно будет напрямую проверить собранные HTML-файлы.

Дополнительные ресурсы permalink

FAQ

Прочтите SvelteKit FAQ, чтобы найти решения типичных проблем, а также полезные советы и рекомендации.

Svelte FAQ и vite-plugin-svelte FAQ также могут быть полезны для вопросов, касающихся этих библиотек.

Примеры

Мы написали и опубликовали несколько различных сайтов на Sveltekit в качестве примеров:

Пользователи SvelteKit также опубликовали множество примеров на GitHub с тегами #sveltekit и #sveltekit-template, а также на сайте Svelte Society. Имейте ввиду, что некоторые из этих сайтов могут быть уже устаревшими

Интеграции

svelte-preprocess автоматически преобразует код в шаблонах Svelte, чтобы обеспечить поддержку TypeScript, PostCSS, Scss/Sass, Less и многих других подобных технологий (кроме CoffeeScript, который не поддерживается SvelteKit). Первым шагом настройки является добавление svelte-preprocess в svelte.config.js. Этот файл уже существует в TypeScript шаблоне, а если используется шаблон JavaScript, нужно будет создать его. После этого обычно нужно только установить соответствующую библиотеку, например npm install -D sass или npm install -D less. Дополнительную информацию ищите в документации svelte-preprocess.

Дополнения Svelte позволяют настроить множество различных сложных интеграций, таких как Tailwind, PostCSS, Firebase, GraphQL, mdsvex и многое другое, с помощью одной команды. Полный список шаблонов, компонентов и инструментов, доступных для использования со Svelte и SvelteKit, ищите на сайте sveltesociety.dev.

В SvelteKit FAQ также есть раздел об интеграции, который может быть полезен, если вы столкнетесь с какими-либо проблемами.

Поддержка

Вы можете обратиться за помощью в русскоязычный канал Telegram, Discord и StackOverflow. Пожалуйста, сначала поищите информацию, касающуюся вашей проблемы, в FAQ, Google или другой поисковой системе, в Issue на GitHub и историях чатов, чтобы не отнимать время у других. Это поможет сообществу развиваться быстрее, потому, что людей, задающих вопросы, гораздо больше, чем отвечающих на них.

Термины permalink

Ядро SvelteKit обеспечивает полностью настраиваемый механизм отрисовки. В этом разделе описаны некоторые термины, используемые при обсуждении отрисовки. Описание настроек этих опций ищете в документации выше.

SSR

Отрисовка на стороне сервера (SSR) - это генерация содержимого страницы на сервере. SSR, как правило, предпочтительнее для SEO. Хотя некоторые поисковые системы могут индексировать контент, который динамически генерируется на стороне клиента, но даже в этих случаях понадобится больше времени для индексации. Кроме того отрисовка на сервере улучшать производительность и делает приложение доступным для пользователей, если у них не работает или отключен JavaScript(что происходит чаще, чем вы, вероятно, думаете).

CSR и SPA

Отрисовка на стороне клиента (CSR) - это генерация содержимого страницы в веб-браузере с использованием JavaScript. Одностраничное приложение (SPA) - это приложение, в котором все запросы к серверу загружают единственный HTML-файл, который затем выполняет отрисовку запрошенного содержимого на основе текущего URL-адреса. Все переходы между страниц обрабатываются на стороне клиента в процессе, называемом маршрутизацией на стороне клиента, при этом обновляется содержимое каждой страницы, а общие элементы макета остаются на месте. SPA не могут предоставить преимуществ SSR, описанных выше. Однако на некоторых приложениях не сильно сказывается отсутствие этих преимуществ, например для сложного бизнес-приложения с авторизацией, где SEO не будет иметь никакого значения и известно, что пользователи будут получать доступ к приложению из известного окружения.

Предварительная отрисовка

Предварительная отрисовка означает вычисление содержимого страницы во время сборки и сохранение в HTML-файл для последующего показа пользователю. Этот подход имеет те же преимущества, что и традиционные страницы, отрисованные на сервере, но позволяет избежать перевысчисления содержимого страницы для каждого посетителя и поэтому, по мере увеличения количества посетителей, масштабируются почти бесплатно. Компромис заключается в том, что процесс сборки является более дорогим, а предварительно отрисованный контент может быть обновлен только путем создания и развертывания новой версии приложения.

Не все страницы могут быть предварительно отрисованы. Основное правило заключается в следующем: чтобы страница могла быть предварительно отрисована, любые два пользователя, заходящих на эту страницу, должны получить один и тот же контент с сервера. Обратите внимание, что всё ещё можно предварительно отрисовать содержимое, загруженное на основе параметров страницы, если все пользователи будут видеть одно и то же содержимое.

Предварительно отрисованные страницы не ограничиваются статическим контентом. Вы можете создавать персонализированные страницы, если пользовательские данные извлекаются и визуализируются на стороне клиента. Следует упомянуть, что в этом случае такой контент не будет иметь преимуществ SSR, описанных выше.

SSG

Статическая генерация сайтов (SSG) - это термин, который относится к сайту, где каждая страница предварительно отрисована. Это то, что делает adapter-static для SvelteKit. SvelteKit, в отличие от специализированных инструментов, был создан не только для генерации статических сайтов, и поэтому может терять производительность при отрисовке очень большого количества страниц. Однако, в отличие от большинства SSG инструментов, SvelteKit прекрасно позволяет смешивать различные типы отрисовки на разных страницах приложения. Одним из преимуществ полной предварительной отрисовки сайта является то, что не придётся платить за серверы для выполнения SSR и обслуживать их. После создания сайт может загружаться с обычного хостинга или из CDN, что приводит к отличной метрике "время до первого байта". Такой метод развертывания сайта ещё называют JAMstack.

Гидратация

Компоненты Svelte хранят некоторое состояние и обновляют DOM при обновлении этого состояния. При получении данных во время SSR по умолчанию SvelteKit будет сохранять эти данные и передавать их клиенту вместе с серверным HTML кодом. Затем компоненты могут быть инициализированы на клиенте с этими данными без повторного вызова эндпоинтов API. Далее Svelte проверит, находится ли DOM в ожидаемом состоянии, и присоединит к нужным элементам слушателей событий. Весь этот процесс называется гидратацией. После того, как компоненты полностью гидратированы, они могут реагировать на изменения своих свойств так же, как и любой недавно созданный компонент Svelte.

Маршрутизация

По умолчанию при переходе на новую страницу (нажав на ссылку или используя кнопки истории браузера) SvelteKit перехватит это событие и обработает его вместо того, чтобы позволить браузеру отправить запрос следующей страницы на сервер. Затем SvelteKit обновит текущий контент страницы, отрисовав содержимое для новой страницы, при этом могут быть получены необходимые данные из API. Этот процесс обновления страницы на клиенте в ответ на попытку перехода называется маршрутизацией на стороне клиента.