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, но поддерживается также и множество других редакторов.

Project Structure permalink

A typical SvelteKit project looks like this:

my-project/
├ src/
│ ├ lib/
│ │ └ [your lib files]
│ ├ params/
│ │ └ [your param matchers]
│ ├ routes/
│ │ └ [your routes]
│ ├ app.html
│ └ hooks.js
├ static/
│ └ [your static assets]
├ package.json
├ svelte.config.js
├ tsconfig.json
└ vite.config.js

You'll also find common files like .gitignore and .npmrc (and .prettierrc and .eslintrc.cjs and so on, if you chose those options when running npm create svelte@latest).

Project files

src

The src directory contains the meat of your project.

  • lib contains your library code, which can be imported via the $lib alias, or packaged up for distribution using svelte-kit package
  • params contains any param matchers your app needs
  • routes contains the pages and endpoints of your application
  • app.html is your page template — an HTML document containing the following placeholders:
    • %sveltekit.head%<link> and <script> elements needed by the app, plus any <svelte:head> content
    • %sveltekit.body% — the markup for a rendered page
    • %sveltekit.assets% — a relative path from the page to paths.assets
    • %sveltekit.nonce% — a CSP nonce for manually included links and scripts, if used
  • hooks.js (optional) contains your application's hooks
  • service-worker.js (optional) contains your service worker

You can use .ts files instead of .js files, if using TypeScript.

static

Any static assets that should be served as-is, like robots.txt or favicon.png, go in here.

package.json

Your package.json file must include @sveltejs/kit, svelte and vite as devDependencies.

When you create a project with npm create svelte@latest, you'll also notice that package.json includes "type": "module". This means that .js files are interpreted as native JavaScript modules with import and export keywords. Legacy CommonJS files need a .cjs file extension.

svelte.config.js

This file contains your Svelte and SvelteKit configuration.

tsconfig.json

This file (or jsconfig.json, if you prefer type-checked .js files over .ts files) configures TypeScript, if you added typechecking during npm create svelte@latest. Since SvelteKit relies on certain configuration being set a specific way, it generates its own .svelte-kit/tsconfig.json file which your own config extends.

vite.config.js

A SvelteKit project is really just a Vite project that uses the @sveltejs/kit/vite plugin, along with any other Vite configuration.

Other files

test

If you choose to add tests during npm create svelte@latest, they will go in a test directory.

.svelte-kit

As you develop and build your project, SvelteKit will generate files in a .svelte-kit directory (configurable as outDir). You can ignore its contents, and delete them at any time (they will be regenerated when you next dev or build).

Веб-стандарты 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

Web standards permalink

Throughout this documentation, you'll see references to the standard Web APIs that SvelteKit builds on top of. Rather than reinventing the wheel, we use the platform, which means your existing web development skills are applicable to SvelteKit. Conversely, time spent learning SvelteKit will help you be a better web developer elsewhere.

These APIs are available in all modern browsers and in many non-browser environments like Cloudflare Workers, Deno and Vercel Edge Functions. During development, and in adapters for Node-based environments (including AWS Lambda), they're made available via polyfills where necessary (for now, that is — Node is rapidly adding support for more web standards).

In particular, you'll get comfortable with the following:

Fetch APIs

SvelteKit uses fetch for getting data from the network. It's available in hooks and endpoints as well as in the browser.

A special version of fetch is available in load functions for invoking endpoints directly during server-side rendering, without making an HTTP call, while preserving credentials. (To make credentialled fetches in server-side code outside load, you must explicitly pass cookie and/or authorization headers.) It also allows you to make relative requests, whereas server-side fetch normally requires a fully qualified URL.

Besides fetch itself, the Fetch API includes the following interfaces:

Request

An instance of Request is accessible in hooks and endpoints as event.request. It contains useful methods like request.json() and request.formData() for e.g. getting data that was posted to an endpoint.

Response

An instance of Response is returned from await fetch(...). Fundamentally, a SvelteKit app is a machine for turning a Request into a Response.

Headers

The Headers interface allows you to read incoming request.headers and set outgoing 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')
		}
	};
}

Stream APIs

Most of the time, your endpoints will return complete data, as in the userAgent example above. Sometimes, you may need to return a response that's too large to fit in memory in one go, or is delivered in chunks, and for this the platform provides streamsReadableStream, WritableStream and TransformStream.

URL APIs

URLs are represented by the URL interface, which includes useful properties like origin and pathname (and, in the browser, hash). This interface shows up in various places — event.url in hooks and endpoints, $page.url in pages, from and to in beforeNavigate and afterNavigate and so on.

URLSearchParams

Wherever you encounter a URL, you can access query parameters via url.searchParams, which is an instance of URLSearchParams:

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

export {};

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

Web Crypto

The Web Crypto API is made available via the crypto global. It's used internally for Content Security Policy headers, but you can also use it for things like generating UUIDs:

const uuid = crypto.randomUUID();

Макеты 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>

Routing permalink

At the heart of SvelteKit is a filesystem-based router. This means that the structure of your application is defined by the structure of your codebase — specifically, the contents of src/routes.

You can change this to a different directory by editing the project config.

There are two types of route — pages and endpoints.

Pages typically generate HTML to display to the user (as well as any CSS and JavaScript needed for the page). By default, pages are rendered on both the client and server, though this behaviour is configurable.

Endpoints run only on the server (or when you build your site, if prerendering). This means it's the place to do things like access databases or APIs that require private credentials or return data that lives on a machine in your production network. Pages can request data from endpoints. Endpoints return JSON by default, though may also return data in other formats.

Pages

Pages are Svelte components written in .svelte files (or any file with an extension listed in config.extensions). By default, when a user first visits the application, they will be served a server-rendered version of the page in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel where the common portions in the layout do not need to be rerendered.

The filename determines the route. For example, src/routes/index.svelte is the root of your site:

/// file: src/routes/index.svelte
<svelte:head>
	<title>Welcome</title>
</svelte:head>

<h1>Hello and welcome to my site!</h1>

<a href="/about">About my site</a>

A file called either src/routes/about.svelte or src/routes/about/index.svelte would correspond to the /about route:

/// file: src/routes/about.svelte
<svelte:head>
	<title>About</title>
</svelte:head>

<h1>About this site</h1>
<p>TODO...</p>

<a href="/">Home</a>

