El trimestre pasado, teníamos un proyecto de cliente que nos dio la excusa perfecta para hacer algo que estábamos ansiosos por intentar: construir la misma aplicación tanto en SolidJS como en React, y luego comparar todo. No una app de tareas. No un contador. Un dashboard de producción real con autenticación, actualizaciones de datos en tiempo real, formularios complejos y un módulo de gráficos que renderiza miles de puntos de datos.

Los resultados nos sorprendieron. No porque un framework "ganara" -- sino porque los tradeoffs eran mucho más matizados de lo que sugiere el discurso de Twitter. Algunas cosas las esperábamos. Algunas cosas nos sorprendieron completamente. Esto es lo que realmente aprendimos.

Tabla de Contenidos

We Built the Same App in SolidJS and React: Signals vs Hooks

La App que Construimos

La aplicación es un dashboard de análisis en tiempo real para un cliente de e-commerce. Aquí está lo que incluye:

  • Flujo de autenticación con tokens JWT y lógica de refresh
  • Dashboard con 6 paneles de widgets, cada uno obteniendo datos de diferentes endpoints de API
  • Feed de órdenes en tiempo real usando conexiones WebSocket
  • Gráficos interactivos renderizando 5,000+ puntos de datos (usando una librería de gráficos)
  • Formularios de filtro complejos con dropdowns dependientes y selectores de rango de fechas
  • Panel de configuración de administrador con gestión de estado anidado
  • Layout responsivo con navegación de barra lateral

Ambas versiones se conectan a la misma API backend. Ambas usan TypeScript. Ambas usan Vite como herramienta de build. Mantuvimos las dependencias de terceros lo más similares posible -- misma librería de gráficos (Chart.js), mismo cliente HTTP (ky), mismo wrapper de WebSocket.

La versión de React usa React 19 con hooks. La versión de SolidJS usa Solid 1.9. No usamos meta-frameworks (sin Next.js, sin SolidStart) porque queríamos aislar las diferencias del framework sin que routing y SSR enturbiaran la comparación.

Signals vs Hooks: Un Cambio de Modelo Mental

Este es el grande. Y honestamente, le tomó a nuestro equipo alrededor de una semana dejar de escribir código con forma de React en SolidJS.

Cómo Funcionan los React Hooks

Tú ya sabes esto, pero vale la pena establecerlo explícitamente para la comparación. El modelo de React es: cuando el estado cambia, la función del componente se re-ejecuta. Toda la función. Cada useState, cada useMemo, cada useCallback -- todos son mecanismos para trabajar alrededor del hecho de que la función completa se re-ejecuta.

