Документация
Введение permalink
Важное замечание
SvelteKit ещё в ранней стадии разработки, и некоторые вещи могут поменяться, когда мы дойдём до релиза 1.0. Этот документ всё ещё дорабатывается. Если у вас появятся вопросы, обратитесь за помощью в русскоязычный канал в Telegram.
Прочтите руководство по миграции для помощи при переходе с Sapper.
Что такое SvelteKit?
SvelteKit — это фреймворк для создания высокопроизводительных веб-приложений.
Создание приложения с учётом всех современных передовых практик — невероятно сложная задача. Эти практики включают в себя оптимизацию сборки, так что вы загружаете только минимальный необходимый код; поддержку работы без сети; предзагрузку данных страницы до того, как пользователь перейдет на следующую страницу; и настраиваемый рендеринг, который позволяет генерировать HTML на сервере или в браузере во время выполнения или во время сборки. Все эти скучные вещи SvelteKit сделает за вас, а вы можете сотредоточиться на творческой части проекта.
SvelteKit использует Vite вместе со Svelte plugin, что даёт множество возможностей и молниеносную разработку с горячей заменой модулей (HMR), где изменения вашего кода мгновенно отражаются в браузере.
Чтобы понять это руководство, знать Svelte не обязательно, но желательно. Если коротко, Svelte — это фреймворк, который компилирует ваши компоненты в высокооптимизированный ванильный JavaScript. Прочтите вводную статью в блоге Svelte и учебник Svelte, чтобы узнать о нём побольше.
Начало работы
Самый простой способ создать приложение SvelteKit — запустить команду npm init
:
npm init svelte my-app
cd my-app
npm install
npm run dev
Первая команда создаст базовый проект в каталоге my-app
, а также спросит о настройке некоторых базовых инструментов, вроде TypeScript. Обратитесь в раздел FAQ, чтобы узнать о некоторых особенностях настройки дополнительных инструментов. Остальные команды установят необходимые зависимости и запустят проект на localhost:3000.
Вот два наших основных принципа:
- Каждая страница вашего приложения является компонентом Svelte
- Вы создаёте новые страницы путём добавления компонентов в директорию
src/routes
. Они будут рендериться на сервере, так что время первой загрузки приложения для пользователя будет максимально быстрым, а уже затем клиентское приложение возьмёт управление на себя.
Попробуйте поредактировать файлы, чтобы понять, как все работает, и, возможно, даже не придется читать остальную часть этого руководства!
Настройка редактора
Мы рекомендуем использовать Visual Studio Code (он же VS Code) с расширением Svelte, но поддерживается также и множество других редакторов.
Веб-стандарты permalink
В этой документации вы увидите ссылки на стандартные Web API, на основе которого SvelteKit строит. Вместо того, чтобы заново изобретать колесо, мы используем платформу, что означает, что ваши существующие навыки веб-разработки применимы к SvelteKit. И наоборот, время, потраченное на изучение SvelteKit, поможет вам стать лучшим веб-разработчиком в другом месте.
Эти API доступны во всех современных браузерах и во многих небраузерных средах, таких как Cloudflare Workers, Deno и Vercel Edge Functions. Во время разработки и в адаптерах для сред на основе NodeJS (включая AWS Lambda) они доступны через полифиллы, где это необходимо (пока - Node быстро добавляет поддержку большего количества веб-стандартов).
В частности, вы освоитесь со следующим:
Fetch APIs
SvelteKit использует fetch
для получения данных из сети. Он доступен в хуках и эндпоинтах, а также в браузере.
Специальная версия
fetch
доступна в функцияхload
для вызова эндпоинтов непосредственно во время рендеринга на стороне сервера, без вызова HTTP, сохраняя при этом учетные данные. (Чтобы сделать учетные данные в коде на стороне сервера за пределамиload
, вы должны явно передать заголовкиcookie
и/илиauthorization
.) Это также позволяет делать относительные запросы, но для выборки на стороне сервера обычно требуется полный URL-адрес.
Помимо самой fetch
, Fetch API включает в себя следующие интерфейсы:
Request
Экземпляр Request
доступен в хуках и эндпоинтах как event.request
. Он содержит полезные методы, такие как request.json()
и request.formData()
, например, для получения данных, которые были размещены на эндпоинте.
Response
Экземпляр Response
возвращается из await fetch(...)
. По сути, приложение SvelteKit - это машина для превращения Request
в Response
.
Headers
Интерфейс Headers
позволяет читать входящие request.headers
и устанавливать исходящие response.headers
:
// @errors: 2461
/// file: src/routes/what-is-my-user-agent.js
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get(event) {
// log all headers
console.log(...event.request.headers);
return {
body: {
// retrieve a specific header
userAgent: event.request.headers.get('user-agent')
}
};
}
URL APIs
URL-адреса представлены интерфейсом URL
, который включает в себя полезные свойства, такие как origin
и pathname
(и, в браузере, hash
). Этот интерфейс отображается в различных местах — event.url
в хуках и эндпоинтах, $page.url
в pages, from
и to
в [beforeNavigate
и afterNavigate
] (#moduli-$app-navigation) и так далее.
URLSearchParams
Где бы вы ни столкнулись с URL-адресом, вы можете получить доступ к параметрам запроса через url.searchParams
, который является экземпляром URLSearchParams
:
// @filename: ambient.d.ts
declare global {
const url: URL;
}
export {};
// @filename: index.js
// ---cut---
const foo = url.searchParams.get('foo');
Web Crypto
Web Crypto API доступен через глобальный объект "crypto". Он используется внутри для заголовков Политика безопасности контента, но вы также можете использовать его для таких вещей, как генерация UUID:
const uuid = crypto.randomUUID();
Маршруты permalink
Сердцем SvelteKit является роутер основанный на файловой системе. Это означает, что структура вашего приложения определяется структурой файлов его исходников – в частности содержимым папки src/routes
.
Можно указать другую директорию в файле конфигурации проекта.
Существует два типа маршрутов — страницы и эндпоинты.
Страницы обычно отдают HTML-код для отображения пользователю ( а также CSS и JavaScript, необходимые странице). По умолчанию они отрисовываются как на сервере, так и на клиенте, но это поведение можно настроить.
Эндпоинты запускаются только на сервере (или при сборке сайта, если используется предварительная отрисовка). Это то место, где можно выполнять запросы к базам данных или API с приватной авторизацией, а также вывести иные данные которые доступны на сервере. Страницы могут получать данные от эндпоинтов. По умолчанию эндпоинты возвращают ответ в формате JSON, но могут также возвращать данные в любых других форматах.
Страницы
Страницы — это компоненты Svelte, описанные в файлах .svelte
(или любой файл с расширением, указанным в config.extensions
). По умолчанию, когда пользователь впервые посещает приложение, ему будет отправлена сгенерированная на сервере версия запрошенной страницы, а также некоторый JavaScript, который выполняет 'гидратацию' страницы и инициализирует роутер на стороне клиента. С этого момента навигация на другие страницы будет полностью выполняться на стороне клиента обеспечивая очень быстрое перемещение, что типично для клиентских приложений, где некоторая часть разметки не требует перерисовки.
Имя файла определяет маршрут. Например, src/routes/index.svelte
— корневой файл вашего сайта:
/// file: src/routes/index.svelte
<svelte:head>
<title>Добро пожаловать!</title>
</svelte:head>
<h1>Приветствую вас на моём сайте!</h1>
<a href="/about">О сайте</a>
Файл с именем src/routes/about.svelte
или src/routes/about/index.svelte
будет соответствовать маршруту /about
:
/// file: src/routes/about.svelte
<svelte:head>
<title>О сайте</title>
</svelte:head>
<h1>Информация о сайте</h1>
<p>Это самый лучший сайт!</p>
<a href="/">Главная</a>
Обратите внимание, что SvelteKit использует элементы
<a>
для навигации между маршрутами, а не компонент<Link>
, специфичный для платформы.
Динамические параметры задаются при помощи квадратных скобок [...]. Например, можно определить страницу, отображающую статью из блога, таким образом – src/routes/blog/[slug].svelte
. Доступ к этим параметрам можно получить с помощью функции load
или через хранилище page
.
Маршрут может иметь несколько динамических параметров, например src/routes/[category]/[item].svelte
или даже src/routes/[category]-[item].svelte
. (Параметры "не жадные"; в неоднозначном случае, таком как x-y-z
, category
будет x
, а item
будет y-z
.)
Эндпоинты
Эндпоинты - это модули, записанные в файлах .js
(или .ts
), которые экспортируют функции request handler, соответствующие HTTP методам. Они могут читать и записывать данные, доступные только на сервере (например, в базе данных или в файловой системе).
/// file: src/routes/items/[id].js
// @filename: ambient.d.ts
type Item = {};
declare module '$lib/database' {
export const get: (id: string) => Promise<Item>;
}
// @filename: __types/[id].d.ts
import type { RequestHandler as GenericRequestHandler } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<{ id: string }, Body>;
// @filename: index.js
// ---cut---
import db from '$lib/database';
/** @type {import('./__types/[id]').RequestHandler} */
export async function get({ params }) {
// `params.id` берётся из [id].js
const item = await db.get(params.id);
if (item) {
return {
body: { item }
};
}
return {
status: 404
};
}
Не беспокойтесь об импорте
$lib
, мы перейдем к этому позже.
Тип функции get
выше взят из файла ./[id].d.ts
, сгенерированного SvelteKit (внутри вашего outDir
с использованием опции rootDirs
, который обеспечивает безопасность типа при доступе к params
. Дополнительную информацию см. в разделе сгенерированные типы.
Цель обработчика запроса – вернуть объект { status, headers, body }
, который будет ответом на полученный запрос, где status
является кодом ответа HTTP:
2xx
— успешный ответ (по умолчанию200
)3xx
— перенаправление (используется совместно с заголовкомlocation
)4xx
— ошибка от клиента5xx
— ошибка на сервере
Эндпоинты страницы
Если эндпоинт имеет то же имя файла, что и страница (за исключением расширения), страница получает свойства от эндпоинта - через fetch
во время навигации на стороне клиента или через прямой вызов функции во время SSR.
Например страница src/routes/items/[id].svelte
, может получить свойства из body
в конечной точке выше:
/// file: src/routes/items/[id].svelte
<script>
// свойство будет задано ответом от эндпоинта
export let item;
</script>
<h1>{item.title}</h1>
Поскольку страница и маршрут имеют один и тот же URL-адрес, вам нужно будет включить заголовок accept: application/json
, чтобы получить JSON из конечной точки, а не HTML со страницы. Вы также можете получить необработанные данные, добавив /__data.json
к URL-адресу, например /items/[id]/__data.json
.
Автономные эндпоинты
Как мы видели ранее, чаще всего эндпоинты связаны со страницей, для которой передают данные. Однако они могут существовать и отдельно от страниц. Автономные эндпоинты имеют большую гибкость в отношении типа поля body
— кроме объекта, они также могут вернуть строку или Uint8Array
.
Поддержка потоковых запросов и ответов на подходе.
Автономные эндпоинты доступны с расширением файла или без него:
filename | endpoint |
---|---|
src/routes/data/index.json.js | /data.json |
src/routes/data.json.js | /data.json |
src/routes/data/index.js | /data |
src/routes/data.js | /data |
POST, PUT, PATCH, DELETE
Эндпоинты могут обрабатывать любой HTTP-метод, не только GET, путём экспорта соответствующей функции:
// @noErrors
export function post(event) {...}
export function put(event) {...}
export function patch(event) {...}
export function del(event) {...} // `delete` - зарезервированное слово
Как и get
, все эти функции могут возвращать объект body
, который будет передан странице в качестве значений её свойств. Ответы со статусом 4xx/5xx на GET-запросы приведут к отображению страницы с ошибкой. Аналогичные ответы на запросы других HTTP-методов этого не сделают, что позволяет, например, передать и отрисовать ошибки валидации формы.
/// file: src/routes/items.js
// @filename: ambient.d.ts
type Item = {
id: string;
};
type ValidationError = {};
declare module '$lib/database' {
export const list: () => Promise<Item[]>;
export const create: (request: Request) => Promise<[Record<string, ValidationError>, Item]>;
}
// @filename: __types/items.d.ts
import type { RequestHandler as GenericRequestHandler } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<{}, Body>;
// @filename: index.js
// ---cut---
import * as db from '$lib/database';
/** @type {import('./__types/items').RequestHandler} */
export async function get() {
const items = await db.list();
return {
body: { items }
};
}
/** @type {import('./items').RequestHandler} */
export async function post({ request }) {
const [errors, item] = await db.create(request);
if (errors) {
// возвращаем ошибки валидации
return {
status: 400,
body: { errors }
};
}
// перенаправляем на страницу новой штуки
return {
status: 303,
headers: {
location: `/items/${item.id}`
}
};
}
/// file: src/routes/items.svelte
<script>
// У страницы всегда есть доступ к свойствам из `get`...
export let items;
// ...также добавляются свойства из `post`, если страница
// отрисовывается по POST-запросу, например после
// формы ниже
export let errors;
</script>
{#each items as item}
<Preview item={item}/>
{/each}
<form method="post">
<input name="title">
{#if errors?.title}
<p class="error">{errors.title}</p>
{/if}
<button type="submit">Создать штуку</button>
</form>
Получение данных запроса
Объект request
является экземпляром стандартного класса Request, поэтому получить данные из тела запроса не составит труда:
// @filename: ambient.d.ts
declare global {
const create: (data: any) => any;
}
export {};
// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function post({ request }) {
const data = await request.formData(); // или .json(), или .text()
await create(data);
return { status: 201 };
}
Установка Cookie
Эндпоинты могут устанавливать Cookie, возвращая объект заголовков с set-cookie
. Чтобы установить несколько Cookie одновременно, верните массив:
// @filename: ambient.d.ts
const cookie1: string;
const cookie2: string;
// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').RequestHandler} */
export function get() {
return {
headers: {
'set-cookie': [cookie1, cookie2]
}
};
}
Переназначение HTTP методов
HTML-формы поддерживают только методы GET
и POST
. Вы можете указать другие допустимые методы, например PUT
и DELETE
, указав их в файле конфигурации, а затем добавлять параметр _method=МЕТОД
(укажите нужный метод) в аттрибуте формы action
:
/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
methodOverride: {
allowed: ['PUT', 'PATCH', 'DELETE']
}
}
};
export default config;
<form method="post" action="/todos/{id}?_method=PUT">
<!-- элементы формы -->
</form>
Использование нативного поведения
<form>
гарантирует, что ваше приложение продолжит работать при сбое или отключении JavaScript.
Приватные модули
Файлы и каталоги, чьи имена начинаются с _
или .
(кроме .well-known
) по умолчанию являются приватными, т.е. они не создают маршруты (но могут быть импортированы файлами, которые это делают). В конфигурации проекта с помощью опции routes
можно указать, какие модули считать приватными, а какие будут создавать маршруты.
Расширенная маршрутизация
Rest-параметры
Если количество сегментов маршрута неизвестно, вы можете использовать синтаксис rest - например, вы можете реализовать средство просмотра файлов GitHub таким образом...
/[org]/[repo]/tree/[branch]/[...file]
И в данном случае запрос для маршрута /sveltejs/kit/tree/master/documentation/docs/01-routing.md
будет преобразован в следующие параметры, доступные на этой странице:
// @noErrors
{
org: 'sveltejs',
repo: 'kit',
branch: 'master',
file: 'documentation/docs/01-routing.md'
}
src/routes/a/[...rest]/z.svelte
будет соответствовать/a/z
(т.е. параметра вообще нет), а также/a/b/z
и/a/b/c/z
и так далее. Убедитесь, что значение параметра rest является допустимым, например, с помощью сопоставления.
Сопоставление
Маршрут, такой как src/routes/archive/[page]
, будет соответствовать /archive/3
, но он также будет соответствовать /archive/potato
. Мы этого не хотим. Вы можете убедиться, что параметры маршрута правильно сформированы, добавив matcher, который принимает строку параметров ("3"
или "potato"
) и возвращает true
, если он действителен - в каталог params
...
/// file: src/params/integer.js
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function validate(param) {
return /^\d+$/.match(param);
}
...и расширение ваших маршрутов:
-src/routes/archive/[page]
+src/routes/archive/[page=integer]
Если путь не совпадает, SvelteKit попытается соответствовать другим маршрутам (используя порядок сортировки, указанный ниже), прежде чем в конечном итоге вернуть 404.
Сопоставления запускаются как на сервере, так и в браузере.
Сортировка
Это нужно, чтобы несколько маршрутов соответствовали данному пути. Например, каждый из этих маршрутов будет соответствовать /foo-abc
:
src/routes/[...catchall].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/foo-[c].svelte
SvelteKit должен знать, какой маршрут запрашивается. Для этого он сортирует их по следующим правилам...
- Более конкретные маршруты имеют более высокий приоритет
- Автономные эндпоинты имеют более высокий приоритет, чем страницы с той же спецификой
- Параметры в сопоставлении маршрутов с (
[name=type]
) имеют более высокий приоритет, чем параметры без ([name]
) - Rest parameters имеют наименьшее приоритет
- Ties разрешаются в алфавитном порядке
...Результат этого порядка – /foo-abc
вызовет src/routes/foo-[bar].svelte
, а не менее конкретный маршрут:
src/routes/foo-[c].svelte
src/routes/[a].js
src/routes/[b].svelte
src/routes/[...catchall].svelte
Макеты permalink
До сих пор мы рассматривали страницы как полностью автономные компоненты — при переходе между страницами существующий компонент уничтожался, а новый занимал его место.
Но во многих приложениях есть элементы, которые должны быть видны на каждой странице, такие как навигация или подвал. Вместо того, чтобы повторять их на каждой странице, мы можем использовать компоненты макета.
Чтобы создать макет, который будет применяться к каждой странице приложения, создайте файл с именем src/routes/__layout.svelte
. По умолчанию макет (SvelteKit использует такой, если не найдет этого файла) выглядит следующим образом:
<slot></slot>
Мы можем добавить любую разметку, стили и поведение, которые мы хотим. Единственное требование — компонент должен иметь <slot>
для содержимого страницы. Например, давайте добавим панель навигации:
/// file: src/routes/__layout.svelte
<nav>
<a href="/">Главная</a>
<a href="/about">О сайте</a>
<a href="/settings">Настройки</a>
</nav>
<slot></slot>
Если мы создадим страницы для /
, /about
и /settings
...
/// file: src/routes/index.svelte
<h1>Главная</h1>
/// file: src/routes/about.svelte
<h1>О сайте</h1>
/// file: src/routes/settings.svelte
<h1>Настройки</h1>
...навигация всегда будет видна, и переход между тремя страницами приведёт только к замене содержимого элемента <h1>
.
Вложенные макеты
Предположим, что у нас не просто одна страница /settings
, а есть и вложенные страницы, вроде /settings/profile
и /settings/notifications
с общим подменю (для реального примера см. github.com/settings).
Мы можем создать макет, который применяется только к страницам, расположенным ниже /settings
(при этом останется и корневой макет с навигацией):
/// file: src/routes/settings/__layout.svelte
<h1>Настройки</h1>
<div class="submenu">
<a href="/settings/profile">Профиль</a>
<a href="/settings/notifications">Уведомления</a>
</div>
<slot></slot>
Именованные макеты
Некоторым частям вашего приложения может понадобиться что-то отличное от макета по умолчанию. В этих случаях можно создать именованные макеты...
/// file: src/routes/__layout-foo.svelte
<div class="foo">
<slot></slot>
</div>
...а затем используйте их, ссылаясь на имя макета (foo
, в примере выше) в имени файла:
/// file: src/routes/my-special-page@foo.svelte
<h1>I am inside __layout-foo</h1>
Область применения
Именованные макеты могут быть созданы на любой глубине и будут применяться к любым компонентам в том же поддереве. Например, __layout-foo
будет применяться к /x/one
и /x/two
, но не /x/three
или /four
:
src/routes/
├ x/
│ ├ __layout-foo.svelte
│ ├ one@foo.svelte # ✅ page has `@foo`
│ ├ two@foo.svelte # ✅ page has `@foo`
│ └ three.svelte # ❌ page does not have `@foo`
└ four@foo.svelte # ❌ page has `@foo`, but __layout-foo is not 'in scope'
Цепи наследования
Макеты сами могут наследовать от именованных макетов, из того же каталога или родительского каталога. Например, x/y/__layout@root.svelte
является макетом по умолчанию для /x/y
(что означает /x/y/one
, /x/y/two
и /x/y/three
наследуют от него), потому что у него нет имени. Поскольку он указывает @root
, он унаследует непосредственно от ближайшего __layout-root.svelte
, пропуская __layout.svelte
и x/__layout.svelte
.
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
└ __layout-root.svelte
В случае, когда
__layout-root.svelte
содержит только<slot />
, это фактически означает, что можно 'сбросить' на пустой макет для любой страницы или вложенного макета в приложении, добавив@root
.
Если родитель не указан, макет унаследует от ближайшего макета по умолчанию (т.е. безымянного) макета above в дереве. В некоторых случаях полезно, чтобы именованный макет унаследовал от макета по умолчанию наряду с ним в дереве, например, __layout-root.svelte
, наследующий от __layout.svelte
. Можно сделать это, явно указав @default
, разрешив /x/y/one
и братьям и сестрам использовать макет приложения по умолчанию без использования x/__layout.svelte
:
src/routes/
├ x/
│ ├ y/
│ │ ├ __layout@root.svelte
│ │ ├ one.svelte
│ │ ├ two.svelte
│ │ └ three.svelte
│ └ __layout.svelte
├ __layout.svelte
-└ __layout-root.svelte
+└ __layout-root@default.svelte
default
является зарезервированным именем - другими словами, нельзя назвать файл__layout-default.svelte
.
Страницы ошибок
Если страница не смогла загрузиться (см Загрузка данных), SvelteKit отобразит страницу ошибки. Вы можете настроить вид этой страницы, создав компонент __error.svelte
рядом с вашим макетом и страницами:
Например, если не удалось загрузить src/routes/settings/notifications/index.svelte
, SvelteKit отрисует src/routes/settings/notifications/__error.svelte
в том же макете, если он существует. В противном случае он отрисует src/routes/settings/__error.svelte
в родительском макете или src/routes/__error.svelte
в корневом макете.
В SvelteKit есть страница ошибок по умолчанию, если он не найдет файла
src/routes/__error.svelte
, но рекомендуется сделать свою.
Если в компоненте__error.svelte
есть функция load
, она будет вызываться со свойствами error
и status
:
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export function load({ error, status }) {
return {
props: {
title: `${status}: ${error.message}`
}
};
}
</script>
<script>
export let title;
</script>
<h1>{title}</h1>
Макеты также имеют доступ к
error
иstatus
через хранилище страницВо избежание того, чтобы пользователям стала доступна чувствительная информация, текст ошибок будет очищен от технических подробностей в продакшн режиме работы приложения.
404s
Вложенные страницы ошибок отображаются только тогда, когда возникает ошибка при рендеринге определенной страницы. В случае запроса, который не соответствует ни одному существующему маршруту, SvelteKit вместо этого отобразит общий 404. Например, учитывая эти маршруты...
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
...Файл marx-brothers/__error.svelte
не будет отображаться, если вы посетите /marx-brothers/karl
. Если вы хотите отобразить вложенную страницу ошибки, вы должны создать маршрут, соответствующий любому запросу /marx-brothers/*
, и вернуть из него 404:
src/routes/
├ __error.svelte
├ marx-brothers/
│ ├ __error.svelte
+│ ├ [...path].svelte
│ ├ chico.svelte
│ ├ harpo.svelte
│ └ groucho.svelte
/// file: src/routes/marx-brothers/[...path].svelte
<script context="module">
/** @type {import('./__types/[...path]').Load} */
export function load({ params }) {
return {
status: 404,
error: new Error(`Not found: /marx-brothers/${params.path}`)
};
}
</script>
Загрузка данных permalink
Компонент, определяющий страницу или макет, может экспортировать функцию load
, которая запускается до создания компонента. Эта функция выполняется как во время рендеринга на стороне сервера, так и в клиенте и позволяет извлекать данные и манипулировать ими до рендеринга страницы, что позволяет обойтись без индикаторов загрузки на странице.
Функция load
может не понадобиться, если данные для страницы поставляются с её эндпоинта. Это полезно, когда нужно больше гибкости, например, для загрузки данных с внешнего API, которая может выглядеть так:
/// file: src/routes/blog/[slug].svelte
<script context="module">
/** @type {import('./__types/[slug]').Load} */
export async function load({ params, fetch, session, stuff }) {
const url = `https://cms.example.com/article/${params.slug}.json`;
const response = await fetch(url);
return {
status: response.status,
props: {
article: response.ok && (await response.json())
}
};
}
</script>
Обратите внимание на
<script context="module">
— это необходимо, потому чтоload
выполняется до визуализации компонента. Код для каждого экземпляра компонента должен быть размещен во втором теге<script>
.
Как и в случае с эндпоинтами, страницы могут импортировать сгенерированные типы - ./[slug]
в приведенном выше примере - чтобы убедиться, что params
правильно набраны.
load
в SvelteKit является эквивалентом функциям getStaticProps
или getServerSideProps
в Next.js или asyncData
в Nuxt.js, за исключением того, что она работает как на сервере, так и на клиенте. В приведенном выше примере, если пользователь нажимает на ссылку на эту страницу, данные будут загуржены с cms.example.com
, не проходя через наш сервер.
Функция load
получает в аргументах метод fetch
, который имеет следующие специальные свойства:
- имеет доступ к файлам cookie на сервере
- может делать запросы к собственным эндпоинтам приложения без выполнения HTTP-запроса
- при использовании делает копию ответа и встраивает её в страницу при первом запросе для гидратации
load
может применяться только в компонентах страниц и макетов (но не в компонентах, которые они импортируют) и по умолчанию работает как на сервере, так и в браузере.
Код, который вызывается внутри функции
load
:
- должен использовать только свой метод
fetch
, а не нативныйfetch
- не должен ссылаться на
window
,document
или любые другие объекты, специфичные для браузера- не должен содержать каких-либо ключей для API или иных секретов, которые будут доступны клиенту, а вместо этого вызывать эндпоинт, который использует любые необходимые секреты
Рекомендуется не хранить состояние каждого запроса в глобальных переменных, а вместо этого использовать их только для межсекторальных проблем, таких как кэширование и хранение подключений к базе данных.
Мутирование любого общего состояния на сервере повлияет на всех клиентов, а не только на текущего.
Получаемые значения
Функция load
получает объект, содержащий 8 полей — url
, params
, props
, fetch
, session
, stuff
, status
, и error
. Функция load
является реактивной и будет повторно запущена при изменении значений её параметров, но только в том случае, если они используются в теле функции. В частности, если в функции используются url
, session
или stuff
, она будут повторно запущена всякий раз, когда их значения изменятся. Также это произойдет при изменении любых отдельных свойств объекта params
.
Обратите внимание, что деструктурирование параметров в объявлении функции уже означает их использование в функции.
url
url
- это экземпляр URL
, содержащий такие свойства, как origin
, hostname
, pathname
и searchParams
(который содержит разобранную строку запроса в виде объекта URLSearchParams
). url.hash
недоступен во время load
, так как он недоступен на сервере.
В некоторых средах этот параметр получается из заголовков запроса во время рендеринга на стороне сервера.Если вы используете adapter-node, например, вам может потребоваться настроить адаптер, чтобы URL был правильным.
params
params
получается из url.pathname
и имени файла маршрута.
Например, для имени файла маршрута src/routes/a/[b]/[...c]
и значении url.pathname
равным /a/x/y/z
, объект params
будет выглядеть следующим образом:
{
"b": "x",
"c": "y/z"
}
props
Если страница, которую вы загружаете, имеет эндпоинт, то возвращаемые из него данные для свойств страницы доступны внутри функции load
как объект props
. Для компонентов макета и страниц без эндпоинтов props
будет пустым объектом.
fetch
fetch
эквивалентен родному веб-API fetch
, с несколькими дополнительными функциями:
- его можно использовать для выполнения авторизованных запросов на сервере, так как он наследует заголовки
cookie
иauthorization
для запроса страницы - он может делать относительные запросы на сервере (обычно
fetch
требует URL-адрес с источником при использовании в контексте сервера) - запросы на эндпоинты поступают непосредственно в функцию обработчика во время рендеринга на стороне сервера, без накладных расходов на HTTP-вызов
- во время рендеринга на стороне сервера ответ будет захвачен и встроен в визуализированный HTML
- во время гидратации ответ будет считываться из HTML, гарантируя согласованность и предотвращая дополнительный сетевой запрос
Cookie будут переданы только в том случае, если целевой хост совпадает с хостом текущего приложения SvelteKit или его поддоменом.
session
session
может использоваться для передачи данных от сервера в текущий запрос, например идентификатор авторизованного пользователя. По умолчанию значение равно undefined
. См. getSession
в разделе Хуки
, чтобы узнать как использовать этот объект.
stuff
Объект stuff
передаётся из макетов дочерним макетам и страницам, и может содержать то, что нужно сделать доступным ниже. Для корневого компонента __layout.svelte
он будет равен {}
, но если функция load
этого компонента возвращает объект со свойством stuff
, оно будет доступно для всех функций load
из дочерних компонентов.
status
status
- это код состояния HTTP при отображении страницы ошибки или null
в противном случае.
error
error
- это ошибка, которая была выдана (или возвращена из предыдущей load
) при отображении страницы ошибки или null
в противном случае.
Возвращаемые значения
Если из load
возвращается промис, страница не будет отображаться, пока промис не исполнится. У возвращаемого объекта может быть несколько свойств, все они опциональны:
status
,error
,redirect
иcache
игнорируются при отображении страниц ошибок.
status
Код ответа HTTP сервера. Если возвращается error
– он должен быть из диапазонов 4xx
или 5xx
; при возвращении свойства redirect
код нужно установить в диапазон 3xx
. По умолчанию код ответа равен 200
.
error
Если при выполнении функции load
что-то пошло не так, поместите в это свойство объект Error
или просто строку, описывающую проблему, не забыв указать код ответа в свойстве status
равным числу в диапазонах 4xx
или 5xx
.
redirect
Если страница должна перенаправить пользователя на другую страницу (например, эта страница устарела, или пользователь должен сначала авторизоваться или ещё что-то), поместите в это свойство строку, содержащую путь по которому нужно переместить пользователя. Не забудьте указать код ответа в свойстве status
равным числу в диапазоне 3xx
.
Строка redirect
должна быть правильно закодированным URI. Допустимы как абсолютные, так и относительные URI.
cache
cache: {
"maxage": 300,
"private": false
}
Чтобы кэшировать страницы, верните объект cache
, содержащий свойство maxage
, установленное в number
, описывающий максимальный возраст страницы в секундах. При необходимости также включите свойство boolean
private
, указывающее, должен ли результирующий заголовок Cache-Control
быть private
или public
(это означает, что он может быть кэширован CDN в дополнение к отдельным браузерам).
Если
cache.private
являетсяundefined
, SvelteKit установит его автоматически, используя следующую эвристику: если функцияload
делаетfetch
учетных данных или страница используетsession
, она считается частной.
Это свойство может быть использовано только для страниц, но не для макетов.
props
Если функция load
возвращает объект props
, то он будет передан компоненту как его свойства, когда он будет отрисован.
stuff
Поля из этого объекта будут добавлены к существующим полям объекта stuff
, который будет предан в функции load
всех дочерних компонентов страниц и макетов.
Полный объект stuff
можно использовать в компонентах используя $page.stuff
из хранилища страницы. Таким образом для страниц обеспечивается механизм передачи данных "вверх", в макеты.
dependencies
Массив строк, представляющих URL-адреса, от которых зависит страница, которые впоследствии могут быть использованы с invalidate
, чтобы вызвать повторный запуск load
. Вам нужно добавить их в зависимости
, только если вы используете пользовательский API-клиент; URL-адреса, загруженные с предоставленной функцией fetch
, добавляются автоматически.
URL-адреса могут быть абсолютными или относительно загружаемой страницы и должны быть [закодированы] (https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding).
Хуки permalink
Необязательный файл src/hooks.js
(или src/hooks.ts
, или src/hooks/index.js
) может экспортировать четыре функции, которые будут запускаться на сервере — handle
, handleError
, getSession
и externalFetch
.
Расположение этого файла может быть настроено в опции
config.kit.files.hooks
handle
Эта функция запускается каждый раз, когда сервер SvelteKit получает request и формирует response. Это может происходить во время работы приложения или во время предварительной отрисовки. Она получает объект event
, представляющий запрос, и функцию resolve
, которая вызывает маршрутизатор SvelteKit и генерирует ответ (отображает страницу или вызывает эндпоинт). Это позволяет изменять заголовки или тело ответов или полностью обойти SvelteKit (например, для программной реализации эндпоинтов).
/// file: src/hooks.js
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
if (event.url.pathname.startsWith('/custom')) {
return new Response('custom response');
}
const response = await resolve(event);
return response;
}
Запросы статический ресурсов, включая предварительно отрисованные страницы, не обрабатываются SvelteKit.
Если не реализовано, по умолчанию используется ({ event, resolve }) => resolve(event)
. Чтобы добавить пользовательские данные к запросу, который передается конечным точкам, заполните объект event.locals
, как показано ниже.
/// file: src/hooks.js
// @filename: ambient.d.ts
type User = {
name: string;
}
declare namespace App {
interface Locals {
user: User;
}
interface Platform {}
interface Session {}
interface Stuff {}
}
const getUserInformation: (cookie: string | null) => Promise<User>;
// declare global {
// const getUserInformation: (cookie: string) => Promise<User>;
// }
// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
event.locals.user = await getUserInformation(event.request.headers.get('cookie'));
const response = await resolve(event);
response.headers.set('x-custom-header', 'potato');
return response;
}
Можно добавить вызов нескольких функций handle
используя хелпер sequence
.
В resolve
можно передать второй необязательный параметр, который даёт больше контроля над тем, как будет отображаться ответ. Этот параметр является объектом, который может иметь следующие поля:
ssr: boolean
(defaulttrue
) - еслиfalse
, отображает пустую страницу 'shell' вместо рендеринга на стороне сервераtransformPage(opts: { html: string }): string
— применяет пользовательские преобразования к HTML
/// file: src/hooks.js
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
const response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/admin'),
transformPage: ({ html }) => html.replace('old', 'new')
});
return response;
}
Отключение отрисовки на стороне сервера фактически превращает приложение SvelteKit в одностраничное приложение или SPA. В большинстве ситуаций это не рекомендуется (см. термин SSR). Решите, действительно ли уместно его полностью отключать или сделайте это выборочно, а не для всех запросов.
handleError
Если ошибка возникает во время рендеринга, эта функция будет вызвана с параметрами error
и event
. Это позволяет отправлять данные в сервис отслеживания ошибок или форматировать сообщение для вывода в консоли.
Если, в режиме разработки, возникает синтаксическая ошибка в коде Svelte, будет добавлен параметр frame
, указывающий на местоположение ошибки.
Если данный хук не задан, SvelteKit отобразит ошибку с форматированием по умолчанию.
/// file: src/hooks.js
// @filename: ambient.d.ts
const Sentry: any;
// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').HandleError} */
export async function handleError({ error, event }) {
// пример интеграции с https://sentry.io/
Sentry.captureException(error, { event });
}
handleError
вызывается только в случае, если ошибка не была поймана ранее в коде. Также хук не вызывается, когда страницы и эндпоинты явно отвечают кодами состояния 4xx и 5xx.
getSession
Эта функция принимает объект event
и возвращает объект session
, который доступен на клиенте и, следовательно, должен быть безопасным для предоставления пользователям. Он запускается всякий раз, когда SvelteKit выполняет рендеринг страницы на сервере.
Если функция не задана, объект сессии будет равен {}
.
/// file: src/hooks.js
// @filename: ambient.d.ts
declare namespace App {
interface Locals {
user: {
name: string;
email: string;
avatar: string;
token: string;
}
}
interface Session {
user?: {
name: string;
email: string;
avatar: string;
}
}
}
type MaybePromise<T> = T | Promise<T>;
// @filename: index.js
// ---cut---
/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
return event.locals.user
? {
user: {
// передайте только поля нужные на клиенте —
// исключите любые другие поля объекта user
// вроде токенов, паролей и т.п.
name: event.locals.user.name,
email: event.locals.user.email,
avatar: event.locals.user.avatar
}
}
: {};
}
Объект
session
должен быть сериализуемым, то есть не должен содержать вещей вроде функций или классов, только встроенные в JavaScript типы данных.
externalFetch
Эта функция позволяет изменять (или заменять) запрос fetch
для внешнего ресурса внутри функции load
, которая выполняется на сервере (или во время предварительной отрисовки).
Например, когда есть страница с функцией load
, которая на клиенте делает запрос на публичный URL-адрес(например https://api.yourapp.com
) какого-либо внутреннего сервиса, то во время отрисовки на сервере имеет смысл выполнить запрос к сервису локально, минуя прокси-серверы и балансировщики.
/** @type {import('@sveltejs/kit').ExternalFetch} */
export async function externalFetch(request) {
if (request.url.startsWith('https://api.yourapp.com/')) {
// копируем исходный запрос, но заменяем URL-адрес
request = new Request(
request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request
);
}
return fetch(request);
}
Модули permalink
В SvelteKit есть несколько модулей, которые доступны в приложении.
$app/env
/// <reference types="@sveltejs/kit" />
// ---cut---
import { amp, browser, dev, mode, prerendering } from '$app/env';
amp
равен либоtrue
, либоfalse
в зависимости от соответствующего значения в конфигурации проектаbrowser
будет равенtrue
илиfalse
если приложение запущено соответственно в браузере или на сервереdev
равенtrue
в режиме разработки,false
в рабочем режимеmode
- это Vite mode, по-умолчаниюdevelopment
в режиме разработки илиproduction
во время сборки, если иное не настроено вconfig.kit.vite.mode
.prerendering
равенtrue
во время предварительной отрисовки, иначеfalse
$app/navigation
/// <reference types="@sveltejs/kit" />
// ---cut---
import {
afterNavigate,
beforeNavigate,
disableScrollHandling,
goto,
invalidate,
prefetch,
prefetchRoutes
} from '$app/navigation';
afterNavigate(({ from, to }: { from: URL, to: URL }) => void)
- функция жизненного цикла, которая запускается при первоначальной отрисовке компонента, а также при каждой последующей навигации, пока компонент остается в отрисованным.beforeNavigate(({ from, to, cancel }: { from: URL, to: URL | null, cancel: () => void }) => void)
— функция, которая запускается всякий раз, когда происходит навигация, будь то нажатие на ссылку, вызовgoto
или перемещение по истории браузера. Также она будет запущена и при переходе на внешние сайты. Если пользователь закрывает страницу, то вto
будет значениеnull
. Вызовcancel
остановит выполнение перехода.disableScrollHandling
запретит SvelteKit применить его обычное управление прокруткой страницы, если вызывается когда страница обновляется после перехода (например, вonMount
или действии). Лучше избегать использования этой функции, чтобы не дезориентировать пользователей.goto(href, { replaceState, noscroll, keepfocus, state })
возвращаетPromise
, который резолвится при навигации SvelteKit к указанномуhref
(ошибка в навигации отклоняет промис). Второй аргумент является необязательным:replaceState
(boolean, по умолчаниюfalse
) Еслиtrue
, заменит текущую записьhistory
, а не создаст новую черезpushState
noscroll
(boolean, по умолчаниюfalse
) Еслиtrue
, браузер сохранит свое положение прокрутки, а не прокрутит в верхнюю часть страницы после навигацииkeepfocus
(boolean, по умолчаниюfalse
) Еслиtrue
, текущий сфокусированный элемент сохранит фокус после навигации. В противном случае фокус будет сброшенstate
(объект, по умолчанию{}
) Состояние новой/обновленной записи истории
invalidate(href)
перезапускает все функцииload
, которые нужны для текущей активной страницы для повторной загрузки необходимых ресурсов. Возвращает объектPromise
, который разрешается, когда страница обновится новыми данными.prefetch(href)
программно выполняет упреждающую загрузку указанной страницы, что означает: а) обеспечение полной загрузки кода для страницы и б) вызов методаload
страницы с соответствующими параметрами. Это поведение, аналогично случаю, когда пользователь касается на сенсорном экране или проводит курсором над элементом<a>
с установленным атрибутом sveltekit:prefetch. Если следующий переход будет по путиhref
, то будет использовано значение, которое вернула функцияload
, что сделает перемещение мгновенным. Возвращает объектPromise
, который разрешается, когда упреждающая загрузка будет завершена.prefetchRoutes(routes)
— программно выполняет упреждающую загрузку кода для маршрутов, которые ещё не были загружены до этого. Обычно используется для ускорения переходов по нижестоящим маршрутам. Если не передавать аргументов, то будут предзагружены все маршруты, но можете указать маршруты по любому подходящему пути, например,/about
(дляsrc/routes/about.svelte
) или/blog/*
(дляsrc/routes/blog/[slug].svelte
). В отличие отprefetch
не вызывает функциюload
для каждой из загружаемых страниц. Возвращает объектPromise
, который разрешается, когда упреждающая загрузка всех маршрутов будет завершена.
$app/paths
/// <reference types="@sveltejs/kit" />
// ---cut---
import { base, assets } from '$app/paths';
base
— строка с путём, относительно корня (т.е. начинается с/
), которая соответствует параметруconfig.kit.paths.base
в конфигурации проектаassets
— путь от корня или абсолютный путь который соответствует параметруconfig.kit.paths.assets
(после его разрешения относительноbase
)
Если указано значение
config.kit.paths.assets
, во время выполненияsvelte-kit dev
илиsvelte-kit preview
оно будет подменяться на'/_svelte_kit_assets'
, так как статические ресурсы ещё не размещены по их окончательному URL-адресу.
$app/stores
/// <reference types="@sveltejs/kit" />
// ---cut---
import { getStores, navigating, page, session, updated } from '$app/stores';
Эти хранилища зависят от контекста, так как они добавляются в контекст корневого компонента приложения. Это значит, что хранилища session
и page
будут уникальны для каждого запроса на сервер и не будут предоставлять одну и ту же информацию в нескольких запросах сразу. Поэтому можно безопасно хранить в session
данные конкретного пользователя.
По этой причине доступ к хранилищу можно получить только во время инициализации компонента, как и в случае с любой функцией, которая использует метод getContext
внутри.
getStores
— это удобная функция-оболочка вокругgetContext
, которая возвращает{ navigating, page, session, updated }
. Её необходимо вызывать на верхнем уровне или синхронно во время инициализации компонента или страницы.
Хранилища сами определяют нужный контекст, когда выполняется подписка на них, что означает, что вы можете импортировать и использовать их непосредственно в компонентах без лишней обвязки. Тем не менее, их его всё ещё нужно вызывать синхронно при инициализации компонента или страницы, когда не используется префикс $
. Вместо этого используйте getStores
, чтобы безопасно асинхронно выполнить .subscribe
.
navigating
- это хранилище. В процессе перехода при навигации его значением становится объект{ from, to }
, гдеfrom
иto
являются экземплярамиURL
. Когда переход завершается, его значение возвращается кnull
.page
содержит объект с текущимиurl
,params
,stuff
,status
иerror
.session
– хранилище, начальное значение которого получается из функцииgetSession
. Значение в хранилище можно изменять, но эти изменения не будут сохранены на сервере – при необходимости это нужно имплементировать самостоятельно.updated
- это хранилище, начальное значение которого равноfalse
. Если в конфигурации заданversion.pollInterval
, SvelteKit будет периодически проверять новую версию приложения на сервере и как только обнаружит её, обновит значение хранилища доtrue
. Вызов методаupdated.check()
принудительно проверит новую версию на сервере, независимо от настроек опроса.
$lib
Это простой псевдоним для директории src/lib
, или иной директории указанной в config.kit.files.lib
. Он позволит обращаться к общим компонентам и утилитам без использования множества ../../../../
в путях импорта.
$service-worker
Этот модуль доступен только в сервис-воркерах.
/// <reference types="@sveltejs/kit" />
// ---cut---
import { build, files, timestamp } from '$service-worker';
build
– массив строк URL-путей до файлов сгенерированных Vite, используется для кеширования при помощи функцииcache.addAll(build)
files
- это массив строк URL, представляющих файлы в вашем каталогеstatic
или любой другой каталог, указанныйconfig.kit.files.assets
. Вы можете настроить, какие файлы включаются из каталогаstatic
, используяconfig.kit.serviceWorker.files
timestamp
– результат вызова функцииDate.now()
во время сборки. Полезно для генерации уникальных имён для кешей внутри сервис-воркера, что позволит инвалидировать устаревшие кеши у клиентов при запуске новой версии приложения.
@sveltejs/kit/hooks
Этот модуль содержит хелпер-функцию sequence
для создания последовательности из нескольких вызовов в handle
.
/// file: src/hooks.js
/// <reference types="@sveltejs/kit" />
// ---cut---
import { sequence } from '@sveltejs/kit/hooks';
/** @type {import('@sveltejs/kit').Handle} */
async function first({ event, resolve }) {
console.log('первая пред-обработка');
const result = await resolve(event);
console.log('первая пост-обработка');
return result;
}
/** @type {import('@sveltejs/kit').Handle} */
async function second({ event, resolve }) {
console.log('вторая пред-обработка');
const result = await resolve(event);
console.log('вторая пост-обработка');
return result;
}
export const handle = sequence(first, second);
Пример выше распечатает:
первая пред-обработка
вторая пред-обработка
вторая пост-обработка
первая пост-обработка
Сервис-воркеры permalink
Сервис-воркеры выступают в роли прокси-серверов, которые обрабатывают сетевые запросы внутри вашего приложения. Это позволяет сделать приложение, которое сможет работать в Offline-режиме, но даже если поддержка работы без сети не требуется(или она невозможна из-за особенностей работы приложения), то сервис-воркер может ускорить навигацию кешированием JS и CSS файлов приложения.
Если в проекте SvelteKit есть файл src/service-worker.js
(или src/service-worker.ts
, или src/service-worker/index.js
) он будет собран в Vite и автоматически зарегистрирован. Вы можете отключить автоматическую регистрацию, если вам нужно зарегистрировать сервис-воркера со своей собственной логикой (например, запросить у пользователя обновление, настроить периодические обновления, использовать workbox
и т. д.).
Вы можете изменить местоположение сервис-воркера и отключить автоматическую регистрацию в конфигурации вашего проекта.
Внутри сервис-воркера есть доступ к модулю $service-worker
.
Файл сервис-воркера должен пройти через процесс сборки, поскольку браузеры ещё не поддерживают import
в этом контексте. Кроме того сервис-воркер зависит от манифеста сборки клиентской части приложения. В следствие чего, сервис-воркеры работают только в рабочей сборке, но не в режиме разработки. Чтобы протестировать его работу локально, запустите проект командой svelte-kit preview
.
Атрибуты ссылок permalink
sveltekit:prefetch
SvelteKit использует разделение кода, чтобы разбить приложение на небольшие фрагменты (по одному на маршрут), обеспечивая быстрое время запуска.
Для динамических маршрутов, таких как src/routes/blog/[slug].svelte
, этого недостаточно. Чтобы отобразить сообщение в блоге, нужно получить для него данные, и мы не сможем этого сделать, пока не узнаем значение slug
. В худшем случае это может вызвать задержку, поскольку браузер будет ждать данные от сервера.
Сгладить ситуацию можно предварительно собрав данные, добавив атрибут sveltekit:prefetch
...
<a sveltekit:prefetch href="blog/what-is-sveltekit">Что такое SvelteKit?</a>
...который заставит SvelteKit запустить функцию load
как только пользователь наведёт курсор мыши на ссылку или коснётся её на мобильном устройстве, вместо того, чтобы дожидаться события click
, которое выполнит переход на страницу. Обычно это даст нам дополнительную пару сотен миллисекунд, что как раз является той разницей, которая существует между быстрым пользовательским интерфейсом, и тем, который кажется медленным.
Обратите внимание, что предварительная загрузка данных не будет работать, если значение router
установлено в false
.
Вы также можете программно вызвать prefetch
из $app/navigation
.
sveltekit:reload
По умолчанию среда выполнения SvelteKit перехватывает клики по элементам <a>
и блокирует обычную навигацию браузера для относительных URL-адресов, соответствующих одному из маршрутов страниц. Иногда нужно сообщить SvelteKit, что определённые ссылки должны обрабатываться с помощью обычной навигации браузера. Примерами этого могут быть ссылка на другую страницу в вашем домене, которая не является частью вашего приложения SvelteKit, или ссылка на эндпоинт.
Добавление атрибута sveltekit:reload
к ссылке...
<a sveltekit:reload href="path">Path</a>
... запустит навигацию браузера с перезагрузкой страницы при нажатии на ссылку.
Ссылки с атрибутом rel="external"
получат такую же обработку. Кроме того, они будут проигнорированы во время пререндера.
sveltekit:noscroll
При переходе по внутренним ссылкам SvelteKit придерживается поведения навигации браузера по умолчанию: он изменяет положение прокрутки на 0,0, чтобы пользователь находился в самом верхнем левом углу страницы (если только ссылка не содержит #hash
, тогда он перейдёт к элементу с соответствующим идентификатором).
В некоторых случаях такое поведение нежелательно. Добавление атрибута sveltekit:noscroll
...
<a href="path" sveltekit:noscroll>Path</a>
... предотвратит прокрутку после перехода по ссылке.
События permalink
SvelteKit по команде sveltekit:start
запускает пользовательские события на объекте window
после гидратации приложения:
Возможно, вам не понадобится их использовать, но они могут быть полезны, например, в интеграционных тестах.
Адаптеры permalink
Прежде чем развернуть готовое приложение SvelteKit на сервере или сервисе, его необходимо адаптировать под то окружение, в котором оно будет работать. Адаптеры - это небольшие плагины, которые на вход принимают созданное приложение и на выходе генерируют приложение, подготовленное для развертывания в определенном окружении.
По умолчанию проекты настроены на использование @sveltejs/adapter-auto
, который сам определяет окружение и выбирает соответствующий адаптер, где это возможно. Если же требуемая платформа пока не поддерживается, можно подключить один из адаптеров от сообщества или написать свой.
См. adapter-auto README для получения информации о добавлении поддержки новых окружений.
Поддерживаемые платформы
SvelteKit предлагает ряд официально поддерживаемых адаптеров.
Вы можете выполнить развертывание на следующих платформах с адаптером по умолчанию, adapter-auto
:
- Cloudflare Pages через
adapter-cloudflare
- [Netlify] (https://netlify.com) через
adapter-netlify
- Vercel через
adapter-vercel
Node.js
Чтобы создать простой Node-сервер, установите пакет @sveltejs/adapter-node
и обновите svelte.config.js
:
/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
После этого svelte-kit build сгенерирует автономное приложение Node в директории build
. Вы можете передать адаптерам параметры, например указать директорию для полученного приложения:
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
- adapter: adapter()
+ adapter: adapter({ out: 'my-output-directory' })
}
};
Статические сайты
Большинство адаптеров будут генерировать статический HTML для любых страниц, которые возможно предварительно отрисовать. В некоторых случаях, когда можно предварительно отрисовать всё приложение, используйте @sveltejs/adapter-static
для генерации статического HTML кода для всех страниц. Полностью статический сайт может быть размещен на самых разных платформах и хостингах, включая GitHub Pages.
/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-static';
Также adapter-static
можно использовать для создания одностраничных приложений (SPA), указав корневую страницу.
Вы должны убедиться, что
trailingSlash
настроен соответствующим образом для вашей среды. Если ваш хост не отображает/a.html
при получении запроса на/a
, вам нужно будет установитьtrailingSlash: 'always'
для создания/a/index.html
.
Контекст платформы
Некоторые адаптеры могут иметь доступ к дополнительной информации о запросе. Например, Cloudflare Workers может получить доступ к объекту env
, содержащему пространства имен KV и т. д. Эта информация может быть передана как свойство platform
в объекте RequestEvent
, который используется в хуках и эндпоинтах. Ознакомьтесь с документацией нужного адаптера, чтобы узнать больше.
Адаптеры сообщества
Для других платформ существуют дополнительные адаптеры от сообщества. После установки соответствующего адаптера с помощью менеджера пакетов обновите svelte.config.js
:
/// file: svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from 'svelte-adapter-[x]';
Создание адаптера
Мы рекомендуем скопировать и взять за основу адаптер для платформы, которая близка к нужной.
Пакеты адаптеров должны реализовывать следующий API, который создает Adapter
:
// @filename: ambient.d.ts
const AdapterSpecificOptions = any;
// @filename: index.js
// ---cut---
/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
const adapter = {
name: 'adapter-package-name',
async adapt(builder) {
// имплементация адаптера
}
};
return adapter;
}
Типы для Adapter
и его параметры доступны в types/config.d.ts.
Есть ряд вещей, которые должны быть выполнены внутри метода adapt
:
- Очищает директорию готовой сборки
- Записывает вывод SvelteKit с помощью
builder.writeClient
,builder.writePrerendered
,builder.writeServer
иbuilder.writeStatic
- Создаёт код, который:
- Импортирует
Server
из${builder.getServerDirectory()}/index.js
- Создаёт экземпляр приложения со сгенерированным методом
builder.generateManifest({ relativePath })
манифестом. - Слушает запросы с платформы и преобразует их в стандартный Request, при необходимости вызывает функцию
server.respond(request, { getClientAddress })
для создания Response и отвечает ей - Глобально настроит
fetch
для работы на целевой платформе. SvelteKit предоставляет хелпер@sveltejs/kit/install-fetch
для платформ, которые могут использоватьnode-fetch
- Импортирует
- При необходимости, соберает модули приложения в единый бандл, чтобы избежать установки зависимостей на целевой платформе
- Помещает статические файлы пользователя и сгенерированные JS/CSS в правильное место для целевой платформы
При возможности, мы рекомендуем помещать готовое приложение в директорию build/
, а любые промежуточные данные в директории '.svelte-kit/' + имя_адаптера
.
API адаптера может меняться до версии 1.0.
Параметры страницы permalink
По умолчанию SvelteKit сначала отрисовывает любой компонент на сервере и отправляет его клиенту в формате HTML. Затем он снова отрисует компонент в браузере, чтобы сделать его интерактивным в процессе, который называется гидратация. Поэтому необходимо следить, чтобы компоненты могли работать как на сервере, так и в браузере. В конце SvelteKit инициализирует клиентский роутер, который берет на себя последующие переходы между страниц.
Каждый из этих шагов можно контролировать как во всём приложении сразу, так и отдельно для каждой страницы. Обратите внимание, что все настройки, которые указываются для конкретных страниц, помещаются в блок script
с атрибутом context="module"
и применяются только к страницам, но не к макетам.
В случае конфликта глобальных настроек и настроек отдельной страницы, последние будут иметь приоритет.
router
В SvelteKit есть клиентский роутер, который отслеживает переходы (клик по ссылке или по кнопкам истории браузера) и обновляет содержимое страницы, при этом не происходит перезагрузки страницы, как при обычной навигации в браузере.
В некоторых случаях может потребоваться отключить клиентский роутер параметром browser.router
в конфигурации приложения или для отдельной страницы, экспортировав router
:
<script context="module">
export const router = false;
</script>
Это отключит роутер для всех переходов с текущей страницы, даже если он уже используется в приложении.
hydrate
По умолчанию SvelteKit гидратирует полученный с сервера HTML, чтобы получить интерактивную страницу. Некоторым страницам совершенно не нужен JavaScript – например, различного рода посты в блоге или страницы 'О сайте'. В таких случаях можно отключить гидратацию при загрузке приложения глобальным параметром browser.hydrate
в конфигурации или для конкретной страницы, экспортировав константу hydrate
:
<script context="module">
export const hydrate = false;
</script>
Если и
hydrate
иrouter
будут оба равныfalse
, SvelteKit вообще не добавит на страницу никакого JavaScript кода. Если рендеринг на стороне сервера отключен вhandle
,hydrate
должен бытьtrue
, иначе содержимое не будет отображаться.
prerender
Иногда некоторые страницы приложения могут быть представлены в виде простого HTML-файла, созданного во время сборки. Эти страницы могут быть предварительно отрисованы выбранным адаптером.
Предварительная отрисовка происходит автоматически для любой страницы с аннотацией prerender
:
<script context="module">
export const prerender = true;
</script>
Кроме того, вы можете установить config.kit.prerender.default
в true
и предварительно отрисовать все, кроме страниц, которые явно помечены как not prerenderable:
<script context="module">
export const prerender = false;
</script>
Если все ваше приложение подходит для предварительного рендеринга, вы можете использовать
adapter-static
, который выведет файлы, подходящие для использования с любым статическим веб-сервером.
Отрисовка начнется с корня приложения и будут сгенерированы HTML-файлы для всех найденных страниц, подходящих для пререндера. Каждая страница сканируется на предмет элементов <a>
, которые указывают на другие страницы, которые тоже могут быть отрисованы - поэтому нет необходимости явно указывать какие именно страницы нужно обработать. При необходимости, список страниц, которые должны быть предварительно отрисованы, можно задать в параметре entries
в разделе конфигурации prerender
.
Когда не делать пререндер
Основное правило таково: для того, чтобы страница могла быть предварительно отрисована, любые два пользователя, попадающие на одну и ту же страницу приложения, должны получать с сервера одно и то же содержимое.
Не все страницы подходят для пререндеринга. Любое содержимое, которое отрисовано таким образом, видно всем пользователям. Конечно, можно получать персональные данные в
onMount
на такой странице, но это может ухудшить пользовательский опыт, поскольку придется дожидаться получения данных, наблюдая индикатор загрузки.
Обратите внимание, что предварительную отрисовка всё ещё можно сделать для приложения с динамическими маршрутами, как в нашем примере src/routes/blog/[slug].svelte
. Адаптер adapter-static будет обрабатывать запросы к серверу внутри функций load
, поэтому данные, поступающие из src/routes/blog/[slug].json.js
тоже будут сохранены.
Во время предварительной отрисовки нет доступа к объекту url.searchParams
. Если его необходимо использовать на странице, убедитесь, что обращение к нему происходит только в браузере (например, в функции onMount
).
Конфликты маршрутов
Поскольку пререндер создаёт отражение всех маршрутов в виде файлового дерева, то невозможно иметь два эндпоинта, где возникает ситуация, что директория и файл в одном и том же месте будут иметь одинаковое имя. Например, src/routes/foo/index.js
и src/routes/foo/bar.js
будут пытаться создать файлы foo
и foo/bar
, что приведёт к ошибке.
По этой причине, рекомендуется всегда добавлять расширение к имени файла — например, src/routes/foo/index.json.js
и src/routes/foo/bar.json.js
будут сохранены как foo.json
и foo/bar.json
, которые не будут мешать друг другу.
Для маршрутов страниц этой проблемы не возникает, поскольку создаётся файл foo/index.html
, а не foo
.
Создание пакетов permalink
svelte-kit package
в настоящее время является экспериментальным и не подпадает под действие правил семантического управления версиями. Несовместимые с обратной связью изменениями могут произойти в любом будущем выпуске.
Кроме создания web-приложений SvelteKit можно использовать также и для библиотек компонентов.
Содержимое папки src/routes
является основой для приложения. А папка src/lib
просто хранит файлы внутренних библиотек.
Библиотека компонентов в SvelteKit имеет точно такую же структуру папок, но src/lib
становится основой библиотеки, а src/routes
может быть использована для документации или демо-сайта, показывающего работу библиотеки. Также можно использовать эту папку как "песочницу" во время разработки компонента.
Запуск команды svelte-kit package
сгенерирует пакет в новой папке package
(которую можно настроить), содержащий следующие файлы:
- Все файлы из папки
src/lib
, если не указаны какие-либо параметрыinclude
/exclude
. Компоненты Svelte будут предварительно обработаны, файлы TypeScript будут преобразованы в JavaScript. - Определения типов (файлы
d.ts
), которые генерируются для файлов Svelte, JavaScript и TypeScript. Для этого вам нужно установитьtypescript >= 4.0.0
иsvelte2tsx >= 0.4.1
. Определения типов размещаются рядом с их реализацией, рукописные файлыd.ts
копируются как есть. Можно отключить генерацию этих файлов, но мы настоятельно рекомендуем не делать этого. - Файл
package.json
, скопированный из корня проекта, со всеми полями, кроме поля"scripts"
. Список зависимостей"dependencies"
тоже будет скопирован, поэтому добавляйте пакеты, которые нужны для документации или демо-сайта, в поле"devDependencies"
. Также будут добавлены поля"type": "module"
и"exports"
, если в исходном файле их нет.
Поле "exports"
содержит файлы, которые будут доступны из модуля. По умолчанию сюда попадут все файлы из папкиsrc/lib
, только если их имя(или имя папки, в которых они содержатся) не начинаются с символа нижнего подчёркивания. Это поведение можно изменить. Если имеется файл src/lib/index.js
или src/lib/index.svelte
, то он станет корнем пакета.
Например, если имеется компонент src/lib/Foo.svelte
и модуль src/lib/index.js
, который реэкспортирует его, то пользователь вашего пакета сможет импортировать компонент любым из двух способов:
// @filename: ambient.d.ts
declare module 'your-library';
// @filename: index.js
// ---cut---
import { Foo } from 'your-library';
// @filename: ambient.d.ts
declare module 'your-library/Foo.svelte';
// @filename: index.js
// ---cut---
import Foo from 'your-library/Foo.svelte';
Публикация
Для публикации полученного пакета выполните команду:
npm publish ./package
Приведенный выше package
относится к сгенерированному имени каталога, измените его соответствующим образом, если вы указываете иную директорию в package.dir
.
Ограничения
Это относительно экспериментальная функция, которая ещё не полностью реализована. Все файлы, кроме файлов Svelte (предварительно обработанных) и файлов TypeScript (переработанных в JavaScript), копируются как есть.
svelte-kit CLI permalink
SvelteKit включает в себя утилиту для создания и запуска вашего приложения.
В шаблоне проекта по умолчанию команды svelte-kit dev
, svelte-kit build
, svelte-kit preview
имеют псевдонимы – соответственно npm run dev
, npm run build
и npm start
. Также можно вызвать CLI-утилиту с помощью npx:
npx svelte-kit dev
svelte-kit dev
Запускает сервер для разработки. Принимает следующие параметры:
-p
/--port
— порт, на котором запустить сервер-o
/--open
— открыть вкладку браузера после запуска сервера--host
— открыть доступ к серверу из сети.
Используйте это с осторожностью!
--https
— запустить HTTPS-сервер используя самоподписанный SSL сертификат. Полезно для тестирования функций, поддерживающих только HTTPS, на внешнем устройстве.
Эта команда завершится неудачей, если указанный (или по умолчанию) порт недоступен. Чтобы использовать альтернативный порт вместо сбоя, установите параметр
config.kit.vite.server.strictPort
вfalse
.
svelte-kit build
Создаёт готовую к работе версию приложения и запускает нужный адаптер, если он указан в файле конфигурации. Команда принимает один параметр:
--verbose
— выводить больше информации
svelte-kit preview
После сборки приложения командой svelte-kit build
, можно запустить его локально с помощью команды svelte-kit preview
(вне зависимости от используемого адаптера). Эта команда предназначена для тестирования собранного приложения локально. При запуске приложения на рабочем сервере вы всегда должны использовать адаптер.
Как и svelte-kit dev
, эта команда принимает следующие параметры:
-p
/--port
-o
/--open
--host
--https
svelte-kit package
svelte-kit package
в настоящее время является экспериментальным и не подпадает под действие правил семантического управления версиями. Несовместимые с обратной связью изменениями могут произойти в любом будущем выпуске.
Для авторов пакетов см. Создание пакетов. Скрипт svelte-kit package
принимает следующие опции:
-w
/--watch
— наблюдать изменения файлов в папкеsrc/lib
и пересобирать пакет.
Конфигурация permalink
Конфигурация проекта находится в файле svelte.config.js
. Все значения необязательны. Полный список параметров со значениями по умолчанию показан здесь:
/** @type {import('@sveltejs/kit').Config} */
const config = {
// параметры для svelte.compile (https://svelte.dev/docs#svelte_compile)
compilerOptions: {},
// массив расширений, которые будут считаться компонентами Svelte
extensions: ['.svelte'],
kit: {
adapter: undefined,
appDir: '_app',
browser: {
hydrate: true,
router: true
},
csp: {
mode: 'auto',
directives: {
'default-src': undefined
// ...
}
},
files: {
assets: 'static',
hooks: 'src/hooks',
lib: 'src/lib',
params: 'src/params',
routes: 'src/routes',
serviceWorker: 'src/service-worker',
template: 'src/app.html'
},
floc: false,
inlineStyleThreshold: 0,
methodOverride: {
parameter: '_method',
allowed: []
},
outDir: '.svelte-kit',
package: {
dir: 'package',
// кроме файлов .d.ts и начинающихся с нижнего подчеркивания
exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
files: () => true,
emitTypes: true
},
paths: {
assets: '',
base: ''
},
prerender: {
concurrency: 1,
crawl: true,
default: false,
enabled: true,
entries: ['*'],
onError: 'fail'
},
routes: (filepath) => !/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/.test(filepath),
serviceWorker: {
register: true,
files: (filepath) => !/\.DS_Store/.test(filepath)
},
trailingSlash: 'never',
version: {
name: Date.now().toString(),
pollInterval: 0
},
vite: () => ({})
},
// SvelteKit использует vite-plugin-svelte. Здесь можно указать его параметры.
// Список параметров см. на https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md
// Параметры для svelte.preprocess (https://svelte.dev/docs#svelte_preprocess)
preprocess: null
};
export default config;
adapter
Требуется при запуске svelte-kit build
и определяет, как преобразуется вывод для разных платформ. См. Адаптеры.
alias
Объект, содержащий ноль или более псевдонимов, используемых для замены значений в инструкциях import
. Эти псевдонимы автоматически передаются в Vite и TypeScript.
Например, вы можете добавить псевдонимы в папку components
и utils
:
/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
alias: {
$components: 'src/components',
$utils: 'src/utils'
}
}
};
Встроенный псевдоним
$lib
контролируетсяconfig.kit.files.lib
, поскольку он используется для упаковки.
appDir
Директория относительно paths.assets
в которой будут находиться скомпилированные JS/CSS файлы и импортированные статические ресурсы. Имена файлов в этой директории будут содержать хеши на основе их содержимого, то есть эти файлы можно кэшировать на неопределённый срок. Значение параметра не должно начинаться или заканчиваться на /
.
browser
Объект, содержащий ноль или более из следующих значений типа boolean
:
hydrate
— следует ли гидратировать серверный HTML с помощью клиентского приложения. Устанавливайте этот параметр вfalse
только в исключительных случаях.router
- включает или отключает клиентский роутер по всему приложению.
csp
Объект, содержащий ноль или более из следующих значений:
mode
- 'hash', 'nonce' или 'auto'directives
— объект, содержащий пары[директива]: значения[]
.
Настройка Content Security Policy. CSP помогает защитить пользователей от XSS-атак, ограничивая места, из которых могут загружаться ресурсы. Например, такая конфигурация...
/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
csp: {
directives: {
'script-src': ['self']
}
}
}
}
export default config;
...позволит предотвратить загрузку скриптов с внешних сайтов. Для любых инлайновых стилей и генерируемых скриптов SvelteKit автоматически дополнит указанные директивы нужным хешем(в зависимости от mode
).
При предварительной отрисовке страниц заголовок CSP добавляется с помощью тега <meta http-equiv>
(учтите, что в этом случае директивы frame-ancestors
, report-uri
и sandbox
будут игнорироваться).
При значении
mode: 'auto'
, SvelteKit будет использовать аттрибуты nonce для динамических страниц и аттрибуты hashe для предварительно отрисованных. Использование аттрибута nonce с предварительно отрисованными страницами небезопасно а, значит, запретно.
endpointExtensions
Массив расширений файлов, которые SvelteKit будет рассматривать как эндпоинты. Файлы с расширениями, которые не соответствуют ни config.extensions
, ни config.kit.endpointExtensions
, будут игнорироваться маршрутизатором.
files
Объект, содержащий следующие строковые параметры(все опциональны):
assets
— место для размещения статических файлов, которые должны иметь стабильные URL-адреса и не подвергаться обработке, напримерfavicon.ico
иmanifest.json
hooks
— путь к файлу хуков (см. Хуки)lib
— внутренняя библиотека вашего приложения, доступная во всей кодовой базе как$lib
params
- каталог, содержащий сопоставление параметровroutes
— файлы, которые определяют структуру вашего приложения (Маршруты)serviceWorker
— файл сервис-воркераtemplate
— расположение шаблона для HTML-ответов сервера
floc
Google FLoC — это технология таргетированной рекламы, которую Electronic Frontier Foundation сочла вредной для конфиденциальности пользователей. Браузеры, отличные от Chrome отказались её реализовать.
SvelteKit по умолчанию отключает использование FLoC в приложении, также как это делают другие сервисы, например GitHub Pages. Если для параметра floc
не установлено значение true
, к ответу сервера будет добавлен такой заголовок:
Permissions-Policy: Interest-cohort = ()
Это может применяться только при серверном рендеринге — заголовки для предварительно отрисованных страниц (например, созданных с помощью adapter-static) определяются платформой хостинга.
inlineStyleThreshold
Встраивание CSS-стилей на странице внутри блока <style>
в теге <head>
. Параметр указывает максимальный размер файла, который будет встроен в страницу. Содержимое всех CSS-файлов, которые необходимы данной странице и по размеру меньше указанного значения, будет слито и помещено в блок <style>
.
Установка данного параметра приведет к меньшему количеству первоначальных запросов и может улучшить метрику Первой Отрисовки Контента. Но при этом получаемый HTML возрастает в размере, а эффективность кэширования в браузере снижается.
methodOverride
См. HTTP методы. Объект, содержащий ноль или более из следующего:
parameter
- имя параметра запроса, используемое для передачи требуемого значения методаallowed
- массив методов HTTP, которые могут быть использованы при переопределении исходного метода запроса
outDir
Каталог, в который SvelteKit записывает файлы во время dev
и build
. Вы должны исключить этот каталог из системы управления версиями.
package
Опции, связанные с созданием пакетов.
dir
- директория для готового пакетаemitTypes
- по умолчаниюsvelte-kit package
автоматически сгенерирует файлы определений типов.d.ts
для пакета. Хоть этот параметр и можно отключить, но мы считаем, что для качества экосистемы нужно всегда генерировать файлы определений типов. Убедитесь, что есть веская причина устанавливать значение равнымfalse
(например, если имеются определения типов, написанные вручную).exports
- функция вида(filepath: string) => boolean
. Когда возвращаетtrue
, путь к файлу будет включён в полеexports
вpackage.json
. Любые существующие значения в исходномpackage.json
будут объединены с полученными изexports
значениямиfiles
- функция вида(filepath: string) => boolean
. Когда возвращаетtrue
, файл по указанному пути будет обработан и скопирован в папку, определенной в параметреdir
Для удобного сопоставления путей в функциях значений exports
и files
, можно использовать различные внешние библиотеки:
// @filename: ambient.d.ts
declare module 'micromatch';
/// file: svelte.config.js
// @filename: index.js
// ---cut---
import mm from 'micromatch';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
package: {
exports: (filepath) => {
if (filepath.endsWith('.d.ts')) return false;
return mm.isMatch(filepath, ['!**/_*', '!**/internal/**'])
},
files: mm.matcher('!**/build.*')
}
}
};
export default config;
paths
Объект, содержащий следующие строковые параметры(все опциональны):
assets
— абсолютный путь, откуда будут загружаться статические файлы приложения. Это может быть полезно в случае, когда эти файлы находятся в каком-либо внешнем хранилище.base
— путь относительно корня, который должен начинаться, но не заканчиваться на/
(например,/base-path
), если только это не пустая строка. Указывает, где будет находиться приложение и позволяет запускать приложение из поддиректории основного домена.
prerender
См. Предварительная отрисовка. Объект, содержащий следующие параметры(все опциональны):
-
concurrency
- сколько страниц может отрисовываться одновременно. Хоть JS и однопоточный, но в случаях, когда производительность отрисовки зависит от сети (например, загрузка контента с удалённой CMS), это поможет ускорить процесс, поскольку во время ожидания ответа сети будут обрабатываться другие задачи. -
crawl
— определяет, должен ли SvelteKit находить страницы для предварительной отрисовки, переходя по ссылкам с исходных страниц -
default
- установите значениеtrue
для предварительной отрисовки страниц не содержащихexport const prerender = false
-
enabled
— установите вfalse
, чтобы полностью отключить предварительную отрисовку -
entries
— массив страниц для предварительной отрисовки или начала сканирования (приcrawl: true
). Строка*
включает все нединамические маршруты (т.е. страницы без[параметр]
) -
onError
-
'fail'
— (по умолчанию) прерывает сборку при обнаружении ошибки маршрутизации при переходе по ссылке -
'continue'
— позволяет продолжить сборку, несмотря на ошибки маршрутизации -
function
— пользовательский обработчик ошибок, в котором можно вывести сообщение, вызвать исключение или прервать сборку, а также совершить любые другие действия, основываясь на полученных аргументахimport static from '@sveltejs/adapter-static'; /** @type {import('@sveltejs/kit').PrerenderErrorHandler} */ const handleError = ({ status, path, referrer, referenceType }) => { if (path.startsWith('/blog')) throw new Error('Missing a blog page!'); console.warn(`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`); };
/** @type {import('@sveltejs/kit').Config} */ const config = { kit: { adapter: static(), prerender: { onError: handleError } } };
export default config;
-
routes
Функция вида (filepath: string) => boolean
, которая определяет, какие файлы создают маршруты, а какие рассматриваются как приватные модули.
serviceWorker
Объект, содержащий ноль или более из следующих значений:
register
- если установлено значениеfalse
, отключит автоматическую регистрацию сервис-воркераfiles
- функция вида(filepath: string) => boolean
. Когда возвращаетtrue
, запрошенный файл будет доступен в$service-worker.files
.
trailingSlash
Следует ли удалять, добавлять или игнорировать конечные слэши при разрешении URL-адресов (обратите внимание, что это относится только к страницам, а не к эндпоинтам).
'never'
- перенаправит/x/
на/x
'always'
- перенаправит/x
на/x/
'ignore'
- ничего не делать./x
и/x/
будут рассматриваться эквивалентно
Этот параметр влияет также и на предварительную отрисовку. Для соответствия с работой web-серверов при сохранении отрисованной страницы с адресом /about
, когда параметр trailingSlash
имеет значение always
, будет создана директория с индексным файлом about/index.html
, в иных случаях просто файл about.html
.
Игнорирование конечных слэшей не рекомендуется — семантика относительных путей в двух случаях различается (
./y
от/x
будет/y
, а от/x/
станет/x/y
). Кроме того,/x
и/x/
рассматриваются как отдельные URL-адреса, что вредно для SEO. При использовании этой опции, убедитесь, что логика добавления или удаления конечных слэшей изrequest.path
реализована в функцииhandle
.
version
Объект, содержащий ноль или более из следующих значений:
name
- текущая весрия приложения в виде строкиpollInterval
- интервал в миллисекундах для опроса новой версии
Навигация на стороне клиента может сбоить, когда на сервер загружена новая версия приложения, а люди всё ещё используют ранее загруженную версию. Если данные для следующей страницы уже загружены с сервера, они могут быть устаревшими. В таком случае может быть запрошен более не существующий JavaScript-файл. SvelteKit решает эту проблему, отключая клиентский роутер и выполняя переход с перезагрузкой страницы, когда обнаруживает, что значение версии приложения, указанное в name
, изменилось (по умолчанию в качестве версии используется метка времени сборки).
При установке значения pollInterval
отличным от ноля, SvelteKit будет периодически опрашивать сервер на наличие новой версии и установит значение хранилища updated
в true
, когда она будет обнаружена.
vite
Объект конфигурации Vite или функция, которая его возвращает. Вы можете использовать плагины Vite и Rollup в параметре plugins
для более продвинутой сборки приложения,например, использовав оптимизацию изображений, Tauri, WASM, Workbox и прочее. Некоторые параметры сборки установить невозможно, они используются внутри SvelteKit и определяются его параметрами.
Types permalink
@sveltejs/kit
Все API в Sveltekit полностью типизированны. Следующие типы могут быть импортированы из @sveltejs/kit
TYPES
App
namespace
Можно сказать Sveltekit, как тизировать объекты внутри вашего приложения, объявив пространство имен App
. По умолчанию новый проект будет иметь файл под названием src/app.d.ts
, содержащий следующее:
/// <reference types="@sveltejs/kit" />
declare namespace App {
interface Locals {}
interface Platform {}
interface Session {}
interface Stuff {}
}
После заполнения этих интерфейсов, вы получите безопасное использование типов в event.locals
, event.platform
, session
и stuff
:
App.Locals
Интерфейс, который определяет event.locals
, доступ к которому можно получить в хуках (handle
, handleError
и getSession
) и эндпоинтах.
App.Platform
Если текущий адаптер предоставляет контекст платформы через event.platform
, укажите его здесь.
App.Session
Интерфейс, который определяет объект session
, как аргумента для функций load
, так и значения хранилища session.
App.Stuff
Интерфейс, который определяет объект stuff
во входных и выходных данных функции load
, а так же в значении свойства stuff
в хранилище page.
Сгенерированные типы
Типы RequestHandler
и Load
принимают аргумент Params
, позволяя вам ввести объект params
. Например, этот эндпоинт ожидает параметры foo
, bar
и baz
:
/// file: src/routes/[foo]/[bar]/[baz].js
// @errors: 2355
/** @type {import('@sveltejs/kit').RequestHandler<{
* foo: string;
* bar: string;
* baz: string
* }>} */
export async function get({ params }) {
// ...
}
Излишне говорить, что это громоздко записывать и менее портативно (если бы вы переименовали каталог [foo]
в [qux]
, тип больше не отражал бы реальность).
Чтобы решить эту проблему, SvelteKit генерирует файлы .d.ts
для каждой из ваших конечных точек и страниц:
/// file: .svelte-kit/types/src/routes/[foo]/[bar]/__types/[baz].d.ts
/// link: false
import type { RequestHandler as GenericRequestHandler, Load as GenericLoad } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<
{ foo: string; bar: string; baz: string },
Body
>;
export type Load<
InputProps extends Record<string, any> = Record<string, any>,
OutputProps extends Record<string, any> = InputProps
> = GenericLoad<{ foo: string; bar: string; baz: string }, InputProps, OutputProps>;
Эти файлы можно импортировать в конечные точки и страницы в качестве братьев и сестер благодаря опции rootDirs
в конфигурации TypeScript:
/// file: src/routes/[foo]/[bar]/[baz].js
// @filename: __types/[baz].d.ts
import type { RequestHandler as GenericRequestHandler, Load as GenericLoad } from '@sveltejs/kit';
export type RequestHandler<Body = any> = GenericRequestHandler<
{ foo: string, bar: string, baz: string },
Body
>;
// @filename: index.js
// @errors: 2355
// ---cut---
/** @type {import('./__types/[baz]').RequestHandler} */
export async function get({ params }) {
// ...
}
<script context="module">
/** @type {import('./__types/[baz]').Load} */
export async function load({ params, fetch, session, stuff }) {
// ...
}
</script>
Чтобы это сработало, ваш собственный
tsconfig.json
илиjsconfig.json
должен расширяться от сгенерированного.svelte-kit/tsconfig.json
(где.svelte-kit
- вашoutDir
):{ "extends": "./.svelte-kit/tsconfig.json" }
tsconfig.json
Сгенерированный файл .svelte-kit/tsconfig.json
содержит смесь опций. Некоторые из них генерируются программно на основе конфигурации вашего проекта и, как правило, не должны быть переопределены без уважительной причины:
// file: .svelte-kit/tsconfig.json
{
"compilerOptions": {
"baseUrl": "..",
"paths": {
"$lib": "src/lib",
"$lib/*": "src/lib/*"
},
"rootDirs": ["..", "./types"]
},
"include": ["../src/**/*.js", "../src/**/*.ts", "../src/**/*.svelte"],
"exclude": ["../node_modules/**", "./**"]
}
Другие необходимы для правильной работы SvelteKit, а также должны оставаться нетронутыми, если вы не знаете, что делаете:
// file: .svelte-kit/tsconfig.json
{
"compilerOptions": {
// это гарантирует, что типы явно
// импортируется с `import type`, который
// необходимо, так как svelte-preprocess не может
// в противном случае правильно компилируйте компоненты
"importsNotUsedAsValues": "error",
// Vite компилирует один модуль TypeScript
// за раз, а не компилировать
// весь график модуля
"isolatedModules": true,
// TypeScript не может "видеть", когда вы
// используйте импортированное значение в вашем
// разметка, поэтому нам это нужно
"preserveValueImports": true,
// Настройки для праивильной работы
// `svelte-kit build` и `svelte-kit package`
"lib": ["esnext", "DOM"],
"moduleResolution": "node",
"module": "esnext",
"target": "esnext"
}
}
SEO permalink
Самым важным аспектом SEO является создание высококачественного контента, который широко связан со всем Интернетом. Тем не менее, есть несколько технических соображений для создания сайтов, которые хорошо ранжируются.
Из коробки
SSR
В то время как поисковые системы в последние годы стали лучше индексировать контент, отображаемый с помощью клиентского JavaScript, контент, отображаемый на стороне сервера, индексируется чаще и надежнее. SvelteKit использует SSR по умолчанию, и хотя вы можете отключить его в handle
, вы должны оставить его включенным, если у вас нет веской причины не делать этого.
Рендеринг SvelteKit легко настраивается, и при необходимости вы можете реализовать динамический рендеринг. Обычно это не рекомендуется, поскольку SSR имеет и другие преимущества помимо SEO.
Производительность
Такие сигналы, как Core Web Vitals, влияют на ранжирование в поисковых системах. Поскольку Svelte и SvelteKit создают минимальные накладные расходы, проще создавать высокопроизводительные сайты. Вы можете проверить производительность своего сайта с помощью Google PageSpeed Insights или Lighthouse.
Нормализованные URL
SvelteKit перенаправляет пути с косой чертой в конце на пути без косой черты (или наоборот, в зависимости от вашей конфигурации), поскольку повторяющиеся URL-адреса вредны для SEO.
Ручная настройка
<title> and <meta>
Каждая страница должна иметь хорошо написанные и уникальные элементы <title>
и <meta name="description">
внутри <svelte:head>
. Руководство по написанию описательных заголовков и описаний, а также другие рекомендации по обеспечению понятности контента для поисковых систем можно найти в документации Google [Lighthouse SEO-аудиты] (https://web.dev/lighthouse-seo/).
Распространенным шаблоном является возврат связанных с SEO
stuff
из функций загрузки страницы, а затем их использование (как$page.stuff
) в<svelte:head>
в вашем корневом макете.
Структурированные данные
Структурированные данные помогают поисковым системам понять содержание страницы. Если вы используете структурированные данные вместе с svelte-preprocess
, вам нужно будет явно сохранить данные ld+json
(это может измениться в будущем ):
/// file: svelte.config.js
// @filename: ambient.d.ts
declare module 'svelte-preprocess';
// @filename: index.js
// ---cut---
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: preprocess({
preserve: ['ld+json'],
// ...
})
};
export default config;
Карта сайта
Карта сайта помогает поисковым системам определять приоритетность страниц вашего сайта, особенно если у вас большой объем контента. Вы можете создать карту сайта динамически, используя эндпоинт:
/// file: src/routes/sitemap.xml.js
export async function get() {
return {
headers: {
'Content-Type': 'application/xml'
},
body: `
<?xml version="1.0" encoding="UTF-8" ?>
<urlset
xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="https://www.w3.org/1999/xhtml"
xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:news="https://www.google.com/schemas/sitemap-news/0.9"
xmlns:image="https://www.google.com/schemas/sitemap-image/1.1"
xmlns:video="https://www.google.com/schemas/sitemap-video/1.1"
>
<!-- <url> elements go here -->
</urlset>
`.trim()
};
}
AMP
Печальная реальность современной веб-разработки заключается в том, что иногда необходимо создать Ускоренную мобильную страницу (AMP) версию вашего сайта. В SvelteKit это можно сделать, принудив следующие параметры конфигурация...
/// file: svelte.config.js
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
// комбинация этих опций
// отключает JavaScript
browser: {
hydrate: false,
router: false
},
// так как <link rel="stylesheet"> не
// разрешено, все стили инлайнятся
inlineStyleThreshold: Infinity
}
};
export default config;
...и преобразование HTML с помощью transformPage
вместе с transform
, импортированным из @sveltejs/amp
:
import * as amp from '@sveltejs/amp';
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
return resolve(event, {
transformPage: ({ html }) => amp.transform(html)
});
}
Рекомендуется использовать хук
handle
для проверки преобразованного HTML с помощьюamphtml-validator
, но только если вы предварительно отрисовываете страницы, так как это очень медленно.
Файлы ресурсов permalink
Импортирование
Vite автоматически обработает импортированные файлы для повышения производительности. Хэши будут добавлены к именам файлов, чтобы их можно было кэшировать, а ресурсы, меньшие, чем assetsInlineLimit
, будут встроены.
<script>
import logo from '$lib/assets/logo.png';
</script>
<img alt="The project logo" src={logo} />
Если вы предпочитаете ссылаться на файлы ресурсов непосредственно в разметке, можно использовать препроцессор, такой как [svelte-preprocess-import-assets] (https://github.com/bluwy/svelte-preprocess-import-assets) или [svelte-image] (https://github.com/matyunya/svelte-image).
Для файлов ресурсов, включенных через CSS функцию url()
, можно найти опцию experimental.useVitePreprocess
:
// svelte.config.js
export default {
experimental: {
useVitePreprocess: true
}
};
Оптимизация
Можно использовать сжатые форматы изображений, такие как .webp
или .avif
, или отзывчивые изображения, которые отдают разные размеры в зависимости от экрана вашего устройства. Для изображений, которые статически включены в проект, можно использовать препроцессор, такой как [svelte-image] (https://github.com/matyunya/svelte-image) или плагин Vite, такой как [vite-imagetools](https://github.com/JonasKruckenberg/
Переход с Sapper permalink
SvelteKit является преемником Sapper и разделяет многие элементы своего дизайна.
Если у вас есть существующее приложение Sapper, которое вы планируете перенести на SvelteKit, вам нужно будет внести ряд изменений. Возможно, вам будет полезно просмотреть некоторые примеры во время миграции.
package.json
type: "module"
Добавьте "type": "module"
в свой package.json
. Вы можете сделать этот шаг отдельно от остальных в рамках инкрементной миграции, если вы используете Sapper 0.29.3
Или новее.
dependencies
Удалите polka
или express
, если вы используете один из них, и любое промежуточное программное обеспечение, такое как sirv
или compression
.
devDependencies
Удалите sapper
из вашего devDependencies
и замените его на @sveltejs/kit
и любой адаптер, который вы планируете использовать (см. следующий раздел).
scripts
Любые скрипты, которые ссылаются на sapper
, должны быть обновлены:
sapper build
должен стать [svelte-kit build
](-sapper export
должен статьsvelte-kit build
с помощью статического адаптера
) с помощью узла адаптер
sapper export
должен статьsvelte-kit build
с помощью статического адаптераsapper dev
должен статьsvelte-kit dev
node __sapper__/build
должен статьnode 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 в качестве примеров:
sveltejs/realworld
пример блога- директория
sites/kit.svelte.dev
содержит код этого сайта sveltejs/sites
содержит код svelte.dev и клона HackerNews
Пользователи 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. Этот процесс обновления страницы на клиенте в ответ на попытку перехода называется маршрутизацией на стороне клиента.