
Um modelo unificado explica HTMX, React Server Components e sync engines
A guerra do estado e as três responsabilidades
Ryan Carniato, autor do SolidJS, argumenta que 30 anos de disputas do frontend sobre quem detém o estado - do modelo de documento com estado no servidor, passando por JavaScript no cliente, ASP.NET e as tentativas de conectar os dois lados, até o impasse atual entre React e HTMX - podem ser resolvidas com um modelo unificado baseado em três responsabilidades:
- Navegação (cliente): a URL pertence ao navegador, e a orquestração é papel do cliente, de SPAs a parciais de HTML.
- Conteúdo (servidor): o servidor é a fonte autoritativa de marcação ou JSON, pendurado na navegação.
- Afordâncias (cliente): estado local de UI, trabalho em andamento e atualizações otimistas, para dar feedback mais rápido que uma ida ao servidor.
A assimetria que torna tudo componível
Toda arquitetura web segue o ciclo cliente -> servidor -> cliente. A web mapeia escritas para a navegação (formulários, ações, invalidação), enquanto o conteúdo no servidor só publica leituras. Essa assimetria é o que garante composição: quando o cliente nunca escreve diretamente no conteúdo do servidor, as affordances cabem como uma camada de sobreposição. Quebrar essa regra gera dois sistemas com estado brigando entre si.
Sob essa lente, Carniato posiciona os frameworks: HTMX investe quase tudo na camada de conteúdo e quase nada nas affordances; LiveView expande a camada de conteúdo; DataStar adiciona Signals preenchidos pelo servidor; Astro (+ View Transitions) nomeia explicitamente as três partes; Server Components do Next.js preservam estado compartilhado no cliente; SPA + JSON (React) deixa a camada 3 absorver a 1; e sync engines como o Zero transformam o conteúdo em leitura persistente de um armazenamento replicado. As diferenças seriam de transporte, janela de tempo e peso de código de affordance - ou seja, eficiência e ergonomia, não expressividade.
O modelo aplicado no Solid 2.0
Carniato mostra como o Solid 2.0 cobriria todo o espectro:
- Navegação por delegação: o roteador não possui nada na árvore de renderização; o compilador JSX registra uma reivindicação em cada
a[href]eform[action], interceptando âncoras e formulários mesmo antes da hidratação, incluindo marcação de servidor sem componentes no cliente. Ações de servidor com"use server"e mutações single-flight resolvem em uma ida e volta toda a UI invalidada. - Conteúdo como leitura reativa: funções
"use server"serializam via Seroval, incluindo estruturas assíncronas como Promises e iteradores assíncronos. O grafo reativo propaga pela rede: o servidor re-executa expressões e envia valores pontuais enquanto a requisição permanece aberta. A mesma função pode trocar Request/Response por transporte persistente (SSE ou socket) sem mudar o autoramento. Uma lição do LiveView guia a segurança: o grafo ativo do servidor é uma projeção re-derivável do estado durável, nunca a fonte da verdade. - Afordâncias com hidratação única: assincronismo é nativo do grafo, e otimismo é um primitivo de primeira classe - qualquer estado não confirmado previsto sobre async, que se settle como verdade ou é revertido, sem sobreviver à transação. A regra crítica é nunca hidratar mais de uma vez: após a inicialização, o servidor não deve renderizar componentes de cliente, evitando os descompassos de hidratação que Carniato aponta como ponto fraco de soluções de parciais de HTML e ilhas. Todo conteúdo do servidor é endereçado pela chamada que o produziu, e a UI montada lê desse endereço - o que impede que um preload de hover sobrescreva a página, garante morphing de refetch e descarta respostas obsoletas por checagem de versão.
Percorrendo o espectro
Com esses blocos, Carniato descreve como atravessar o grid: um app sem componentes de cliente que troca pedaços de Server Components via ações de servidor (canto inferior esquerdo); a SPA pura com APIs JSON (superior esquerdo); leituras persistentes com a camada otimista granular, onde live e until fecham a lacuna - embora ele ainda usaria um sync engine dedicado; e o canto inferior direito, próximo da origem do modelo, com Server Components reativos e conexão persistente.
Conclusão
Para Carniato, tudo - de HTMX a LiveView, ilhas e SPA - é uma coordenada nesse grid, e as peças difíceis já estão construídas: serialização e hidratação únicas, grafo reativo que serializa as próprias atualizações e conteúdo armazenado por endereço. Signals seriam a representação comum dos dois lados. Ele reconhece a ambição: os RSCs miraram só metade esquerda do grid e muitos acharam que ficaram aquém; o campo HTML-over-the-wire mirou a metade de baixo, mas ignorar o cliente é ignorar uma responsabilidade inteira. Ainda assim, defende que esse futuro já está aqui - um em que escolher framework não exige escolher uma religião.