Signals · JSX · SSR

Atualize o nó, não a página.

Veloz é uma biblioteca de interface reativa em que os signals atualizam exatamente os nós do DOM que dependem deles. Sem DOM virtual, sem re-render: componentes rodam uma vez.

terminal
npm install @velozjs/dom
Quantidade
2

DOM renderizado

  • <h4>Resumo do pedido0 atualizações
  • <p>2 itens × R$ 24,000 atualizações
  • <p>Subtotal R$ 48,000 atualizações
  • <p>Desconto —0 atualizações
  • <p>Frete R$ 9,000 atualizações
  • <strong>Total R$ 57,000 atualizações

O componente rodou 1 vez. Cada linha conta as próprias atualizações no DOM.

Mude o pedido. Só as linhas cujo texto muda acendem.

O modelo

Componentes rodam uma vez

Um componente é uma função que monta DOM de verdade e o devolve. O que muda depois são as funções que você coloca no JSX: cada uma vira uma região viva ligada aos signals que ela lê.

  1. Leia signals dentro de funções{count} ou {() => a() + b()} atualizam; valores lidos no corpo do componente, não.
  2. As props chegam como foram passadasCallbacks e render props continuam funções. Aceite um valor ou um signal com access().
  3. Sem estados inconsistentesMemos nunca ficam desatualizados, effects rodam uma vez por mudança e tudo é descartado com o dono.
Counter.tsx
import { render, createSignal, createMemo } from '@velozjs/dom';

function Counter() {
  console.log('runs once');
  const [count, setCount] = createSignal(0);
  const doubled = createMemo(() => count() * 2);

  return (
    <button onClick={() => setCount((c) => c + 1)}>
      {count} × 2 = {doubled}
    </button>
  );
}

render(() => <Counter />, document.body);
Na caixa

Tudo o que uma camada de UI precisa, e nada além

Signals de granularidade fina

Signals, memos e effects com atualizações em lote e consistentes.

SSR e hidratação

renderToString no servidor, hydrate no cliente, mesmos componentes.

Dados assíncronos

createResource com Suspense, ErrorBoundary e dados entregues à hidratação.

CSS-in-JS com escopo

css, styled e a prop css, compatível com CSP e coletado no SSR.

Seguro por padrão

Texto nunca vira HTML, URLs e nomes de atributo são validados, innerHTML é sanitizado.

Pequeno e tipado

Só ESM, TypeScript em primeiro lugar, sem dependências em tempo de execução.

Dados assíncronos

Estados de carregamento sem encanamento

Leia um recurso dentro do Suspense e o fallback aparece até a primeira carga terminar. Recargas mantêm o conteúdo na tela; falhas vão para o ErrorBoundary mais próximo. No servidor, o renderToStringAsync espera os dados e os entrega ao hydrate().

tsx
const [user] = createResource(userId, (id) =>
  fetch(`/api/users/${id}`).then((r) => r.json())
);

<Suspense fallback={<Spinner />}>
  {() => <h2>{() => user()?.name}</h2>}
</Suspense>
Guia de dados assíncronos

Nada carregado ainda. O recurso só busca quando a fonte é definida.

Renderização no servidor

Esta página é a demonstração

Cada página daqui é renderizada em HTML pelo @velozjs/ssr no build e estilizada com o salve-css. Só as partes interativas (o playground, a demo assíncrona, o botão de tema e o menu) são hidratadas, então o resto chega sem JavaScript.

Guia de renderização no servidor
  1. O servidor renderiza os componentes em HTML com chaves de hidratação e marcadores de região.
  2. O hydrate() reaproveita esses elementos, liga eventos e effects e remove as chaves.
  3. Daí em diante, os signals atualizam só os nós que dependem deles.
Pacotes

Use só o que precisar

Seu primeiro componente em três passos

Instale o pacote, adicione o plugin do Vite, escreva JSX.

Ler o guia