Note that SvelteKit uses <a> elements to navigate between routes, rather than a framework-specific <Link> component.

Dynamic parameters are encoded using [brackets]. For example, a blog post might be defined by src/routes/blog/[slug].svelte. These parameters can be accessed in a load function or via the page store.

A route can have multiple dynamic parameters, for example src/routes/[category]/[item].svelte or even src/routes/[category]-[item].svelte. (Parameters are 'non-greedy'; in an ambiguous case like x-y-z, category would be x and item would be y-z.)

Endpoints

Endpoints are modules written in .js (or .ts) files that export request handler functions corresponding to HTTP methods. Request handlers make it possible to read and write data that is only available on the server (for example in a database, or on the filesystem).

Their job is to return a { status, headers, body } object representing the response.

/// file: src/routes/random.js
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function GET() {
	return {
		status: 200,
		headers: {
			'access-control-allow-origin': '*'
		},
		body: {
			number: Math.random()
		}
	};
}
  • status is an HTTP status code:
    • 2xx — successful response (default is 200)
    • 3xx — redirection (should be accompanied by a location header)
    • 4xx — client error
    • 5xx — server error
  • headers can either be a plain object, as above, or an instance of the Headers class
  • body can be a plain object or, if something goes wrong, an Error. It will be serialized as JSON

A GET or HEAD response must include a body, but beyond that restriction all three properties are optional.

Page endpoints

If an endpoint has the same filename as a page (except for the extension), the page gets its props from the endpoint — via fetch during client-side navigation, or via direct function call during SSR. (If a page uses syntax for named layouts or matchers in its filename then the corresponding page endpoint's filename must also include them.)

For example, you might have a src/routes/items/[id].svelte page...

/// file: src/routes/items/[id].svelte
<script>
	// populated with data from the endpoint
	export let item;
</script>

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

...paired with a src/routes/items/[id].js endpoint (don't worry about the $lib import, we'll get to that later):

/// 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` comes from [id].js
	const item = await db.get(params.id);

	if (item) {
		return {
			status: 200,
			headers: {},
			body: { item }
		};
	}

	return {
		status: 404
	};
}

The type of the GET function above comes from ./__types/[id].d.ts, which is a file generated by SvelteKit (inside your outDir, using the rootDirs option) that provides type safety when accessing params. See the section on generated types for more detail.

To get the raw data instead of the page, you can include an accept: application/json header in the request, or — for convenience — append /__data.json to the URL, e.g. /items/[id]/__data.json.

Standalone endpoints

Most commonly, endpoints exist to provide data to the page with which they're paired. They can, however, exist separately from pages. Standalone endpoints have slightly more flexibility over the returned body type — in addition to objects and Error instances, they can return a Uint8Array or a ReadableStream.

Standalone endpoints can be given a file extension if desired, or accessed directly if not:

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

Endpoints can handle any HTTP method — not just GET — by exporting the corresponding function:

// @noErrors
export function POST(event) {...}
export function PUT(event) {...}
export function PATCH(event) {...}
export function DELETE(event) {...}

These functions can, like GET, return a body that will be passed to the page as props. Whereas 4xx/5xx responses from GET will result in an error page rendering, similar responses to non-GET requests do not, allowing you to do things like render form validation errors:

/// 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('./__types/items').RequestHandler} */
export async function POST({ request }) {
	const [errors, item] = await db.create(request);

	if (errors) {
		// return validation errors
		return {
			status: 400,
			body: { errors }
		};
	}

	// redirect to the newly created item
	return {
		status: 303,
		headers: {
			location: `/items/${item.id}`
		}
	};
}
/// file: src/routes/items.svelte
<script>
	// The page always has access to props from `GET`...
	export let items;

	// ...plus props from `POST` when the page is rendered
	// in response to a POST request, for example after
	// submitting the form below
	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">Create item</button>
</form>

Body parsing

The request object is an instance of the standard Request class. As such, accessing the request body is easy:

// @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(); // or .json(), or .text(), etc

	await create(data);
	return { status: 201 };
}

Setting cookies

Endpoints can set cookies by returning a headers object with set-cookie. To set multiple cookies simultaneously, return an array:

// @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 method overrides

HTML <form> elements only support GET and POST methods natively. You can allow other methods, like PUT and DELETE, by specifying them in your configuration and adding a _method=VERB parameter (you can configure the name) to the form's 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 elements -->
</form>

Using native <form> behaviour ensures your app continues to work when JavaScript fails or is disabled.

Private modules

Files and directories with a leading _ or . (other than .well-known) are private by default, meaning that they do not create routes (but can be imported by files that do). You can configure which modules are considered public or private with the routes configuration.

Advanced routing

Rest parameters

If the number of route segments is unknown, you can use rest syntax — for example you might implement GitHub's file viewer like so...

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

...in which case a request for /sveltejs/kit/tree/master/documentation/docs/01-routing.md would result in the following parameters being available to the page:

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

