No trimestre passado, tínhamos um projeto de cliente que nos deu a desculpa perfeita para fazer algo que estávamos ansiosos para tentar: construir a mesma aplicação em SolidJS e React, e depois comparar tudo. Não um app de tarefas. Não um contador. Um dashboard de produção real com autenticação, atualizações de dados em tempo real, formulários complexos e um módulo de gráficos que renderiza milhares de pontos de dados.

Os resultados nos surpreenderam. Não porque um framework "venceu" -- mas porque os trade-offs eram muito mais nuançados do que o discurso do Twitter sugere. Algumas coisas que esperávamos. Algumas coisas nos pegaram completamente desprevenidos. Isso é o que realmente aprendemos.

Índice

Construímos o Mesmo App em SolidJS e React: Signals vs Hooks

O App que Construímos

A aplicação é um dashboard de análises em tempo real para um cliente de e-commerce. Aqui está o que inclui:

  • Fluxo de autenticação com tokens JWT e lógica de refresh
  • Dashboard com 6 painéis de widgets, cada um obtendo dados de diferentes endpoints da API
  • Feed de pedidos em tempo real usando conexões WebSocket
  • Gráficos interativos renderizando 5.000+ pontos de dados (usando uma biblioteca de gráficos)
  • Formulários de filtro complexos com dropdowns dependentes e seletores de intervalo de datas
  • Painel de configurações de administrador com gerenciamento de estado aninhado
  • Layout responsivo com navegação de barra lateral

Ambas as versões se conectam à mesma API de backend. Ambas usam TypeScript. Ambas usam Vite como ferramenta de construção. Mantivemos as dependências de terceiros o mais similares possível -- mesma biblioteca de gráficos (Chart.js), mesmo cliente HTTP (ky), mesmo wrapper WebSocket.

A versão React usa React 19 com hooks. A versão SolidJS usa Solid 1.9. Não usamos nenhum meta-framework (sem Next.js, sem SolidStart) porque queríamos isolar as diferenças do framework sem roteamento e SSR confundindo a comparação.

Signals vs Hooks: Uma Mudança de Modelo Mental

Esta é a grande. E honestamente, levou cerca de uma semana para o nosso time parar de escrever código com a forma do React em SolidJS.

Como os React Hooks Funcionam

Você sabe disso, mas vale a pena afirmar explicitamente para a comparação. O modelo do React é: quando o estado muda, a função do componente é re-executada. A função inteira. Cada useState, cada useMemo, cada useCallback -- eles são todos mecanismos para contornar o fato de que a função inteira é re-executada.

// React: Essa função inteira é re-executada a cada mudança de estado
function OrderFeed() {
  const [orders, setOrders] = useState([]);
  const [filter, setFilter] = useState('all');
  
  // Isso é recalculado a cada renderização a menos que memoizemos
  const filteredOrders = useMemo(() => 
    orders.filter(o => filter === 'all' || o.status === filter),
    [orders, filter]
  );

  // Essa ref é recriada conceitualmente a cada renderização
  const handleNewOrder = useCallback((order) => {
    setOrders(prev => [order, ...prev]);
  }, []);

  useEffect(() => {
    const ws = connectWebSocket(handleNewOrder);
    return () => ws.close();
  }, [handleNewOrder]);

  return <OrderList orders={filteredOrders} />;
}

Como os Solid Signals Funcionam

O modelo do Solid é fundamentalmente diferente. A função do componente é executada uma vez. Depois disso, apenas as expressões específicas que leem um signal são re-executadas quando esse signal muda. Não há virtual DOM diff. Não há reconciliação. O gráfico reativo rastreia exatamente quais nós DOM dependem de quais signals.

