12k
All articles

Boas Práticas para Trabalhar com Svelte

Boas práticas do Svelte 5 para $state, $derived, contexto e carregamento de dados no SvelteKit, além de each com chave e sintaxe moderna.

OpenReplay Team
OpenReplay Team
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

Quando devo usar $state.raw em vez de $state?

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.

Por que $derived é preferível a $effect para valores computados?

$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.

É seguro armazenar estado compartilhado em uma variável em nível de módulo?

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.

Quando devo escolher +server.js em vez de +page.server.js?

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.

DevTools for the frontend

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.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.