src/routes/a/[...rest]/z.svelte will match /a/z (i.e. there's no parameter at all) as well as /a/b/z and /a/b/c/z and so on. Make sure you check that the value of the rest parameter is valid, for example using a matcher.

Matching

A route like src/routes/archive/[page] would match /archive/3, but it would also match /archive/potato. We don't want that. You can ensure that route parameters are well-formed by adding a matcher — which takes the parameter string ("3" or "potato") and returns true if it is valid — to your params directory...

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

...and augmenting your routes:

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

If the pathname doesn't match, SvelteKit will try to match other routes (using the sort order specified below), before eventually returning a 404.

Matchers run both on the server and in the browser.

Sorting

It's possible for multiple routes to match a given path. For example each of these routes would match /foo-abc:

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

SvelteKit needs to know which route is being requested. To do so, it sorts them according to the following rules...

  • More specific routes are higher priority (e.g. a route with no parameters is more specific than a route with one dynamic parameter, and so on)
  • Standalone endpoints have higher priority than pages with the same specificity
  • Parameters with matchers ([name=type]) are higher priority than those without ([name])
  • Rest parameters have lowest priority
  • Ties are resolved alphabetically

...resulting in this ordering, meaning that /foo-abc will invoke src/routes/foo-abc.svelte, and /foo-def will invoke src/routes/foo-[c].svelte rather than less specific routes:

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

Encoding

Filenames are URI-decoded, meaning that (for example) a filename like %40[username].svelte would match characters beginning with @:

// @filename: ambient.d.ts
declare global {
	const assert: {
		equal: (a: any, b: any) => boolean;
	};
}

export {};

// @filename: index.js
// ---cut---
assert.equal(
	decodeURIComponent('%40[username].svelte'),
	'@[username].svelte'
);

To express a % character, use %25, otherwise the result will be malformed.

Layouts permalink

So far, we've treated pages as entirely standalone components — upon navigation, the existing component will be destroyed, and a new one will take its place.

But in many apps, there are elements that should be visible on every page, such as top-level navigation or a footer. Instead of repeating them in every page, we can use layout components.

To create a layout that applies to every page, make a file called src/routes/__layout.svelte. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this...

<slot></slot>

...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a <slot> for the page content. For example, let's add a nav bar:

/// file: src/routes/__layout.svelte
<nav>
	<a href="/">Home</a>
	<a href="/about">About</a>
	<a href="/settings">Settings</a>
</nav>

<slot></slot>

If we create pages for /, /about and /settings...

/// file: src/routes/index.svelte
<h1>Home</h1>
/// file: src/routes/about.svelte
<h1>About</h1>
/// file: src/routes/settings.svelte
<h1>Settings</h1>

...the nav will always be visible, and clicking between the three pages will only result in the <h1> being replaced.

Nested layouts

Suppose we don't just have a single /settings page, but instead have nested pages like /settings/profile and /settings/notifications with a shared submenu (for a real-life example, see github.com/settings).

We can create a layout that only applies to pages below /settings (while inheriting the root layout with the top-level nav):

/// file: src/routes/settings/__layout.svelte
<h1>Settings</h1>

<div class="submenu">
	<a href="/settings/profile">Profile</a>
	<a href="/settings/notifications">Notifications</a>
</div>

<slot></slot>

Named layouts

Some parts of your app might need something other than the default layout. For these cases you can create named layouts...

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

...and then use them by referencing the layout name (foo, in the example above) in the filename:

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

Named layouts are very powerful, but it can take a minute to get your head round them. Don't worry if this doesn't make sense all at once.

Scoping

Named layouts can be created at any depth, and will apply to any components in the same subtree. For example, __layout-foo will apply to /x/one and /x/two, but not /x/three or /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'

Inheritance chains

Layouts can themselves choose to inherit from named layouts, from the same directory or a parent directory. For example, x/y/__layout@root.svelte is the default layout for /x/y (meaning /x/y/one, /x/y/two and /x/y/three all inherit from it) because it has no name. Because it specifies @root, it will inherit directly from the nearest __layout-root.svelte, skipping __layout.svelte and x/__layout.svelte.

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

In the case where __layout-root.svelte contains a lone <slot />, this effectively means we're able to 'reset' to a blank layout for any page or nested layout in the app by adding @root.

If no parent is specified, a layout will inherit from the nearest default (i.e. unnamed) layout above it in the tree. In some cases, it's helpful for a named layout to inherit from a default layout alongside it in the tree, such as __layout-root.svelte inheriting from __layout.svelte. We can do this by explicitly specifying @default, allowing /x/y/one and siblings to use the app's default layout without using 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 is a reserved name — in other words, you can't have a __layout-default.svelte file.

Error pages

If a page fails to load (see Loading), SvelteKit will render an error page. You can customise this page by creating __error.svelte components alongside your layouts and pages.

For example, if src/routes/settings/notifications/index.svelte failed to load, SvelteKit would render src/routes/settings/notifications/__error.svelte in the same layout, if it existed. If not, it would render src/routes/settings/__error.svelte in the parent layout, or src/routes/__error.svelte in the root layout.

SvelteKit provides a default error page in case you don't supply src/routes/__error.svelte, but it's recommended that you bring your own.

If an error component has a load function, it will be called with error and status properties:

<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>

Layouts also have access to error and status via the page store

Server-side stack traces will be removed from error in production, to avoid exposing privileged information to users.

404s

Nested error pages are only rendered when an error occurs while rendering a specific page. In the case of a request that doesn't match any existing route, SvelteKit will render a generic 404 instead. For example, given these routes...

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

...the marx-brothers/__error.svelte file will not be rendered if you visit /marx-brothers/karl. If you want to render the nested error page, you should create a route that matches any /marx-brothers/* request, and return a 404 from it:

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);
}

Loading permalink

A component that defines a page or a layout can export a load function that runs before the component is created. This function runs both during server-side rendering and in the client, and allows you to fetch and manipulate data before the page is rendered, thus preventing loading spinners.

If the data for a page comes from its endpoint, you may not need a load function. It's useful when you need more flexibility, for example loading data from an external API, which might look like this:

/// 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>

Note the <script context="module"> — this is necessary because load runs before the component is rendered. Code that is per-component instance should go into a second <script> tag.

As with endpoints, pages can import generated types — the ./[slug] in the example above — to ensure that params are correctly typed.

load is similar to getStaticProps or getServerSideProps in Next.js, except that load runs on both the server and the client. In the example above, if a user clicks on a link to this page the data will be fetched from cms.example.com without going via our server.

SvelteKit's load receives an implementation of fetch, which has the following special properties:

  • it has access to cookies on the server
  • it can make requests against the app's own endpoints without issuing an HTTP call
  • it makes a copy of the response when you use it, and then sends it embedded in the initial page load for hydration

load only applies to page and layout components (not components they import), and runs on both the server and in the browser with the default rendering options.

Code called inside load blocks:

  • should use the SvelteKit-provided fetch wrapper rather than using the native fetch
  • should not reference window, document, or any browser-specific objects
  • should not directly reference any API keys or secrets, which will be exposed to the client, but instead call an endpoint that uses any required secrets

It is recommended that you not store per-request state in global variables, but instead use them only for cross-cutting concerns such as caching and holding database connections.

Mutating any shared state on the server will affect all clients, not just the current one.

Input

The load function receives an object containing eight fields — url, params, props, fetch, session, stuff, status, and error. The load function is reactive, and will re-run when its parameters change, but only if they are used in the function. Specifically, if url, session or stuff are used in the function, they will be re-run whenever their value changes, and likewise for the individual properties of params.

Note that destructuring parameters in the function declaration is enough to count as using them.

url

url is an instance of URL, containing properties like the origin, hostname, pathname and searchParams (which contains the parsed query string as a URLSearchParams object). url.hash cannot be accessed during load, since it is unavailable on the server.

In some environments this is derived from request headers during server-side rendering. If you're using adapter-node, for example, you may need to configure the adapter in order for the URL to be correct.

params

params is derived from url.pathname and the route filename.

For a route filename example like src/routes/a/[b]/[...c] and a url.pathname of /a/x/y/z, the params object would look like this:

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

props

If the page you're loading has an endpoint, the data returned from it is accessible inside the leaf component's load function as props. For layout components and pages without endpoints, props will be an empty object.

fetch

fetch is equivalent to the native fetch web API, with a few additional features:

  • it can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request
  • it can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context)
  • requests for endpoints go direct to the handler function during server-side rendering, without the overhead of an HTTP call
  • during server-side rendering, the response will be captured and inlined into the rendered HTML
  • during hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request

Cookies will only be passed through if the target host is the same as the SvelteKit application or a more specific subdomain of it.

session

session can be used to pass data from the server related to the current request, e.g. the current user. By default it is undefined. See getSession to learn how to use it.

stuff

stuff is passed from layouts to descendant layouts and pages, and can be filled with anything else you need to make available. For the root __layout.svelte component, it is equal to {}, but if that component's load function returns an object with a stuff property, it will be available to subsequent load functions.

status

status is the HTTP status code when rendering an error page, or null otherwise.

error

error is the error that was thrown (or returned from a previous load) when rendering an error page, or null otherwise.

Output

If you return a Promise from load, SvelteKit will delay rendering until the promise resolves. The return value has several properties listed below, all of which are optional (as is the return value itself).

status, error, redirect and cache are ignored when rendering error pages.

status

The HTTP status code for the page. If returning an error this must be a 4xx or 5xx response; if returning a redirect it must be a 3xx response. The default is 200.

error

If something goes wrong during load, return an Error object or a string describing the error alongside a 4xx or 5xx status code.

redirect

If the page should redirect (because the page is deprecated, or the user needs to be logged in, or whatever else) return a string containing the location to which they should be redirected alongside a 3xx status code.

The redirect string should be a properly encoded URI. Both absolute and relative URIs are acceptable.

cache

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

To cause pages to be cached, return a cache object containing a maxage property set to a number describing the page's max age in seconds. Optionally, also include a boolean private property indicating whether the resulting Cache-Control header should be private or public (meaning it can be cached by CDNs in addition to individual browsers).

If cache.private is undefined, SvelteKit will set it automatically using the following heuristic: if a load function makes a credentialled fetch, or the page uses session, the page is considered private.

This only applies to pages, not layouts.

props

If the load function returns a props object, the props will be passed to the component when it is rendered.

stuff

This will be merged with any existing stuff and passed to the load functions of subsequent layout and page components.

The combined stuff is available to components using the page store as $page.stuff, providing a mechanism for pages to pass data 'upward' to layouts.

dependencies

An array of strings representing URLs the page depends on, which can subsequently be used with invalidate to cause load to rerun. You only need to add them to dependencies if you're using a custom API client; URLs loaded with the provided fetch function are added automatically.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Hooks permalink

An optional src/hooks.js (or src/hooks.ts, or src/hooks/index.js) file exports four functions, all optional, that run on the server — handle, handleError, getSession, and externalFetch.

The location of this file can be configured as config.kit.files.hooks

handle

This function runs every time the SvelteKit server receives a request — whether that happens while the app is running, or during prerendering — and determines the response. It receives an event object representing the request and a function called resolve, which invokes SvelteKit's router and generates a response (rendering a page, or invoking an endpoint) accordingly. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing endpoints programmatically, for example).

/// 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;
}

Requests for static assets — which includes pages that were already prerendered — are not handled by SvelteKit.

If unimplemented, defaults to ({ event, resolve }) => resolve(event). To add custom data to the request, which is passed to endpoints, populate the event.locals object, as shown below.

/// 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;
}

You can add call multiple handle functions with the sequence helper function.

resolve also supports a second, optional parameter that gives you more control over how the response will be rendered. That parameter is an object that can have the following fields:

  • ssr: boolean (default true) — if false, renders an empty 'shell' page instead of server-side rendering
  • transformPage(opts: { html: string }): string — applies custom transforms to 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;
}

Disabling server-side rendering effectively turns your SvelteKit app into a single-page app or SPA. In most situations this is not recommended (see appendix). Consider whether it's truly appropriate to disable it, and do so selectively rather than for all requests.

handleError

If an error is thrown during rendering, this function will be called with the error and the event that caused it. This allows you to send data to an error tracking service, or to customise the formatting before printing the error to the console.

During development, if an error occurs because of a syntax error in your Svelte code, a frame property will be appended highlighting the location of the error.

If unimplemented, SvelteKit will log the error with default formatting.

/// 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 }) {
	// example integration with https://sentry.io/
	Sentry.captureException(error, { event });
}

handleError is only called in the case of an uncaught exception. It is not called when pages and endpoints explicitly respond with 4xx and 5xx status codes.

getSession

This function takes the event object and returns a session object that is accessible on the client and therefore must be safe to expose to users. It runs whenever SvelteKit server-renders a page.

If unimplemented, session is {}.

/// 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: {
					// only include properties needed client-side —
					// exclude anything else attached to the user
					// like access tokens etc
					name: event.locals.user.name,
					email: event.locals.user.email,
					avatar: event.locals.user.avatar
				}
		  }
		: {};
}

session must be serializable, which means it must not contain things like functions or custom classes, just built-in JavaScript data types

externalFetch

This function allows you to modify (or replace) a fetch request for an external resource that happens inside a load function that runs on the server (or during pre-rendering).

For example, your load function might make a request to a public URL like https://api.yourapp.com when the user performs a client-side navigation to the respective page, but during SSR it might make sense to hit the API directly (bypassing whatever proxies and load balancers sit between it and the public internet).

/** @type {import('@sveltejs/kit').ExternalFetch} */
export async function externalFetch(request) {
	if (request.url.startsWith('https://api.yourapp.com/')) {
		// clone the original request, but change the 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);

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

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

Modules permalink

SvelteKit makes a number of modules available to your application.

EXPORTS

Сервис-воркеры 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>

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

Service workers permalink

Service workers act as proxy servers that handle network requests inside your app. This makes it possible to make your app work offline, but even if you don't need offline support (or can't realistically implement it because of the type of app you're building), it's often worth using service workers to speed up navigation by precaching your built JS and CSS.

In SvelteKit, if you have a src/service-worker.js file (or src/service-worker.ts, or src/service-worker/index.js, etc) it will be built with Vite and automatically registered. You can disable automatic registration if you need to register the service worker with your own logic (e.g. prompt user for update, configure periodic updates, use workbox, etc).

You can change the location of your service worker and disable automatic registration in your project configuration.

Inside the service worker you have access to the $service-worker module.

Because it needs to be bundled (since browsers don't yet support import in this context), and depends on the client-side app's build manifest, service workers only work in the production build, not in development. To test it locally, use vite preview.

Anchor options permalink

sveltekit:prefetch

SvelteKit uses code splitting to break your app into small chunks (one per route), ensuring fast startup times.

For dynamic routes, such as our src/routes/blog/[slug].svelte example, that's not enough. In order to render the blog post, we need to fetch the data for it, and we can't do that until we know what slug is. In the worst case, that could cause lag as the browser waits for the data to come back from the server.

We can mitigate that by prefetching the data. Adding a sveltekit:prefetch attribute to a link...

<a sveltekit:prefetch href="blog/what-is-sveltekit">What is SvelteKit?</a>

...will cause SvelteKit to run the page's load function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the click event to trigger navigation. Typically, this buys us an extra couple of hundred milliseconds, which is the difference between a user interface that feels laggy, and one that feels snappy.

Note that prefetching will not work if the router setting is false.

You can also programmatically invoke prefetch from $app/navigation.

sveltekit:reload

By default, the SvelteKit runtime intercepts clicks on <a> elements and bypasses the normal browser navigation for relative (same-origin) URLs that match one of your page routes. We sometimes need to tell SvelteKit that certain links need to be handled by normal browser navigation. Examples of this might be linking to another page on your domain that's not part of your SvelteKit app or linking to an endpoint.

Adding a sveltekit:reload attribute to a link...

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

...will cause browser to navigate via a full page reload when the link is clicked.

Links with a rel="external" attribute will receive the same treatment. In addition, they will be ignored during prerendering.

sveltekit:noscroll

When navigating to internal links, SvelteKit mirrors the browser's default navigation behaviour: it will change the scroll position to 0,0 so that the user is at the very top left of the page (unless the link includes a #hash, in which case it will scroll to the element with a matching ID).

In certain cases, you may wish to disable this behaviour. Adding a sveltekit:noscroll attribute to a link...

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

...will prevent scrolling after the link is clicked.

События 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.

Events permalink

SvelteKit emits a sveltekit:start CustomEvent on the window object once the app has hydrated.

You probably won't need to use it, but it can be useful in the context of (for example) integration tests.

Adapters permalink

Before you can deploy your SvelteKit app, you need to adapt it for your deployment target. Adapters are small plugins that take the built app as input and generate output for deployment.

By default, projects are configured to use @sveltejs/adapter-auto, which detects your production environment and selects the appropriate adapter where possible. If your platform isn't (yet) supported, you may need to install a custom adapter or write one.

See the adapter-auto README for information on adding support for new environments.

Supported environments

SvelteKit offers a number of officially supported adapters.

You can deploy to the following platforms with the default adapter, adapter-auto:

Node.js

To create a simple Node server, install the @sveltejs/adapter-node package and update your svelte.config.js:

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

With this, vite build will generate a self-contained Node app inside the build directory. You can pass options to adapters, such as customising the output directory:

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

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

Static sites

Most adapters will generate static HTML for any prerenderable pages of your site. In some cases, your entire app might be prerenderable, in which case you can use @sveltejs/adapter-static to generate static HTML for all your pages. A fully static site can be hosted on a wide variety of platforms, including static hosts like GitHub Pages.

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

You can also use adapter-static to generate single-page apps (SPAs) by specifying a fallback page.

You must ensure trailingSlash is set appropriately for your environment. If your host does not render /a.html upon receiving a request for /a then you will need to set trailingSlash: 'always' to create /a/index.html instead.

Platform-specific context

Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an env object containing KV namespaces etc. This can be passed to the RequestEvent used in hooks and endpoints as the platform property — consult each adapter's documentation to learn more.

Community adapters

Additional community-provided adapters exist for other platforms. After installing the relevant adapter with your package manager, update your svelte.config.js:

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

Writing custom adapters

We recommend looking at the source for an adapter to a platform similar to yours and copying it as a starting point.

Adapters packages must implement the following API, which creates an 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) {
			// adapter implementation
		}
	};

	return adapter;
}

The types for Adapter and its parameters are available in types/config.d.ts.

Within the adapt method, there are a number of things that an adapter should do:

  • Clear out the build directory
  • Write SvelteKit output with builder.writeClient, builder.writePrerendered, builder.writeServer, and builder.writeStatic
  • Output code that:
    • Imports Server from ${builder.getServerDirectory()}/index.js
    • Instantiates the app with a manifest generated with builder.generateManifest({ relativePath })
    • Listens for requests from the platform, converts them to a standard Request if necessary, calls the server.respond(request, { getClientAddress }) function to generate a Response and responds with it
    • expose any platform-specific information to SvelteKit via the platform option passed to server.respond
    • Globally shims fetch to work on the target platform, if necessary. SvelteKit provides a @sveltejs/kit/install-fetch helper for platforms that can use node-fetch
  • Bundle the output to avoid needing to install dependencies on the target platform, if necessary
  • Put the user's static files and the generated JS/CSS in the correct location for the target platform

Where possible, we recommend putting the adapter output under the build/ directory with any intermediate output placed under .svelte-kit/[adapter-name].

The adapter API may change before 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), копируются как есть.

