Back

Boas Práticas para Trabalhar com Svelte

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 $state apenas quando um valor controla atualizações da UI, e recorra a $state.raw quando estiver substituindo valores em vez de mutá-los.
  • Prefira $derived em vez de $effect para valores computados; reserve $effect para sincronizar com sistemas externos.
  • Evite estado em nível de módulo em ambientes SSR. Use a API de contexto do Svelte com $state baseado em classe para um estado compartilhado, escopado por requisição e com tipagem segura.
  • No SvelteKit, use +page.server.js para dados de página do lado do servidor e +server.js para 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');

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árioUse
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çãoonMount + 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.

OpenReplay