// Solid: Essa função é executada UMA VEZ
function OrderFeed() {
  const [orders, setOrders] = createSignal([]);
  const [filter, setFilter] = createSignal('all');
  
  // Isso é rastreado automaticamente -- nenhum array de dependências necessário
  const filteredOrders = createMemo(() => 
    orders().filter(o => filter() === 'all' || o.status === filter())
  );

  // Nenhum useCallback necessário -- esse closure é estável
  const handleNewOrder = (order) => {
    setOrders(prev => [order, ...prev]);
  };

  // onMount em vez de useEffect com deps vazias
  onMount(() => {
    const ws = connectWebSocket(handleNewOrder);
    onCleanup(() => ws.close());
  });

  return <OrderList orders={filteredOrders()} />;
}

O Que Isso Significa na Prática

A versão Solid não tem arrays de dependências. Sem useCallback. Sem useMemo para estado derivado (embora createMemo exista para computações caras -- a diferença é que é opt-in para desempenho, não necessário para correção).

Aqui está o que realmente nos pegou durante o desenvolvimento:

  1. Desestruturação de props mata reatividade em Solid. Tínhamos um desenvolvedor júnior desestruturando props em um componente Solid e passamos 45 minutos depurando por que as atualizações não estavam se propagando. Em React, desestruturação é fina porque a função inteira é re-executada. Em Solid, você precisa acessar props.value dentro do JSX ou em um escopo rastreado.

  2. Early returns são complicados em Solid. Você não pode fazer if (!data()) return <Loading /> no topo de um componente Solid da forma que faria em React. A função do componente é executada apenas uma vez, então essa condicional nunca seria re-avaliada. Você precisa de <Show when={data()}> em vez disso.

  3. Sem bugs de closure obsoleto. Essa foi a grande vitória. Na nossa versão React, tínhamos três bugs de closure obsoleto separados na primeira semana relacionados aos manipuladores WebSocket capturando estado antigo. A versão Solid tinha zero, porque signals são sempre lidos no momento do acesso, não capturados em um closure.

Comparação de Tamanho de Bundle

Medimos ambas as construções de produção com a mesma configuração Vite, compressão gzip e estratégia de code splitting.

Métrica React 19 SolidJS 1.9 Diferença
Runtime do framework 44.2 KB (gzip) 7.1 KB (gzip) -84%
Bundle inicial total 127.8 KB 89.3 KB -30%
App total (todos os chunks) 312.4 KB 274.1 KB -12%
Primeiro chunk (caminho crítico) 68.4 KB 41.2 KB -40%
Número de chunks 14 14 Mesmo

O runtime do Solid é dramaticamente menor. Isso não é novidade -- Ryan Carniato falou sobre isso extensivamente. Mas o que nos surpreendeu foi que a diferença do tamanho total do app se estreitou significativamente uma vez que você adiciona código de aplicação real, bibliotecas de terceiros e assets.

O runtime do framework importa mais para a carga inicial. E em 7.1 KB gzipped, o Solid basicamente desaparece no ruído. O 44 KB do React é notável, especialmente em conexões móveis.

Tree Shaking

Solid faz tree shaking melhor que React. Primitivas Solid não utilizadas são eliminadas completamente. Com React, o reconciliador e a arquitetura de fiber são enviados independentemente de você usar todos os seus recursos ou não. Confirmamos isso construindo uma página mínima em ambos -- o piso do Solid é mais baixo.

Construímos o Mesmo App em SolidJS e React: Signals vs Hooks - arquitetura

Benchmarks de Desempenho de Renderização

Executamos benchmarks estruturados usando perfis de desempenho do Chrome DevTools, Lighthouse e instrumentação de timing customizada. Todos os testes em um MacBook Pro M2 com throttling de CPU definido como 4x slowdown para simular dispositivos de médio alcance.

Renderização de Gráfico (5.000 pontos de dados)

Métrica React 19 SolidJS 1.9
Renderização inicial 142ms 89ms
Re-renderização ao mudar filtro 67ms 23ms
Memória durante renderização 18.4 MB 11.2 MB
Nós DOM criados 5.847 5.812