// React: Esta función completa se re-ejecuta en cada cambio de estado
function OrderFeed() {
  const [orders, setOrders] = useState([]);
  const [filter, setFilter] = useState('all');
  
  // Esto se recalcula en cada renderizado a menos que lo memoicemos
  const filteredOrders = useMemo(() => 
    orders.filter(o => filter === 'all' || o.status === filter),
    [orders, filter]
  );

  // Esta ref se recrea conceptualmente en cada renderizado
  const handleNewOrder = useCallback((order) => {
    setOrders(prev => [order, ...prev]);
  }, []);

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

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

Cómo Funcionan los Solid Signals

El modelo de Solid es fundamentalmente diferente. La función del componente se ejecuta una sola vez. Después de eso, solo las expresiones específicas que leen un signal se re-ejecutan cuando ese signal cambia. No hay virtual DOM diff. No hay reconciliación. El grafo reactivo rastrea exactamente qué nodos del DOM dependen de qué signals.

// Solid: Esta función se ejecuta UNA SOLA VEZ
function OrderFeed() {
  const [orders, setOrders] = createSignal([]);
  const [filter, setFilter] = createSignal('all');
  
  // Esto se rastrea automáticamente -- no se necesita array de dependencias
  const filteredOrders = createMemo(() => 
    orders().filter(o => filter() === 'all' || o.status === filter())
  );

  // No se necesita useCallback -- este closure es estable
  const handleNewOrder = (order) => {
    setOrders(prev => [order, ...prev]);
  };

  // onMount en lugar de useEffect con deps vacías
  onMount(() => {
    const ws = connectWebSocket(handleNewOrder);
    onCleanup(() => ws.close());
  });

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

Qué Significa Esto en la Práctica

La versión de Solid no tiene arrays de dependencias. Sin useCallback. Sin useMemo para estado derivado (aunque createMemo existe para cálculos costosos -- la diferencia es que es opt-in para rendimiento, no requerido para corrección).

Aquí está lo que realmente nos mordió durante el desarrollo:

  1. La destructuración de props mata la reactividad en Solid. Teníamos un desarrollador junior destructurando props en un componente Solid y pasamos 45 minutos debugueando por qué las actualizaciones no se propagaban. En React, la destructuración está bien porque la función completa se re-ejecuta. En Solid, necesitas acceder a props.value dentro del JSX o un scope rastreado.

  2. Los early returns son complicados en Solid. No puedes hacer if (!data()) return <Loading /> al inicio de un componente Solid de la manera que lo harías en React. La función del componente solo se ejecuta una vez, así que ese condicional nunca se re-evaluaría. Necesitas <Show when={data()}> en su lugar.

  3. Sin bugs de closure obsoleto. Este fue el gran ganador. En nuestra versión de React, tuvimos tres bugs de closure obsoleto separados en la primera semana relacionados con handlers de WebSocket capturando estado antiguo. La versión de Solid tuvo cero, porque los signals siempre se leen en el momento del acceso, no capturados en un closure.

Comparación de Tamaño de Bundle

Medimos ambas compilaciones de producción con la misma configuración de Vite, compresión gzip y estrategia de code splitting.

Métrica React 19 SolidJS 1.9 Diferencia
Runtime del framework 44.2 KB (gzip) 7.1 KB (gzip) -84%
Bundle inicial total 127.8 KB 89.3 KB -30%
App total (todos los chunks) 312.4 KB 274.1 KB -12%
Primer chunk (ruta crítica) 68.4 KB 41.2 KB -40%
Número de chunks 14 14 Igual

El runtime de Solid es dramáticamente más pequeño. Eso no es novedad -- Ryan Carniato ha hablado extensamente sobre esto. Pero lo que nos sorprendió fue que la diferencia de tamaño total de la app se redujo significativamente una vez que agregaste código de aplicación real, librerías de terceros y assets.

El runtime del framework importa más para la carga inicial. Y a 7.1 KB gzipped, Solid básicamente desaparece en el ruido. Los 44 KB de React son notables, especialmente en conexiones móviles.

Tree Shaking

Solid hace tree-shaking mejor que React. Las primitivas de Solid no utilizadas se eliminan completamente. Con React, el reconciliador y la arquitectura fiber se envían sin importar si usas todas sus características o no. Confirmamos esto construyendo una página mínima en ambos -- el piso de Solid es más bajo.

We Built the Same App in SolidJS and React: Signals vs Hooks - architecture

Benchmarks de Rendimiento de Renderizado

Ejecutamos benchmarks estructurados usando perfiles de rendimiento de Chrome DevTools, Lighthouse e instrumentación de timing personalizada. Todas las pruebas en un MacBook Pro M2 con throttling de CPU establecido a 4x slowdown para simular dispositivos de rango medio.

Renderizado de Gráficos (5,000 puntos de datos)

Métrica React 19 SolidJS 1.9
Renderizado inicial 142ms 89ms
Re-renderizado en cambio de filtro 67ms 23ms
Memoria durante renderizado 18.4 MB 11.2 MB
Nodos del DOM creados 5,847 5,812

Solid fue consistentemente más rápido en re-renderizados porque no difiere un árbol virtual del DOM. Cuando un signal de filtro cambia, solo las expresiones que leen ese signal se actualizan. Las mejoras del compilador de React 19 ayudaron -- la misma prueba en React 18 fue 95ms para re-renderizados -- pero Solid seguía teniendo una ventaja clara.

Feed de Órdenes en Tiempo Real (100 actualizaciones/segundo)

Esto es donde las cosas se pusieron realmente interesantes. Empujamos 100 mensajes de WebSocket por segundo al feed de órdenes.

Métrica React 19 SolidJS 1.9
Caídas de fotogramas (por 10s) 12 2
Tiempo de paint promedio 8.3ms 3.1ms
Tiempo de paint máximo 34ms 11ms
Uso de CPU (promedio) 24% 9%

Solid absolutamente aplastó este benchmark. Las actualizaciones de alta frecuencia son donde la reactividad fine-grained paga los mayores dividendos. React estaba batching de actualizaciones (lo cual es bueno), pero aún estaba difiriendo más DOM del necesario en cada batch.

Deberíamos notar: el useTransition de React 19 y el batching automático hicieron esto mucho mejor que lo que habría sido React 18. Y para la mayoría de las apps del mundo real, no estás empujando 100 actualizaciones por segundo. A 10 actualizaciones/segundo, ambos frameworks eran suave.

Formulario Complejo con 40 Campos

Métrica React 19 SolidJS 1.9
Lag de entrada de keystroke 2-4ms <1ms
Renderizado de envío de formulario 28ms 12ms
Re-renderizados de componentes por keystroke 3-8 1

En React, escribir en un campo causaría que los componentes padres se re-renderizaran a menos que memoizáramos todo cuidadosamente. En Solid, escribir en un campo literalmente solo actualiza ese nodo de texto del DOM de ese campo. Nada más se re-ejecuta.

Experiencia del Desarrollador y Ecosistema

El rendimiento no es todo. Realmente tienes que construir la cosa, debuguearla, contratar para ella y mantenerla.

Tamaño del Ecosistema (a principios de 2025)

Factor React SolidJS
Descargas semanales en npm ~28M ~85K
Estrellas en GitHub 233K+ 33K+
Preguntas en Stack Overflow 470K+ ~2K
Librerías de componentes UI 50+ opciones maduras 5-8 opciones
Publicaciones de empleos (LinkedIn US) ~45,000 ~200
Meta-framework Next.js (maduro) SolidStart (beta)

Este es el elefante en la sala. El ecosistema de React es órdenes de magnitud más grande. Cuando necesitábamos un date range picker para Solid, tuvimos que portar uno de React o escribir el nuestro. En React, teníamos 15 opciones para elegir.

Usamos Kobalte para primitivos de UI accesibles en Solid, y es genuinamente bueno. Pero no es Radix UI en términos de cobertura de componentes.

Debugging

React DevTools es maduro, bien mantenido, y algo que cada desarrollador frontend conoce. Solid tiene su propia extensión de DevTools, y es decente -- puedes inspeccionar el grafo de signal, que es realmente más útil para rastrear bugs de reactividad que la vista del árbol de componentes de React. Pero es menos pulido.

Soporte de TypeScript

Ambos son excelentes. El soporte de TypeScript de Solid es realmente ligeramente mejor para JSX porque el compilador maneja más en tiempo de compilación. Tuvimos menos acrobacias de tipo en la base de código de Solid.

Tradeoffs de Producción que Realmente Importan

Después de construir ambas versiones e implementar la versión de Solid en staging (el cliente finalmente eligió React para producción -- más sobre esto abajo), aquí están los tradeoffs que realmente importaban:

Contratación

Nuestro cliente tiene un equipo de 8 desarrolladores frontend. Todos conocen React. Ninguno había usado Solid. Estimación de tiempo de entrenamiento: 2-3 semanas para profesionalidad, 2-3 meses para maestría. Ese es un costo real. Este es el factor más grande en la mayoría de decisiones de producción, y es por qué típicamente recomendamos React o frameworks como Next.js para equipos que necesitan contratar frecuentemente.

Compatibilidad de Librerías de Terceros

Tuvimos que escribir wrappers personalizados para tres librerías que tenían integraciones específicas de React. Esto agregó aproximadamente 20 horas de tiempo de desarrollo. En un proyecto de React, esas horas no existen.

Renderizado del Lado del Servidor

SolidStart es prometedor pero seguía siendo beta durante nuestro proyecto. Next.js es battle-tested. Para proyectos donde necesitamos SSR de nivel de producción con todos los adornos, seguimos alcanzando Next.js development o Astro dependiendo del modelo de contenido.

Rendimiento Donde Importa

Aquí está la verdad honesta: para este dashboard en particular, ambos frameworks funcionaron lo suficientemente bien para producción. La versión de Solid fue mediblemente más rápida, pero la versión de React nunca fue lenta. Los usuarios no notarían la diferencia en la mayoría de interacciones.

La excepción fue el feed en tiempo real a altas frecuencias de actualización. Si tu app tiene un caso de uso como ese, la ventaja de rendimiento de Solid es significativa, no solo alardear de benchmark.

Cuándo Elegir SolidJS sobre React

Después de este experimento, aquí está nuestro framework honesto para la decisión:

Elige SolidJS cuando:

  • Tu app tiene actualizaciones reactivas de alta frecuencia (dashboards, plataformas de trading, colaboración en tiempo real)
  • El tamaño del bundle es crítico (widgets embebidos, micro-frontends, mobile-first)
  • Tu equipo es pequeño y está dispuesto a invertir en aprender un nuevo paradigma
  • Quieres reactividad fine-grained sin pelear contra el framework
  • Estás construyendo algo nuevo y no necesitas un ecosistema de librería de componentes masivo

Elige React cuando:

  • Tu equipo ya conoce React (esto solo generalmente es decisivo)
  • Necesitas un meta-framework maduro (Next.js, Remix)
  • La disponibilidad de librerías de terceros es importante
  • Estás contratando y necesitas un gran pool de talento
  • Los requerimientos de rendimiento de tu app son típicos (no extremos)

Para nuestros proyectos de headless CMS development, React aún domina porque las integraciones de CMS (Sanity, Contentful, Storyblok) tienen SDKs de React de primera clase. El soporte de Solid existe pero a menudo es mantenido por la comunidad.

Comparación de Código: Patrones Reales

Veamos algunos patrones reales del proyecto lado a lado.

Data Fetching con Estados de Carga

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>
  );
}

