Boas Práticas para Trabalhar com Svelte
Se você já passou do básico do Svelte e começou a construir aplicações reais, provavelmente notou que a documentação oficial cobre o que as coisas fazem, mas nem sempre quando ou por que usá-las. Este artigo foca em boas práticas do Svelte 5 que melhoram a manutenibilidade, o desempenho e a clareza em código de produção, assumindo que você já entende como componentes e reatividade funcionam.
Principais Conclusões
- Use
$stateapenas quando um valor controla atualizações da UI, e recorra a$state.rawquando estiver substituindo valores em vez de mutá-los. - Prefira
$derivedem vez de$effectpara valores computados; reserve$effectpara sincronizar com sistemas externos. - Evite estado em nível de módulo em ambientes SSR. Use a API de contexto do Svelte com
$statebaseado em classe para um estado compartilhado, escopado por requisição e com tipagem segura. - No SvelteKit, use
+page.server.jspara dados de página do lado do servidor e+server.jspara endpoints de API independentes. - Adote a sintaxe moderna do Svelte 5 (
onclick,{#snippet},$props()) em vez de padrões legados em código novo.
Runes do Svelte 5: Use-as com Precisão
As runes do Svelte 5 são o principal modelo de reatividade, e usá-las corretamente importa mais do que usá-las em todo lugar.
Recorra a $state apenas quando uma variável precisar controlar atualizações da UI. Variáveis comuns são mais baratas e mais claras para todo o resto.
Quando seu estado é um objeto grande ou um array que é substituído em vez de mutado, use $state.raw:
// ❌ Sobrecarga desnecessária de proxy para dados de API que você só vai reatribuir
let users = $state(await fetchUsers());
// ✅ Sem custo de proxy quando você está substituindo, não mutando
let users = $state.raw(await fetchUsers());
Use $state quando precisar mutar propriedades aninhadas diretamente (como cart.items[0].quantity++). Use $state.raw quando estiver trocando o valor inteiro.
Prefira $derived em Vez de $effect para Valores Computados
Este é um dos erros mais comuns no desenvolvimento moderno com Svelte:
let num = $state(0);
// ❌ Evite — cria um efeito colateral desnecessário
let square = $state(0);
$effect(() => { square = num * num; });
// ✅ Correto — declarativo e com dependências rastreadas
let square = $derived(num * num);
$effect é uma saída de emergência. Reserve-o para sincronizar com sistemas externos (como o D3), e considere {@attach} para integrações em nível de DOM onde se encaixe naturalmente.
Trate Props como Dinâmicas
Valores derivados de props devem usar $derived, não atribuição simples:
let { type } = $props();
// ✅ Permanece sincronizado quando `type` muda
let color = $derived(type === 'danger' ? 'red' : 'green');
Discover how at OpenReplay.com.
Contexto Tipado em Vez de Módulos Compartilhados
Para estado compartilhado entre uma subárvore de componentes, prefira a API de contexto do Svelte em vez de estado em nível de módulo. O estado de módulo persiste entre requisições em ambientes SSR, o que pode causar vazamento de dados entre usuários.
O padrão moderno usa uma classe com campos $state:
// lib/theme.svelte.ts
import { getContext, setContext } from 'svelte';
class ThemeContext {
current = $state('light');
toggle() {
this.current = this.current === 'light' ? 'dark' : 'light';
}
}
const KEY = Symbol('theme');
export const setTheme = () => setContext(KEY, new ThemeContext());
export const getTheme = () => getContext<ThemeContext>(KEY);
Isso oferece tipagem segura, estado reativo e escopo apropriado para SSR em um único padrão.
Carregamento de Dados no SvelteKit: Escolhendo o Padrão Certo
Um ponto comum de confusão no SvelteKit é quando usar +page.server.js versus +server.js:
| Cenário | Use |
|---|---|
| Buscar dados para uma página com SSR ou acesso somente do servidor | +page.server.js com load() |
| Construir um endpoint de API para uso externo | +server.js |
| Dados apenas do cliente após a hidratação | onMount + fetch |
Para dados de página que precisam de acesso ao servidor, segredos ou SSR, +page.server.js geralmente é o padrão correto. Ele roda no servidor, mantém segredos fora do cliente e integra-se de forma limpa com as form actions do SvelteKit para aprimoramento progressivo.
Pequenas Vitórias Práticas
Blocos {#each} com chave evitam bugs sutis de reciclagem do DOM. Sempre use uma chave com ID único e estável, nunca pelo índice.
$inspect.trace é subutilizado para depurar reatividade. Coloque-o no topo de qualquer $effect ou $derived.by para ver exatamente qual dependência disparou uma reexecução.
Snippets em vez de slots para blocos de marcação reutilizáveis. Snippets compõem melhor e podem ser passados como props, tornando as APIs dos componentes mais limpas.
Evite sintaxe legada em código novo. Substitua on:click por onclick, <slot> por {#snippet} e export let por $props(). Esses padrões estão alinhados com as convenções modernas do Svelte 5 e com o comportamento atual do compilador.
Conclusão
O Svelte 5 recompensa a contenção. Quanto mais precisamente você escopar a reatividade — usando $state apenas onde necessário, $derived em vez de $effect, e contexto em vez de globais de módulo — mais previsível e performática sua aplicação se torna. Comece com a primitiva reativa mais simples que resolva o problema, e só recorra a ferramentas mais poderosas quando as mais simples genuinamente não forem suficientes.
Perguntas Frequentes
Use $state.raw quando planeja substituir o valor inteiro em vez de mutar partes dele, como ao armazenar respostas de API ou arrays grandes que você reatribui por completo. Ele evita a sobrecarga do proxy reativo, o que melhora o desempenho para grandes conjuntos de dados. Use $state simples quando precisar de reatividade granular para mutações aninhadas, como atualizar um item dentro de um array.
$derived é declarativo, rastreia automaticamente suas dependências e produz um valor somente leitura que permanece sincronizado. $effect é executado imperativamente como um efeito colateral e é mais difícil de raciocinar, pois pode introduzir bugs de temporização e reexecuções desnecessárias. Reserve $effect para sincronizar com sistemas fora da reatividade do Svelte, como bibliotecas de terceiros, APIs de canvas ou manipulação manual do DOM.
Não em ambientes SSR como o SvelteKit. O estado em nível de módulo é compartilhado entre todas as requisições que o servidor processa, o que pode vazar dados de um usuário para a sessão de outro. Use a API de contexto do Svelte com setContext e getContext, idealmente apoiada por uma classe contendo campos $state. Isso escopa o estado por requisição e por árvore de componentes, preservando reatividade e segurança de tipos.
Use +page.server.js quando os dados pertencem a uma página específica e se beneficiam de SSR, SEO, acesso ao servidor ou form actions. Use +server.js quando precisar de um endpoint HTTP independente, como uma API JSON consumida por clientes externos, webhooks ou chamadas fetch não vinculadas a páginas. Se os dados são renderizados apenas por uma página e precisam de capacidades do servidor, +page.server.js geralmente é o padrão melhor.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.