Solid foi consistentemente mais rápido em re-renderizações porque não faz diff de uma árvore virtual DOM. Quando um signal de filtro muda, apenas as expressões que leem esse signal são atualizadas. As melhorias do compilador React 19 ajudaram -- o mesmo teste em React 18 foi 95ms para re-renderizações -- mas Solid ainda tinha uma clara vantagem.

Feed de Pedidos em Tempo Real (100 atualizações/segundo)

Isso é onde as coisas ficaram realmente interessantes. Empurramos 100 mensagens WebSocket por segundo para o feed de pedidos.

Métrica React 19 SolidJS 1.9
Quedas de frame (por 10s) 12 2
Tempo médio de paint 8.3ms 3.1ms
Tempo máximo de paint 34ms 11ms
Uso de CPU (média) 24% 9%

Solid absolutamente esmagou esse benchmark. Atualizações de alta frequência são onde a reatividade de granulação fina paga os maiores dividendos. React estava agrupando atualizações (o que é bom), mas ainda fazendo diff de mais DOM do que necessário em cada lote.

Devemos notar: o useTransition e agrupamento automático do React 19 tornaram isso muito melhor do que o React 18 teria sido. E para a maioria dos apps do mundo real, você não está empurrando 100 atualizações por segundo. Com 10 atualizações/segundo, ambos os frameworks eram suaves.

Formulário Complexo com 40 Campos

Métrica React 19 SolidJS 1.9
Lag de entrada de teclado 2-4ms <1ms
Renderização de envio de formulário 28ms 12ms
Re-renderizações de componente por teclada 3-8 1

Em React, digitar em um campo causaria a re-renderização dos componentes pais a menos que memorizássemos tudo cuidadosamente. Em Solid, digitar em um campo literalmente apenas atualiza aquele nó de texto DOM do campo. Nada mais é re-executado.

Experiência do Desenvolvedor e Ecossistema

Desempenho não é tudo. Você tem que realmente construir a coisa, depurá-la, contratar para ela e mantê-la.

Tamanho do Ecossistema (a partir do início de 2025)

Fator React SolidJS
Downloads semanais no npm ~28M ~85K
GitHub stars 233K+ 33K+
Perguntas no Stack Overflow 470K+ ~2K
Bibliotecas de componentes de UI 50+ opções maduras 5-8 opções
Postagens de emprego (LinkedIn EUA) ~45.000 ~200
Meta-framework Next.js (maduro) SolidStart (beta)

Este é o elefante na sala. O ecossistema do React é ordens de magnitude maior. Quando precisávamos de um seletor de intervalo de datas para Solid, tínhamos que portar um do React ou escrever o nosso próprio. Em React, tínhamos 15 opções para escolher.

Usamos Kobalte para primitivos de UI acessíveis em Solid, e é genuinamente bom. Mas não é Radix UI em termos de cobertura de componentes.

Debugging

React DevTools é maduro, bem mantido e algo que todo desenvolvedor frontend conhece. Solid tem sua própria extensão DevTools, e é decente -- você pode inspecionar o gráfico de signal, que é na verdade mais útil para rastrear bugs de reatividade do que a visualização da árvore de componentes do React. Mas é menos refinado.

Suporte a TypeScript

Ambos são excelentes. O suporte a TypeScript do Solid é na verdade ligeiramente melhor para JSX porque o compilador lida com mais em tempo de construção. Tínhamos menos ginástica de tipo na base de código Solid.

Trade-offs de Produção que Realmente Importam

Depois de construir ambas as versões e implantar a versão Solid em staging (o cliente ultimately escolheu React para produção -- mais sobre isso abaixo), aqui estão os trade-offs que realmente importavam:

Contratação

Nosso cliente tem um time de 8 desenvolvedores frontend. Todos conhecem React. Nenhum tinha usado Solid. Estimativa de tempo de treinamento: 2-3 semanas para proficiência, 2-3 meses para maestria. Esse é um custo real. Este é o fator individual mais importante na maioria das decisões de produção, e é por isso que normalmente recomendamos React ou frameworks como Next.js para times que precisam contratar frequentemente.

Compatibilidade de Biblioteca de Terceiros