Page options permalink

By default, SvelteKit will render any component first on the server and send it to the client as HTML. It will then render the component again in the browser to make it interactive in a process called hydration. For this reason, you need to ensure that components can run in both places. SvelteKit will then initialise a router that takes over subsequent navigations.

You can control each of these on a per-app or per-page basis. Note that each of the per-page settings use context="module", and only apply to pages, not layouts.

If both are specified, per-page settings override per-app settings in case of conflicts.

router

SvelteKit includes a client-side router that intercepts navigations (from the user clicking on links, or interacting with the back/forward buttons) and updates the page contents, rather than letting the browser handle the navigation by reloading.

In certain circumstances you might need to disable client-side routing with the app-wide browser.router config option or the page-level router export:

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

Note that this will disable client-side routing for any navigation from this page, regardless of whether the router is already active.

hydrate

Ordinarily, SvelteKit hydrates your server-rendered HTML into an interactive page. Some pages don't require JavaScript at all — many blog posts and 'about' pages fall into this category. In these cases you can skip hydration when the app boots up with the app-wide browser.hydrate config option or the page-level hydrate export:

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

If hydrate and router are both false, SvelteKit will not add any JavaScript to the page at all. If server-side rendering is disabled in handle, hydrate must be true or no content will be rendered.

prerender

