SvelteKit — фреймворк для веб-приложений на Svelte, который совмещает серверный рендеринг, маршрутизацию и сборку. Компоненты компилируются в компактный JavaScript, а не тащат большую библиотеку времени выполнения. Связка Svelte 5 и SvelteKit 2 остаётся практичным выбором для сайтов, где важны скорость и небольшой клиентский код.
Почему JavaScript получается меньше
Svelte компилирует разметку и реактивность в обычные операции над DOM. Виртуального DOM нет, поэтому браузеру не нужно держать в памяти второе дерево. Сервер отдаёт готовый HTML, а клиентский JavaScript оживляет разметку и обслуживает переходы. Если на странице нет обработчиков и динамических состояний, JavaScript может вообще не понадобиться.
- Серверный рендеринг даёт быстрый первый экран и нормальную индексацию поисковиками.
- Гидратация подключает обработчики к уже отрисованному HTML, а не перерисовывает страницу с нуля.
- Код разделяется по маршрутам, поэтому начальная загрузка не включает всё приложение.
- Статические страницы можно пререндерить в HTML на этапе сборки.
JavaScript не исчезает совсем: формы и меню требуют кода, но его объём растёт с функциональностью, а не с размером фреймворка.
Создание проекта
Официальный способ начать работу — команда sv create. Она задаёт вопросы о шаблоне, TypeScript и дополнительных инструментах. Для первого проекта достаточно минимального шаблона без лишних зависимостей.
npx sv create myapp
cd myapp
npm install
npm run dev -- --open
После запуска откройте адрес из терминала: горячая перезагрузка и ошибки компиляции работают сразу. Маршруты лежат в src/routes, компоненты — в src/lib, статика — в static.
Маршруты и данные
Каждый каталог в src/routes соответствует сегменту URL. Файл +page.svelte описывает страницу, +page.server.js выполняет серверную загрузку данных, а +layout.svelte задаёт общий каркас. Серверная функция load получает параметры маршрута и может обращаться к базе напрямую, не отдавая клиенту секреты.
import { error } from '@sveltejs/kit';
export async function load({ params }) {
const post = await db.getPost(params.slug);
if (!post) throw error(404, 'Статья не найдена');
return { post };
}
Данные возвращаются как обычный объект и становятся доступны странице через props. В Svelte 5 они принимаются так:
<script>
let { data } = $props();
</script>
<h1>{data.post.title}</h1>
<article>{@html data.post.html}</article>
Использовать {@html} можно только для очищенного на сервере HTML: пользовательский ввод без санитизации открывает путь к XSS.
Формы без лишнего клиентского кода
Формы в SvelteKit работают даже при отключённом JavaScript: браузер отправляет обычный POST, сервер выполняет action и возвращает страницу. Прогрессивное улучшение добавляет плавность там, где скрипты доступны.
import { fail } from '@sveltejs/kit';
export const actions = {
default: async ({ request }) => {
const form = await request.formData();
const email = String(form.get('email') || '').trim();
if (!email.includes('@')) {
return fail(400, { email, error: 'Проверьте адрес' });
}
await db.subscribe(email);
return { success: true };
}
};
На клиенте форма подключается к action через атрибут method и действие enhance. Оно перехватывает отправку, показывает состояние и обновляет данные без полной перезагрузки.
<script>
import { enhance } from '$app/forms';
let { form } = $props();
</script>
<form method="POST" use:enhance>
<input name="email" value={form?.email ?? ''} />
<button>Подписаться</button>
{#if form?.error}<p>{form.error}</p>{/if}
</form>
Если JavaScript выключен, форма всё равно отправится и сервер вернёт результат. Это снижает зависимость интерфейса от клиентского кода и упрощает отладку.
API и клиентская навигация
Для внешних потребителей или динамических запросов можно создать endpoint +server.js. Он возвращает JSON и не требует отдельного сервера.
import { json } from '@sveltejs/kit';
export async function GET({ url }) {
const q = url.searchParams.get('q') ?? '';
const items = await db.search(q);
return json({ query: q, items });
}
Внутренние переходы SvelteKit перехватывает и подгружает только нужный маршрут, но ссылки должны оставаться обычными ссылками, а фокус — предсказуемым.
Сборка и адаптеры
Итоговый способ запуска зависит от адаптера. Для собственного сервера на VPS удобен adapter-node: он собирает Node-приложение, которое отдаёт статику и рендерит страницы. Для полностью статического сайта используют adapter-static и пререндер.
npm install -D @sveltejs/adapter-node
Затем адаптер подключается в svelte.config.js. Каталог сборки по умолчанию называется build.
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
adapter: adapter({ out: 'build' })
}
};
После сборки приложение запускается обычным Node-процессом. За обратным прокси задайте ORIGIN, чтобы корректно формировались абсолютные адреса, и PORT, если стандартный порт занят.
npm run build
node build
PORT=8080 ORIGIN=https://example.com node build
curl -I http://localhost:3000
Статический экспорт включается флагом prerender в layout или page. Для динамических маршрутов перечислите конкретные страницы, иначе сборка не знает, какие URL создавать. Приложению с авторизацией пререндер не подходит.
Как не отправить лишний JavaScript
Начните с аудита: посмотрите во вкладке Network, сколько килобайт скриптов грузит первая страница. Часто вес дают карты и редакторы, а не фреймворк; их подключают динамически при взаимодействии.
- Держите серверную загрузку данных в +page.server.js, чтобы не тащить клиентские запросы.
- Не включайте глобальные сторы там, где достаточно локального состояния.
- Для страниц без интерактивности используйте пререндер и отключайте SSR только осознанно.
- Проверяйте размер бандла после каждого крупного изменения, а не перед релизом.
- Изображения и шрифты оптимизируйте отдельно: они часто весят больше скриптов.
Флаг ssr = false превращает страницу в клиентское приложение и задерживает первый экран. Он нужен для узких случаев, например для API, требующего браузерного окружения; по умолчанию SSR лучше оставить включённым.
Чек-лист перед публикацией
- Сборка проходит без предупреждений, старые артефакты удалены.
- Выбран правильный адаптер: node для сервера, static для CDN.
- Заданы ORIGIN, PORT и переменные окружения для секретов.
- Проверены формы при выключенном JavaScript.
- HTML из редактора очищается перед вставкой через {@html}.
- Размер начального бандла измерен и не растёт бесконтрольно.
Итог
SvelteKit даёт полный цикл разработки веб-приложения: маршруты, серверные данные, формы, API и сборку под нужную платформу. Благодаря компиляции и серверному рендерингу клиентский JavaScript остаётся компактным, а страницы открываются быстро даже на слабых устройствах. Для сайта, которому нужна интерактивность без тяжёлого фреймворка, это разумный и хорошо документированный выбор.