Tínhamos que escrever wrappers customizados para três bibliotecas que tinham integrações específicas do React. Isso adicionou aproximadamente 20 horas de tempo de desenvolvimento. Em um projeto React, essas horas não existem.

Renderização no Lado do Servidor

SolidStart é promissor mas estava ainda em beta durante nosso projeto. Next.js é testado em batalha. Para projetos onde precisamos de SSR de nível de produção com todos os extras, ainda estamos recorrendo a desenvolvimento Next.js ou Astro dependendo do modelo de conteúdo.

Desempenho Onde Importa

Aqui está a verdade honesta: para este dashboard específico, ambos os frameworks tiveram bom desempenho suficiente para produção. A versão Solid foi mensuravelmente mais rápida, mas a versão React nunca foi lenta. Os usuários não notariam a diferença na maioria das interações.

A exceção foi o feed em tempo real com altas frequências de atualização. Se seu app tem um caso de uso como esse, a vantagem de desempenho do Solid é significativa, não apenas bragging de benchmark.

Quando Escolher SolidJS em vez de React

Depois desta experiência, aqui está nosso framework honesto para a decisão:

Escolha SolidJS quando:

  • Seu app tem atualizações reativas de alta frequência (dashboards, plataformas de trading, colaboração em tempo real)
  • O tamanho do bundle é crítico (widgets incorporados, micro-frontends, mobile-first)
  • Seu time é pequeno e disposto a investir em aprender um novo paradigma
  • Você quer reatividade de granulação fina sem lutar contra o framework
  • Você está construindo algo novo e não precisa de um ecossistema massivo de biblioteca de componentes

Escolha React quando:

  • Seu team já conhece React (sozinho, isso geralmente é decisivo)
  • Você precisa de um meta-framework maduro (Next.js, Remix)
  • Disponibilidade de biblioteca de terceiros é importante
  • Você está contratando e precisa de um grande pool de talento
  • Os requisitos de desempenho do seu app são típicos (não extremos)

Para nossos projetos de desenvolvimento de CMS headless, React ainda domina porque integrações de CMS (Sanity, Contentful, Storyblok) têm SDKs React de primeira classe. O suporte a Solid existe mas geralmente é mantido pela comunidade.

Comparação de Código: Padrões Reais

Vamos ver alguns padrões reais do projeto lado a lado.

Busca de Dados com Estados de Carregamento

React:

function Dashboard() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchDashboardData()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <Skeleton />;
  if (error) return <ErrorBanner error={error} />;
  return <DashboardGrid data={data} />;
}

SolidJS:

function Dashboard() {
  const [data] = createResource(fetchDashboardData);

  return (
    <Suspense fallback={<Skeleton />}>
      <ErrorBoundary fallback={(err) => <ErrorBanner error={err} />}>
        <DashboardGrid data={data()} />
      </ErrorBoundary>
    </Suspense>
  );
}

O createResource do Solid com Suspense é genuinamente elegante. React também tem Suspense (e melhorou em React 19), mas a versão do Solid se sentia mais natural para trabalhar. Menos boilerplate, menos variáveis de estado para gerenciar.

Renderização Condicional

React:

{user ? (
  <Profile user={user} />
) : (
  <LoginPrompt />
)}

SolidJS:

<Show when={user()} fallback={<LoginPrompt />}>
  {(u) => <Profile user={u()} />}
</Show>

O componente <Show> do Solid existe porque ternários não funcionam da mesma forma quando a função do componente é executada apenas uma vez. Levou tempo para se acostumar, mas o padrão de callback oferece a você uma referência estreita e não-nula, o que é legal para TypeScript.

Renderização de Lista

React:

{orders.map(order => (
  <OrderRow key={order.id} order={order} />
))}

SolidJS:

<For each={orders()}>
  {(order) => <OrderRow order={order} />}
</For>

O <For> do Solid não precisa de chaves porque rastreia itens de array por referência. Quando um item se move no array, Solid move o nó DOM real. React desmontaria e remontaria. É por isso que o desempenho de lista do Solid é tão bom.