El createResource de Solid con Suspense es genuinamente elegante. React también tiene Suspense (y ha mejorado en React 19), pero la versión de Solid se sintió más natural trabajar. Menos boilerplate, menos variables de estado que gestionar.

Renderizado Condicional

React:

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

SolidJS:

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

El componente <Show> de Solid existe porque los ternarios no funcionan igual cuando la función del componente solo se ejecuta una vez. Tomó acostumbrarse, pero el patrón de callback te da una referencia estrecha y no-null que es buena para TypeScript.

Renderizado de Listas

React:

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

SolidJS:

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

El <For> de Solid no necesita keys porque rastrea items del array por referencia. Cuando un item se mueve en el array, Solid mueve el nodo del DOM real. React desmontaría y remontaría. Por eso el rendimiento de lista de Solid es tan bueno.

FAQ

¿Es SolidJS production-ready en 2025?

Sí. Solid 1.x ha sido estable por más de dos años. Compañías como Cloudflare y Samsung lo han usado en producción. La librería principal es madura y bien testeada. El ecosistema alrededor (SolidStart, librerías de componentes) es más pequeño que el de React pero está creciendo constantemente. La pregunta no es si Solid está listo -- es si los requerimientos de tu equipo y proyecto se alinean con el tamaño de su ecosistema.