It's likely that at least some pages of your app can be represented as a simple HTML file generated at build time. These pages can be prerendered.

Prerendering happens automatically for any page with the prerender annotation:

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

Alternatively, you can set config.kit.prerender.default to true and prerender everything except pages that are explicitly marked as not prerenderable:

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

If your entire app is suitable for prerendering, you can use adapter-static, which will output files suitable for use with any static webserver.

The prerenderer will start at the root of your app and generate HTML for any prerenderable pages it finds. Each page is scanned for <a> elements that point to other pages that are candidates for prerendering — because of this, you generally don't need to specify which pages should be accessed. If you do need to specify which pages should be accessed by the prerenderer, you can do so with the entries option in the prerender configuration.

When not to prerender

The basic rule is this: for a page to be prerenderable, any two users hitting it directly must get the same content from the server.

Not all pages are suitable for prerendering. Any content that is prerendered will be seen by all users. You can of course fetch personalized data in onMount in a prerendered page, but this may result in a poorer user experience since it will involve blank initial content or loading indicators.

Note that you can still prerender pages that load data based on the page's parameters, like our src/routes/blog/[slug].svelte example from earlier. The prerenderer will intercept requests made inside load, so the data served from src/routes/blog/[slug].json.js will also be captured.

Accessing url.searchParams during prerendering is forbidden. If you need to use it, ensure you are only doing so in the browser (for example in onMount).

