Modos del proyecto: SSR, SPA e islands
Los tres modos en que SolidStart puede entregar la misma aplicación, a alto nivel, y qué eliges al crear la app. SSR es el modo por defecto: el servidor renderiza HTML por petición, lo transmite en streaming y el cliente lo hidrata, lo mejor para SEO y primer pintado. SPA se activa con ssr false: el servidor sirve un shell vacío y todo se renderiza en el cliente, útil tras login o en hosts estáticos. Islands es experimental: HTML estático con solo las islas interactivas hidratadas, para minimizar el JavaScript. El asistente pregunta por SSR al crear el proyecto; el modo es en el fondo un ajuste de configuración.
Una misma aplicación SolidStart puede entregarse de tres maneras distintas, y la elección entre ellas es sobre todo una decisión de cuánto trabajo ocurre en el servidor y cuánto en el navegador. En un extremo, SSR renderiza cada página en el servidor y la hidrata en el cliente; en el otro, la SPA no toca el servidor para renderizar y lo hace todo en el navegador; en medio, el modo islands riega de HTML estático la página y solo hidrata las porciones que de verdad necesitan JavaScript. Lo notable de Solid es que este espectro es casi un interruptor de configuración, porque su renderizado es isomorfo por diseño. Esta lección los recorre a alto nivel y cierra con la pregunta práctica: qué eliges cuando el asistente te lo pregunta al crear el proyecto.
- Distinguir SSR, SPA e islands por dónde ocurre el render y qué llega al navegador.
- Reconocer que el modo se decide en
app.config.tsy se pregunta al crear la app. - Enumerar los criterios que inclinan la elección hacia cada modo.
- Situar islands como opción experimental y saber cuándo tendría sentido.
Los tres modos comparten tu app.tsx y tus rutas; lo que cambia es el reparto del trabajo entre los dos entornos. Verlos juntos, por lo que llega al navegador, aclara la diferencia antes de entrar en cada uno.
flowchart TD Q[que llega al navegador] --> SSR[SSR HTML por peticion mas hidratacion] Q --> SPA[SPA shell vacio mas render en el cliente] Q --> ISL[Islands HTML estatico mas islas hidratadas] SSR --> U1[SEO y primer pintado rapido y contenido dinamico] SPA --> U2[apps tras login y hosts estaticos sin SEO] ISL --> U3[sitios de contenido con minimo JavaScript] style SSR fill:#a6e3a1,color:#11111b style SPA fill:#89b4fa,color:#11111b style ISL fill:#f9e2af,color:#11111b
SSR
El servidor renderiza HTML por petición y el cliente lo hidrata. Máximo SEO y primer pintado, al precio de ejecutar la lógica en los dos entornos. El defecto.
SPA
El servidor sirve un shell vacío y el navegador renderiza todo. Despliegue y modelo mental simples, al precio de una pantalla inicial en blanco y poco SEO.
Islands
HTML estático con solo las islas interactivas hidratadas. JavaScript mínimo en el cliente, aún experimental y pensado para sitios de contenido.
SSR: el modo por defecto
Con ssr en true —el valor por defecto— cada petición se renderiza en el servidor: SolidStart ejecuta tu árbol, produce el HTML de la página y lo envía al navegador, que lo pinta de inmediato y después lo hidrata con entry-client. El usuario ve contenido real en el primer viaje, antes de que el JavaScript cargue, y los buscadores reciben una página completa.
// app.config.ts
import { defineConfig } from "@solidjs/start/config";
export default defineConfig({ ssr: true }); // el defecto explicito
El SSR de SolidStart transmite en streaming por defecto: en lugar de esperar a que toda la página esté lista, envía el HTML a trozos y deja que las partes asíncronas —envueltas en Suspense— lleguen cuando resuelven. Existen variantes de menor uso, un modo async que espera a tener la página entera antes de enviarla y un modo sync que no resuelve asincronía, pero el streaming es el que da el mejor tiempo hasta el primer byte y el revelado progresivo. Este es el modo recomendado para la mayoría de aplicaciones: SEO, primer pintado veloz y contenido que depende de cada petición.
El coste que SSR paga a cambio de esas virtudes es la hidratación: tu árbol corre dos veces, una en el servidor para escupir el HTML y otra en el cliente para reconectarle la reactividad sobre ese mismo DOM. Eso implica enviar al navegador el JavaScript de toda la página y volver a ejecutar su lógica de arranque, aunque buena parte del contenido sea estático. Solid mitiga ese coste con su grano fino —hidrata con precisión quirúrgica y sin reconciliar árboles—, pero el trabajo no es cero, y es justo ese trabajo el que el modo islands se propone recortar. Tenerlo presente evita idealizar el SSR: es el mejor modo por defecto, no un modo gratis.
El streaming, además, no es un detalle aislado: es la razón de ser de todo lo que aprendiste sobre Suspense, createAsync y las transiciones en los niveles de async. Cuando una parte de la página depende de un dato que aún viaja, su frontera de Suspense deja que el servidor envíe primero el resto del HTML y complete ese hueco en cuanto el dato resuelve, sin bloquear el primer byte.
// bajo SSR, esta frontera fluye en streaming: el resto de la pagina
// se envia ya, y el panel llega cuando su dato resuelve
<Suspense fallback={<Cargando />}>
<PanelDeDatos />
</Suspense>
Lo que en el cliente veías como un patrón de carga elegante es, bajo SSR, el mecanismo que permite transmitir una página progresivamente. El modo por defecto y las primitivas de datos fueron diseñados para encajar; SSR es el escenario donde revelan su sentido pleno.
SPA: todo en el cliente
Poner ssr en false apaga el renderizado de servidor. El servidor —o un host estático— entrega entonces un shell mínimo, una página casi vacía cuyo contenedor se llenará en el navegador una vez que cargue y ejecute el JavaScript. Es el modelo clásico de aplicación de una sola página.
export default defineConfig({ ssr: false }); // modo SPA
El precio es visible: hay una ventana en blanco hasta que el bundle arranca, y los buscadores reciben poco que indexar. A cambio, ganas simplicidad de despliegue —una SPA puede vivir en un CDN estático sin proceso de servidor— y evitas por completo la complejidad de la hidratación y del código que debe correr en dos entornos. Sigue siendo un proyecto SolidStart de pleno derecho: conservas el enrutado por ficheros, el build y, si mantienes un servidor, incluso las funciones de servidor. Es la elección sensata cuando el SEO no importa y el primer pintado tampoco es crítico: paneles tras un login, herramientas internas, aplicaciones muy interactivas donde el contenido no es público.
Si necesitas algo de SEO sin renunciar a la SPA, aún puedes pre-renderizar rutas concretas a HTML en el build; pero cuando el SEO es central, esa misma necesidad es la señal de que en realidad querías SSR.
// una SPA puede congelar rutas concretas a HTML en el build
export default defineConfig({
ssr: false,
server: { prerender: { routes: ["/", "/precios"] } },
});
Desactivar SSR y desplegar a un host estático suelen ir de la mano, pero son decisiones separadas. ssr: false dice dónde se renderiza; el preset de despliegue dice a qué plataforma va el artefacto. Puedes tener una SPA servida por un servidor Node que además expone funciones de servidor, o una SPA congelada en un bucket estático sin servidor alguno. Y a la inversa, un proyecto SSR puede pre-renderizar rutas a estático con prerender. Modo de render y destino de despliegue son ejes ortogonales que combinas según el caso.
Islands: hidratación parcial
El tercer modo, todavía experimental, busca el mejor de los dos mundos para sitios dominados por contenido. En el modo islands, el servidor genera HTML estático para toda la página, pero solo las porciones marcadas como interactivas —las islas— envían y ejecutan JavaScript en el cliente. El resto de la página es HTML puro que nunca se hidrata, de modo que el navegador descarga y ejecuta drásticamente menos código.
export default defineConfig({
ssr: true,
// opcion experimental: activa el modelo de islas
experimental: { islands: true },
});
El caso ideal son blogs, documentación, tiendas o páginas de marketing: mucho texto estático con unos pocos widgets vivos —un buscador, un carrito, un carrusel—. Frente a un SSR clásico, que hidrata la página entera aunque el noventa por ciento sea inerte, las islas hidratan solo lo que se mueve. En una página donde casi todo es contenido de lectura, esa diferencia se traduce en enviar una fracción del JavaScript y en un dispositivo modesto que responde antes, porque no gasta ciclos hidratando lo que nunca reaccionará. Al ser una función experimental, su API y sus límites pueden cambiar, así que hoy es una opción a vigilar y prototipar más que a construir un producto crítico encima; pero apunta a la dirección en la que se mueve todo el frontend, la de enviar cada vez menos JavaScript.
El SSR clásico parte de que todo se hidrata y confía en que el grano fino de Solid abarate ese todo. Las islas invierten la premisa: parten de que nada se hidrata salvo lo que marcas explícitamente como interactivo. Ese cambio de defecto —de opt-out a opt-in de la interactividad— es lo que las hace tan frugales en JavaScript, y también lo que obliga a pensar tu página como un mar de contenido inerte con islas conscientes de sí mismas. Es un modelo mental distinto, no solo un ajuste, y esa es la razón de que todavía madure como experimento.
En términos del eje que abre esta lección, islands empuja el reparto hacia el servidor todo lo posible: renderiza allí la página entera y reserva el navegador para las chispas de interactividad. Es la apuesta más ambiciosa de las tres y también la menos asentada, así que hoy la eliges sabiendo que exploras terreno en movimiento y no que construyes sobre roca. Vigílala como se vigila el futuro: es probable que la dirección que marca —enviar cada vez menos JavaScript— acabe siendo la norma, aunque su forma concreta todavía cambie.
Qué eliges al crear la app
En la práctica, la primera bifurcación la tomas en el asistente de creación, cuando create-solid pregunta si quieres Server Side Rendering. Responder que sí deja ssr: true y te pone en el camino recomendado; responder que no fija ssr: false y arrancas en SPA. Islands no aparece ahí: se activa después en app.config.ts como la opción experimental que es. Y nada de esto es irreversible —cambiar de modo es, casi siempre, editar una clave de configuración—, pero conviene elegir con criterio desde el principio, porque el modo condiciona cómo escribes: en SSR piensas en qué corre en el servidor y qué en el cliente, en SPA vives solo en el navegador.
El consejo por defecto es nítido: empieza en SSR salvo que tengas una razón concreta para no hacerlo. Es el modo que mejor se porta con buscadores, con la percepción de velocidad y con contenido que cambia por usuario, y es donde las primitivas de datos rinden al máximo. Reserva la SPA para cuando el SEO sea irrelevante y el despliegue estático sea una ventaja real —una herramienta interna, un panel tras un login—, y trata islands como un experimento a seguir de cerca. Elegir SSR primero no te encierra: siempre puedes bajar a SPA con una clave, pero rara vez necesitarás el camino inverso.
Hay, por último, una consecuencia del modo que trasciende la configuración: moldea cómo programas cada componente. En SSR tu lógica corre en dos entornos, así que has de distinguir qué puede ejecutarse en el servidor y qué exige el navegador —de ahí que isServer y las funciones de servidor sean utensilios cotidianos—. En SPA esa dualidad se desvanece: todo es cliente, y con ella se van tanto la complejidad como las capacidades del servidor. El modo no es una casilla que marcas y olvidas; es el marco mental desde el que escribes.
Conviene no confundir el modo SPA con volver a Solid puro. Aunque desactives el render de servidor, conservas el enrutado por ficheros, el build de Vinxi, la configuración de app.config.ts y —si mantienes un servidor bajo el preset— hasta las funciones de servidor, que siguen ejecutándose en el backend aunque tu interfaz se pinte entera en el navegador. La SPA de SolidStart es una decisión sobre dónde se renderiza la interfaz, no una renuncia al meta-framework. Por eso migrar de SPA a SSR más adelante es casi siempre cambiar ssr a true y revisar el código que asumía estar solo en el navegador.
La lección que unifica los tres modos es que no son tres características distintas de SolidStart sino tres puntos de un mismo eje: cuánta de tu aplicación se ejecuta en el servidor y cuánta en el navegador. En un extremo del eje, el SSR clásico ejecuta tu árbol dos veces —una en el servidor para producir HTML y otra en el cliente para hidratarlo— y con ello compra el mejor primer pintado y el mejor SEO al precio de enviar y volver a ejecutar toda la lógica en ambos lados. En el otro extremo, la SPA ejecuta tu árbol una sola vez, en el navegador, y con ello compra simplicidad de despliegue y de modelo mental al precio de una pantalla en blanco inicial y una indexación pobre. Las islas son el intento de habitar el punto medio, ejecutando en el servidor todo y en el cliente solo lo imprescindible, y por eso representan la frontera de investigación del área. Que Solid pueda ofrecer este espectro moviendo apenas una clave de configuración no es casualidad ni comodidad accidental: es consecuencia directa de que su renderizado es isomorfo desde el diseño, de que el mismo componente que corre una vez sabe describir su salida tanto como cadena de HTML en un servidor cuanto como DOM reactivo en un navegador. Esa propiedad, que en otros marcos se paga con dos modelos mentales o dos APIs, en Solid es el mismo árbol interpretado por dos entornos, y el modo del proyecto es simplemente la instrucción de cuántas veces y en qué lugar quieres que ese árbol se interprete. Cuando eliges un modo, por tanto, no estás activando una función: estás decidiendo la geografía de tu render, el reparto de trabajo entre dos máquinas, y con él las propiedades que tu producto tendrá para el usuario y para el buscador. Elegir con criterio es preguntarte qué necesita tu producto —contenido indexable y rápido, o interactividad tras un muro de login, o texto casi estático con chispas de vida— y dejar que esa respuesta, no la costumbre, coloque tu render donde debe estar.
- Crea el mismo proyecto dos veces, una con SSR y otra sin él, y compara qué HTML llega en la primera respuesta viendo el código fuente de la página.
- En el modo SPA, localiza el shell vacío que sirve el servidor y explica por qué hay un instante en blanco hasta que carga el JavaScript.
- Razona, para tres productos —un blog público, un panel interno tras login, una tienda con mucho texto y un carrito— qué modo elegirías y por qué.
- Activa
experimental.islandsen un proyecto de prueba y argumenta qué partes serían islas y cuáles quedarían como HTML sin hidratar. - Defiende por qué modo de render y preset de despliegue son ejes independientes, dando un ejemplo de cada una de sus cuatro combinaciones plausibles.