¿Puedo migrar de React a SolidJS incrementalmente?

No fácilmente. A pesar de la sintaxis JSX similar, los modelos de runtime son fundamentalmente diferentes. No puedes incrustar componentes de Solid dentro de una app de React (o vice versa) sin límites de iframe o web component. Una migración sería esencialmente una reescritura. Si estás considerándolo, comienza con una característica nueva aislada o micro-frontend en lugar de intentar convertir código de React existente.

¿SolidJS soporta renderizado del lado del servidor?

Sí. SolidStart proporciona SSR, streaming y server functions. Es funcional y mejora rápidamente, pero a principios de 2025, aún es menos maduro que Next.js o Remix. Para proyectos SSR-heavy, seguiríamos recomendando evaluar Next.js o Astro dependiendo de tus necesidades de contenido.

¿Cómo se compara el compilador de React 19 con el enfoque de Solid?

El compilador de React 19 (anteriormente React Forget) auto-memoiza componentes para reducir re-renderizados innecesarios. Es una mejora significativa. Pero seguirá funcionando dentro del modelo de React de re-ejecutar funciones de componentes y difundir un virtual DOM. Solid salta ambos pasos completamente. El compilador hace React más rápido, pero no cambia la arquitectura fundamental. En nuestros benchmarks, React 19 con el compilador fue aproximadamente 30% más rápido que React 18, pero aún más lento que Solid en escenarios update-heavy.

¿Qué hay de Preact Signals como un punto medio?

Preact Signals (y el adaptador @preact/signals-react) traen reactividad similar a signals al ecosistema de React. Es un enfoque interesante, pero está peleando contra el modelo central de React en lugar de trabajar con él. Lo probamos brevemente y encontramos casos extremos con Suspense y características concurrentes. Si quieres signals, Solid te da la experiencia completa sin la desajuste de impedancia.

¿Es SolidJS más difícil de aprender que React?

Si ya conoces React, la API de Solid se verá familiar -- JSX similar, patrones similares. La parte difícil es desaprender el modelo mental de React. Alcanzarás patrones de useEffect que no existen. Destructurarás props y romperás la reactividad. Intentarás early returns y te preguntarás por qué no funcionan. Presupuesto alrededor de 1-2 semanas para que un dev de React experimentado sea productivo en Solid, y otros 1-2 meses para dejar de escribir Solid con sabor a React.

¿Qué framework tiene mejor soporte de TypeScript?

Ambos tienen excelente soporte de TypeScript. Solid tiene una ligera ventaja porque su compilador puede proporcionar tipos más estrechos en ciertos patrones (como el callback en <Show>), y no necesitas el mismo volumen de parámetros de tipo genérico que los hooks de React complejos a veces requieren. Pero honestamente, ambos son excelentes. Esto no debería ser un factor decisivo.

¿Debería usar SolidJS para mi próximo proyecto?

Depende de tus restricciones. Si eres un equipo pequeño construyendo algo sensible al rendimiento y estás dispuesto a invertir en curva de aprendizaje y trabajar alrededor de un ecosistema más pequeño, Solid es genuinamente una opción excelente. Si necesitas contratar desarrolladores de React, usar librerías de componentes establecidas, o necesitas un meta-framework battle-tested para producción, React es la apuesta más segura. No hay una respuesta universal -- solo la respuesta correcta para tu situación específica. Si quieres hablar sobre la decisión para tu proyecto, contáctanos y podemos ayudarte a evaluar los tradeoffs.