Route conflicts

Because prerendering writes to the filesystem, it isn't possible to have two endpoints that would cause a directory and a file to have the same name. For example, src/routes/foo/index.js and src/routes/foo/bar.js would try to create foo and foo/bar, which is impossible.

For that reason among others, it's recommended that you always include a file extension — src/routes/foo/index.json.js and src/routes/foo/bar.json.js would result in foo.json and foo/bar.json files living harmoniously side-by-side.

For pages, we skirt around this problem by writing foo/index.html instead of foo.

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 и пересобирать пакет.

Packaging permalink

svelte-kit package is currently experimental and is not subject to Semantic Versioning rules. Non-backward compatible changes may occur in any future release.

You can use SvelteKit to build component libraries as well as apps.

When you're creating an app, the contents of src/routes is the public-facing stuff; src/lib contains your app's internal library.

A SvelteKit component library has the exact same structure as a SvelteKit app, except that src/lib is the public-facing bit. src/routes might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.

Running svelte-kit package will take the contents of src/lib and generate a package directory (which can be configured) containing the following:

  • All the files in src/lib, unless you configure custom include/exclude options. Svelte components will be preprocessed, TypeScript files will be transpiled to JavaScript.
  • Type definitions (d.ts files) which are generated for Svelte, JavaScript and TypeScript files. You need to install typescript >= 4.0.0 and svelte2tsx >= 0.4.1 for this. Type definitions are placed next to their implementation, hand-written d.ts files are copied over as is. You can disable generation, but we strongly recommend against it.
  • A package.json copied from the project root with all fields but the "scripts" field. The "dependencies" field is included, which means you should add packages that you only need for your documentation or demo site to "devDependencies". A "type": "module" and an "exports" field will be added if it's not defined in the original file.

The "exports" field contains the package's entry points. By default, all files in src/lib will be treated as an entry point unless they start with (or live in a directory that starts with) an underscore, but you can configure this behaviour. If you have a src/lib/index.js or src/lib/index.svelte file, it will be treated as the package root.

For example, if you had a src/lib/Foo.svelte component and a src/lib/index.js module that re-exported it, a consumer of your library could do either of the following:

// @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';

Publishing

To publish the generated package:

npm publish ./package

The ./package above is referring to the directory name generated, change accordingly if you configure a custom package.dir.

Caveats

This is a relatively experimental feature and is not yet fully implemented. All files except Svelte files (preprocessed) and TypeScript files (transpiled to JavaScript) are copied across as-is.

Command Line Interface permalink

SvelteKit projects use Vite, meaning you'll mostly use its CLI (albeit via npm run dev/build/preview scripts):

  • vite dev — start a development server
  • vite build — build a production version of your app
  • vite preview — run the production version locally

However SvelteKit includes its own CLI for creating distributable packages and initialising your project:

svelte-kit package

svelte-kit package is currently experimental and is not subject to Semantic Versioning rules. Non-backward compatible changes may occur in any future release.

See packaging. svelte-kit package accepts the following options:

  • -w/--watch — watch files in src/lib for changes and rebuild the package

svelte-kit sync

svelte-kit sync creates the generated files for your project such as types and a tsconfig.json. When you create a new project, it is listed as the prepare script and will be run automatically as part of the npm lifecycle, so you should not ordinarily have to run this command.

Конфигурация 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 и определяются его параметрами.

Configuration permalink

Your project's configuration lives in a svelte.config.js file. All values are optional. The complete list of options, with defaults, is shown here:

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	// options passed to svelte.compile (https://svelte.dev/docs#compile-time-svelte-compile)
	compilerOptions: {},

	// an array of file extensions that should be treated as Svelte components
	extensions: ['.svelte'],

	kit: {
		adapter: undefined,
		alias: {},
		appDir: '_app',
		browser: {
			hydrate: true,
			router: true
		},
		csp: {
			mode: 'auto',
			directives: {
				'default-src': undefined
				// ...
			}
		},
		moduleExtensions: ['.js', '.ts'],
		files: {
			assets: 'static',
			hooks: 'src/hooks',
			lib: 'src/lib',
			params: 'src/params',
			routes: 'src/routes',
			serviceWorker: 'src/service-worker',
			template: 'src/app.html'
		},
		inlineStyleThreshold: 0,
		methodOverride: {
			parameter: '_method',
			allowed: []
		},
		outDir: '.svelte-kit',
		package: {
			dir: 'package',
			emitTypes: true,
			// excludes all .d.ts and files starting with _ as the name
			exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
			files: () => true
		},
		paths: {
			assets: '',
			base: ''
		},
		prerender: {
			concurrency: 1,
			crawl: true,
			default: false,
			enabled: true,
			entries: ['*'],
			onError: 'fail',
			origin: 'http://sveltekit-prerender'
		},
		routes: (filepath) => !/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/.test(filepath),
		serviceWorker: {
			register: true,
			files: (filepath) => !/\.DS_Store/.test(filepath)
		},
		trailingSlash: 'never',
		version: {
			name: Date.now().toString(),
			pollInterval: 0
		}
	},

	// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
	preprocess: null
};