FAQ

SolidJS é pronto para produção em 2025?

Sim. Solid 1.x tem sido estável por mais de dois anos. Empresas como Cloudflare e Samsung usaram em produção. A biblioteca principal é madura e bem testada. O ecossistema ao seu redor (SolidStart, bibliotecas de componentes) é menor do que o do React, mas crescendo steadily. A questão não é se Solid está pronto -- é se seus requisitos de team e projeto se alinham com o tamanho do seu ecossistema.

Posso migrar do React para SolidJS incrementalmente?

Não facilmente. Apesar da sintaxe JSX similar, os modelos de runtime são fundamentalmente diferentes. Você não pode incorporar componentes Solid dentro de um app React (ou vice versa) sem limites de iframe ou web component. Uma migração seria essencialmente uma reescrita. Se você está considerando, comece com um novo recurso isolado ou micro-frontend em vez de tentar converter código React existente.

SolidJS suporta renderização no lado do servidor?

Sim. SolidStart fornece SSR, streaming e server functions. É funcional e melhorando rapidamente, mas a partir do início de 2025, ainda é menos maduro que Next.js ou Remix. Para projetos pesados em SSR, ainda recomendaríamos avaliar Next.js ou Astro dependendo de suas necessidades de conteúdo.

Como o compilador React 19 se compara à abordagem do Solid?

O compilador React 19 (anteriormente React Forget) auto-memoiza componentes para reduzir re-renderizações desnecessárias. É uma melhoria significativa. Mas ainda está trabalhando dentro do modelo do React de re-executar funções de componente e fazer diff de um DOM virtual. Solid pula ambas as etapas completamente. O compilador torna React mais rápido, mas não muda a arquitetura fundamental. Em nossos benchmarks, React 19 com o compilador foi cerca de 30% mais rápido que React 18, mas ainda mais lento que Solid em cenários de atualizações pesadas.

E quanto Preact Signals como um meio termo?

Preact Signals (e o adaptador @preact/signals-react) trazem reatividade similar a signal para o ecossistema React. É uma abordagem interessante, mas está lutando contra o modelo central do React em vez de funcionar com ele. Testamos brevemente e encontramos casos extremos com Suspense e features concorrentes. Se você quer signals, Solid oferece a experiência completa sem a desadaptação de impedância.

SolidJS é mais difícil de aprender que React?

Se você já conhece React, a API do Solid parecerá familiar -- JSX similar, padrões similares. A parte difícil é desaprender o modelo mental do React. Você vai recorrer a padrões useEffect que não existem. Você vai desestruturar props e quebrar reatividade. Você vai tentar early returns e se perguntará por que não funcionam. Orçar cerca de 1-2 semanas para um dev React experiente se tornar produtivo em Solid, e mais um ou dois meses para parar de escrever Solid com sabor React.

Qual framework tem melhor suporte a TypeScript?

Ambos têm excelente suporte a TypeScript. Solid tem uma ligeira vantagem porque seu compilador pode fornecer tipos mais estreitos em certos padrões (como o callback em <Show>), e você não precisa do mesmo volume de parâmetros de tipo genérico que alguns hooks React complexos às vezes requerem. Mas honestamente, ambos são ótimos. Isso não deve ser um fator decisivo.

Devo usar SolidJS para meu próximo projeto?

Depende de seus restrições. Se você é um pequeno team construindo algo sensível ao desempenho e está disposto a investir em curva de aprendizado e lidar com um ecossistema menor, Solid é uma escolha genuinamente excelente. Se você precisa contratar desenvolvedores React, usar bibliotecas de componentes estabelecidas, ou precisa de um meta-framework testado em batalha para produção, React é o aposto mais seguro. Não há resposta universal -- apenas a resposta certa para sua situação específica. Se você quer conversar sobre a decisão para seu projeto, entre em contato conosco e podemos ajudá-lo a avaliar os trade-offs.