O que é SvelteKit?
SvelteKit é o framework oficial de aplicações para Svelte. Enquanto o Svelte fornece componentes e reatividade, o SvelteKit adiciona roteamento, carregamento de dados no servidor, manipulação de formulários, endpoints de API e adaptadores de deploy. É a maneira recomendada de construir qualquer coisa maior que um widget, e combina naturalmente com o Svelte 5.
Se você já utilizou Next.js ou Nuxt, a estrutura parecerá familiar. A diferença é uma forte inclinação para os padrões da web: formulários, requisições e respostas são primitivos da plataforma, e o SvelteKit os aprimora em vez de substituí-los.
Roteamento baseado em arquivos
Tudo reside em src/routes. Pastas tornam-se segmentos de URL e arquivos com nomes específicos definem o comportamento.
src/routes/
├── +layout.svelte # shared shell for all routes
├── +page.svelte # /
├── about/+page.svelte # /about
├── blog/
│ ├── +page.svelte # /blog
│ └── [slug]/
│ ├── +page.svelte # /blog/:slug
│ └── +page.server.js # data for that page
└── api/
└── posts/+server.js # GET/POST /api/posts
O prefixo + marca os arquivos especiais do SvelteKit. +page.svelte renderiza uma página, +layout.svelte envolve as rotas filhas, +page.server.js fornece dados exclusivos do servidor e +server.js define um endpoint de API.
Funções de load
As funções de load buscam dados antes de uma página ser renderizada. Elas podem ser executadas no servidor, no navegador ou em ambos.
// src/routes/posts/+page.server.js
export async function load({ fetch }) {
const res = await fetch("/api/posts");
if (!res.ok) throw error(500, "Failed to load posts");
return { posts: await res.json() };
}
<!-- src/routes/posts/+page.svelte -->
<script>
let { data } = $props();
</script>
<ul>
{#each data.posts as post (post.id)}
<li>{post.title}</li>
{/each}
</ul>
Como os dados são resolvidos antes da renderização, o primeiro paint já contém conteúdo. Use +page.server.js quando o código precisar de secrets ou de um banco de dados, e +page.js quando ele puder ser executado em ambos os ambientes. Layouts também podem ter funções de load, e os loads dos filhos recebem os dados do pai.
Form actions
Formulários são tratados como cidadãos de primeira classe. Uma form action é executada no servidor e processa o envio, sem a necessidade de um fetch no lado do cliente.
// src/routes/posts/new/+page.server.js
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const title = String(data.get("title") ?? "").trim();
if (!title) {
return { success: false, error: "Title is required" };
}
await db.post.create({ data: { title } });
return { success: true };
},
};
<!-- src/routes/posts/new/+page.svelte -->
<script>
let { form } = $props();
</script>
<form method="POST">
<input name="title" />
{#if form?.error}<p class="error">{form.error}</p>{/if}
<button>Create</button>
</form>
O formulário funciona antes mesmo do JavaScript carregar, e o SvelteKit o aprimora assim que o cliente está pronto. O valor retornado fica disponível na prop form da página, tornando o feedback de validação simples.
Endpoints da API
Para APIs JSON, um arquivo +server.js exporta handlers HTTP.
// src/routes/api/posts/+server.js
import { json } from "@sveltejs/kit";
export async function GET() {
const posts = await db.post.findMany();
return json(posts);
}
export async function POST({ request }) {
const body = await request.json();
const post = await db.post.create({ data: body });
return json(post, { status: 201 });
}
Estes são objetos comuns de Request e Response da web, portanto, o mesmo conhecimento se aplica a outros runtimes e frameworks.
Hooks
Um arquivo hooks.server.js é executado em cada requisição. É o local ideal para autenticação, logging e preenchimento de event.locals.
// src/hooks.server.js
export async function handle({ event, resolve }) {
const session = await getSession(event.cookies);
event.locals.user = session?.user ?? null;
return resolve(event);
}
Qualquer valor definido em locals fica disponível para as funções de load e actions, o que mantém as preocupações transversais (cross-cutting concerns) em um único lugar, em vez de espalhadas pelas rotas.
Renderização e adapters
O SvelteKit suporta diversas estratégias de renderização e permite que você escolha por rota:
- SSR renderiza no servidor e faz a hidratação no navegador.
- Prerendering gera HTML estático no momento do build.
- CSR renderiza apenas no navegador para as rotas que optarem por isso.
- Híbrido mistura as três opções, permitindo que uma página de marketing seja estática enquanto uma rota de app seja renderizada no servidor.
O deploy é gerenciado por adapters. Instale o adapter para o seu destino — Node, static, Vercel, Netlify, Cloudflare e outros — configure-o, e o mesmo código-fonte será buildado para aquela plataforma. Mudar de host geralmente exige a alteração de apenas uma linha.
Melhores práticas
- Use funções de load
+page.server.jspara dados que devem permanecer no servidor. - Prefira form actions em vez de requisições POST no lado do cliente para mutações.
- Mantenha a autenticação e o logging em
hooks.server.js. - Escolha o modo de renderização mais restrito que atenda a cada rota.
- Use
+layout.sveltepara UI compartilhada, para que o estado persista durante a navegação. - Tipagem os valores de retorno da sua função de load ao usar TypeScript.
- Instale desde o início um adapter que corresponda ao seu alvo de deploy.
Erros comuns
- Fazer fetch em
onMounte perder a renderização no servidor. - Colocar segredos em um load universal
+page.jsem vez de+page.server.js. - Recriar formulários com fetch no lado do cliente quando as actions já funcionam.
- Esquecer de adicionar chaves (key) em blocos
{#each}e quebrar as atualizações de listas. - Fazer o prerendering de uma rota que depende de dados por usuário.
- Ignorar hooks e duplicar verificações de autenticação em cada função load.
Próximos passos
O SvelteKit é a forma completa de construir aplicações com Svelte. Aprofunde seus conhecimentos em Svelte, adicione TypeScript e compare a arquitetura com Next.js, Nuxt e Astro. Depois, construa um pequeno app com uma load function, uma form action e um API endpoint para ver todo o modelo em ação.