export default config;

adapter

Run when executing vite build and determines how the output is converted for different platforms. See Adapters.

alias

An object containing zero or more aliases used to replace values in import statements. These aliases are automatically passed to Vite and TypeScript.

For example, you can add aliases to a components and utils folder:

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

The built-in $lib alias is controlled by config.kit.files.lib as it is used for packaging.

appDir

The directory relative to paths.assets where the built JS and CSS (and imported assets) are served from. (The filenames therein contain content-based hashes, meaning they can be cached indefinitely). Must not start or end with /.

browser

An object containing zero or more of the following boolean values:

  • hydrate — whether to hydrate the server-rendered HTML with a client-side app. (It's rare that you would set this to false on an app-wide basis.)
  • router — enables or disables the client-side router app-wide.

csp

An object containing zero or more of the following values:

  • mode — 'hash', 'nonce' or 'auto'
  • directives — an object of [directive]: value[] pairs
  • reportOnly — an object of [directive]: value[] pairs for CSP report-only mode

Content Security Policy configuration. CSP helps to protect your users against cross-site scripting (XSS) attacks, by limiting the places resources can be loaded from. For example, a configuration like this...

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

export default config;

...would prevent scripts loading from external sites. SvelteKit will augment the specified directives with nonces or hashes (depending on mode) for any inline styles and scripts it generates.

When pages are prerendered, the CSP header is added via a <meta http-equiv> tag (note that in this case, frame-ancestors, report-uri and sandbox directives will be ignored).

When mode is 'auto', SvelteKit will use nonces for dynamically rendered pages and hashes for prerendered pages. Using nonces with prerendered pages is insecure and therefore forbidden.

Note that most Svelte transitions work by creating an inline <style> element. If you use these in your app, you must either leave the style-src directive unspecified or add unsafe-inline.

moduleExtensions

An array of file extensions that SvelteKit will treat as modules. Files with extensions that match neither config.extensions nor config.kit.moduleExtensions will be ignored by the router.

files

An object containing zero or more of the following string values:

  • assets — a place to put static files that should have stable URLs and undergo no processing, such as favicon.ico or manifest.json
  • hooks — the location of your hooks module (see Hooks)
  • lib — your app's internal library, accessible throughout the codebase as $lib
  • params — a directory containing parameter matchers
  • routes — the files that define the structure of your app (see Routing)
  • serviceWorker — the location of your service worker's entry point (see Service workers)
  • template — the location of the template for HTML responses

inlineStyleThreshold

Inline CSS inside a <style> block at the head of the HTML. This option is a number that specifies the maximum length of a CSS file to be inlined. All CSS files needed for the page and smaller than this value are merged and inlined in a <style> block.

This results in fewer initial requests and can improve your First Contentful Paint score. However, it generates larger HTML output and reduces the effectiveness of browser caches. Use it advisedly.

methodOverride

See HTTP Method Overrides. An object containing zero or more of the following:

  • parameter — query parameter name to use for passing the intended method value
  • allowed - array of HTTP methods that can be used when overriding the original request method

outDir

The directory that SvelteKit writes files to during dev and build. You should exclude this directory from version control.

package

Options related to creating a package.

  • dir - output directory
  • emitTypes - by default, svelte-kit package will automatically generate types for your package in the form of .d.ts files. While generating types is configurable, we believe it is best for the ecosystem quality to generate types, always. Please make sure you have a good reason when setting it to false (for example when you want to provide handwritten type definitions instead)
  • exports - a function with the type of (filepath: string) => boolean. When true, the filepath will be included in the exports field of the package.json. Any existing values in the package.json source will be merged with values from the original exports field taking precedence
  • files - a function with the type of (filepath: string) => boolean. When true, the file will be processed and copied over to the final output folder, specified in dir

For advanced filepath matching, you can use exports and files options in conjunction with a globbing library:

// @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

An object containing zero or more of the following string values:

  • assets — an absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kind
  • base — a root-relative path that must start, but not end with / (e.g. /base-path), unless it is the empty string. This specifies where your app is served from and allows the app to live on a non-root path

prerender

See Prerendering. An object containing zero or more of the following:

  • concurrency — how many pages can be prerendered simultaneously. JS is single-threaded, but in cases where prerendering performance is network-bound (for example loading content from a remote CMS) this can speed things up by processing other tasks while waiting on the network response

  • crawl — determines whether SvelteKit should find pages to prerender by following links from the seed page(s)

  • default — set to true to prerender encountered pages not containing export const prerender = false

  • enabled — set to false to disable prerendering altogether

  • entries — an array of pages to prerender, or start crawling from (if crawl: true). The * string includes all non-dynamic routes (i.e. pages with no [parameters] )

  • onError

    • 'fail' — (default) fails the build when a routing error is encountered when following a link

    • 'continue' — allows the build to continue, despite routing errors

    • function — custom error handler allowing you to log, throw and fail the build, or take other action of your choosing based on the details of the crawl

      import adapter from '@sveltejs/adapter-static';
      
      /** @type {import('@sveltejs/kit').Config} */
      const config = {
      	kit: {
      		adapter: adapter(),
      		prerender: {
      			onError: ({ status, path, referrer, referenceType }) => {
      				if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
      				console.warn(
      					`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`
      				);
      			}
      		}
      	}
      };
      
      export default config;
  • origin — the value of url.origin during prerendering; useful if it is included in rendered content

routes

A (filepath: string) => boolean function that determines which files create routes and which are treated as private modules.

serviceWorker

An object containing zero or more of the following values:

  • register - if set to false, will disable automatic service worker registration
  • files - a function with the type of (filepath: string) => boolean. When true, the given file will be available in $service-worker.files, otherwise it will be excluded.

trailingSlash

Whether to remove, append, or ignore trailing slashes when resolving URLs (note that this only applies to pages, not endpoints).

  • 'never' — redirect /x/ to /x
  • 'always' — redirect /x to /x/
  • 'ignore' — don't automatically add or remove trailing slashes. /x and /x/ will be treated equivalently

This option also affects prerendering. If trailingSlash is always, a route like /about will result in an about/index.html file, otherwise it will create about.html, mirroring static webserver conventions.

Ignoring trailing slashes is not recommended — the semantics of relative paths differ between the two cases (./y from /x is /y, but from /x/ is /x/y), and /x and /x/ are treated as separate URLs which is harmful to SEO. If you use this option, ensure that you implement logic for conditionally adding or removing trailing slashes from request.path inside your handle function.

version

An object containing zero or more of the following values:

  • name - current app version string
  • pollInterval - interval in milliseconds to poll for version changes

Client-side navigation can be buggy if you deploy a new version of your app while people are using it. If the code for the new page is already loaded, it may have stale content; if it isn't, the app's route manifest may point to a JavaScript file that no longer exists. SvelteKit solves this problem by falling back to traditional full-page navigation if it detects that a new version has been deployed, using the name specified here (which defaults to a timestamp of the build).

If you set pollInterval to a non-zero value, SvelteKit will poll for new versions in the background and set the value of the updated store to true when it detects one.

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, но только если вы предварительно отрисовываете страницы, так как это очень медленно.

false permalink

TYPES

Generated types

The RequestHandler and Load types both accept a Params argument allowing you to type the params object. For example this endpoint expects foo, bar and baz params:

/// 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 }) {
	// ...
}

Needless to say, this is cumbersome to write out, and less portable (if you were to rename the [foo] directory to [qux], the type would no longer reflect reality).

To solve this problem, SvelteKit generates .d.ts files for each of your endpoints and pages:

/// 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>;

These files can be imported into your endpoints and pages as siblings, thanks to the rootDirs option in your TypeScript configuration:

/// 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>

For this to work, your own tsconfig.json or jsconfig.json should extend from the generated .svelte-kit/tsconfig.json (where .svelte-kit is your outDir):

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

Default tsconfig.json

The generated .svelte-kit/tsconfig.json file contains a mixture of options. Some are generated programmatically based on your project configuration, and should generally not be overridden without good reason:

/// 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/**", "./**"]
}

Others are required for SvelteKit to work properly, and should also be left untouched unless you know what you're doing:

/// file: .svelte-kit/tsconfig.json
{
	"compilerOptions": {
		// this ensures that types are explicitly
		// imported with `import type`, which is
		// necessary as svelte-preprocess cannot
		// otherwise compile components correctly
		"importsNotUsedAsValues": "error",

		// Vite compiles one TypeScript module
		// at a time, rather than compiling
		// the entire module graph
		"isolatedModules": true,

		// TypeScript cannot 'see' when you
		// use an imported value in your
		// markup, so we need this
		"preserveValueImports": true,

		// This ensures both `vite build`
		// and `svelte-kit package` work correctly
		"lib": ["esnext", "DOM"],
		"moduleResolution": "node",
		"module": "esnext",
		"target": "esnext"
	}
}

Файлы ресурсов 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/

false permalink

The most important aspect of SEO is to create high-quality content that is widely linked to from around the web. However, there are a few technical considerations for building sites that rank well.

Out of the box

SSR

While search engines have got better in recent years at indexing content that was rendered with client-side JavaScript, server-side rendered content is indexed more frequently and reliably. SvelteKit employs SSR by default, and while you can disable it in handle, you should leave it on unless you have a good reason not to.

SvelteKit's rendering is highly configurable and you can implement dynamic rendering if necessary. It's not generally recommended, since SSR has other benefits beyond SEO.

Performance

Signals such as Core Web Vitals impact search engine ranking. Because Svelte and SvelteKit introduce minimal overhead, it's easier to build high performance sites. You can test your site's performance using Google's PageSpeed Insights or Lighthouse.

Normalized URLs

SvelteKit redirects pathnames with trailing slashes to ones without (or vice versa depending on your configuration), as duplicate URLs are bad for SEO.

Manual setup

<title> and <meta>

Every page should have well-written and unique <title> and <meta name="description"> elements inside a <svelte:head>. Guidance on how to write descriptive titles and descriptions, along with other suggestions on making content understandable by search engines, can be found on Google's Lighthouse SEO audits documentation.

A common pattern is to return SEO-related stuff from page load functions, then use it (as $page.stuff) in a <svelte:head> in your root layout.

Structured data

Structured data helps search engines understand the content of a page. If you're using structured data alongside svelte-preprocess, you will need to explicitly preserve ld+json data (this may change in future):

/// 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;

Sitemaps

Sitemaps help search engines prioritize pages within your site, particularly when you have a large amount of content. You can create a sitemap dynamically using an endpoint:

/// 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

An unfortunate reality of modern web development is that it is sometimes necessary to create an Accelerated Mobile Pages (AMP) version of your site. In SvelteKit this can be done by enforcing the following configuration options...

/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// the combination of these options
		// disables JavaScript
		browser: {
			hydrate: false,
			router: false
		},

		// since <link rel="stylesheet"> isn't
		// allowed, inline all styles
		inlineStyleThreshold: Infinity
	}
};

export default config;

...and transforming the HTML using transformPage along with transform imported from @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)
	});
}

It's a good idea to use the handle hook to validate the transformed HTML using amphtml-validator, but only if you're prerendering pages since it's very slow.

Asset handling permalink

Importing

Vite will automatically process imported assets for improved performance. Hashes will be added to the filenames so that they can be cached and assets smaller than assetsInlineLimit will be inlined.

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

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

If you prefer to reference assets directly in the markup, you can use a preprocessor such as svelte-preprocess-import-assets or svelte-image.

For assets included via the CSS url() function, you may find the experimental.useVitePreprocess option useful:

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

Optimization

You may wish to utilize compressed image formats such as .webp or .avif or responsive images that serve a different size based on your device's screen. For images that are included statically in your project you may use a preprocessor like svelte-image or a Vite plugin such as vite-imagetools.

Переход с 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. Этот процесс обновления страницы на клиенте в ответ на попытку перехода называется маршрутизацией на стороне клиента.