Ir al contenido principal

Devlog · Fase 0 · 2/7

La stack de aubia.dev: Octane, FrankenPHP e Inertia SSR

Una latencia dividida entre cinco y diez gracias a Octane y FrankenPHP, un SSR de Inertia que sirve el HTML completo desde el primer byte: la stack de aubia.dev, bloque a bloque.

Publicado el 20 julio 20265 min de lectura
  • laravel
  • octane
  • frankenphp
  • inertia
  • vite

aubia.dev sirve su HTML completo desde el primer byte y responde con una latencia dividida entre cinco y diez frente a un PHP-FPM clásico. Para una landing, esto no es un lujo: un sitio web tiene un único cometido innegociable, que es ser visto. Por los visitantes, pero antes por los buscadores y por los motores de respuesta de IA. Le abro la stack, con el razonamiento detrás de cada bloque.

El renderizado en servidor como invariante SEO

Una aplicación React clásica devuelve una cáscara HTML vacía y luego puebla la página en JavaScript. Un navegador se las apaña con eso. Un crawler o un motor de respuesta, en cambio, debe encontrar el contenido directamente en el HTML de la primera respuesta.

Por esa razón me prohibí el renderizado solo en cliente en este sitio web. El SSR manda sobre todo lo demás. Inertia v3 renderiza las páginas React del lado servidor, y el HTML completo sale desde el primer byte: título, subtítulo, secciones, metadatos SEO, todo está presente antes de que se ejecute una sola línea de JavaScript del lado cliente. La hidratación toma luego el relevo para la interactividad. Esta regla, que el contenido debe existir en el HTML inicial, dicta todo el resto del código de frontend, hasta la prohibición de mostrar contenido mediante un useEffect.

Octane y FrankenPHP: el servidor que no reinicia

Instalé Octane desde el primer día del repositorio, a finales de abril de 2026, incluso antes de escribir la más mínima línea de contenido. Es una elección de base, no una optimización añadida después. En PHP tradicional, cada petición rearranca la aplicación: carga del framework, resolución del contenedor y luego respuesta. Laravel Octane cambia ese modelo. La aplicación arranca una vez, y luego workers persistentes sirven miles de peticiones en el mismo proceso.

Quedaba elegir el driver. Miré RoadRunner y Swoole, las otras dos opciones de Octane, antes de decantarme por FrankenPHP: integra el servidor Caddy de forma nativa, con HTTP/3, certificados automáticos y streaming sin ninguna capa adicional que operar, y su hoja de ruta está activa en el ecosistema Laravel.

// config/octane.php
'server' => env('OCTANE_SERVER', 'roadrunner'),
# .env : le driver actif sur aubia.dev
OCTANE_SERVER=frankenphp

Sobre esta base, el bootstrap de Laravel permanece en memoria y la latencia por petición cae en un factor de cinco a diez frente al cold start de PHP-FPM. Un tiempo de respuesta de servidor bajo y estable cuenta para la puntuación de rendimiento, y por tanto para el posicionamiento. Pero este modelo impone una disciplina que abordo más abajo.

Comparación animada: php-fpm rearranca el framework en cada petición y luego muere, mientras que Octane arranca una vez y sirve las peticiones sucesivas en un worker persistente.

Inertia v3: React sin API separada

El punto que hace agradable esta stack es Inertia. Tiende el puente entre Laravel y React sin que yo tenga que construir y versionar una API REST separada. Los controllers devuelven páginas React con sus props, igual que devolverían vistas Blade. El SSR se activa en la configuración, sin servidor Node aparte que mantener en desarrollo.

// config/inertia.php
'ssr' => [
    'enabled' => true,
    'url' => 'http://127.0.0.1:13714',
],

En concreto, Inertia::render() reemplaza las vistas, las rutas siguen definidas del lado de Laravel, y React solo se ocupa del renderizado. Una única fuente de verdad para el enrutamiento, ninguna duplicación de lógica entre un back y un front que se ignoran.

Vite 8, Rolldown y React 19

Del lado del build, aubia.dev usa Vite 8 con Rolldown, el bundler escrito en Rust integrado de forma nativa. React 19 se compila con el React Compiler, que memoiza automáticamente los componentes sin anotaciones manuales. La división del bundle se pilota de forma explícita para aislar las grandes dependencias en sus propios chunks:

// vite.config.ts
codeSplitting: {
    minSize: 20_000,
    groups: [
        { name: 'react', test: /node_modules\/(react|react-dom|scheduler)\//, priority: 50 },
        { name: 'motion', test: /node_modules\/(motion|motion-dom)\//, priority: 40 },
        { name: 'fontawesome', test: /node_modules\/@fortawesome\//, priority: 30 },
    ],
},

Separar React, las animaciones y los iconos permite al navegador cachear lo que cambia poco y recargar solo lo que cambia. El build de producción genera además un bundle SSR dedicado mediante vite build --ssr.

La restricción stateless

Un servidor que nunca reinicia lo guarda todo en memoria entre las peticiones. Es justo lo que lo hace rápido, y es también su trampa. Bajo Octane, almacenar un estado propio de una petición en un singleton o una propiedad estática lo filtraría hacia la petición siguiente, servida por el mismo worker. Por eso todo el código del sitio web respeta esta regla: ningún estado de petición se retiene fuera de su alcance.

El recuento de la lista de espera, por ejemplo, se carga de forma diferida para no bloquear el renderizado en servidor con una llamada de red, y su resultado llega en una segunda petición del lado cliente:

'waitlist' => [
    'count' => Inertia::defer(fn(): ?int => app(FetchWaitlistCountQuery::class)->run()),
],

Así el SSR sigue siendo instantáneo, y el dato no determinista nunca entra en el primer render. Este rigor stateless irriga cada módulo del repositorio.

Lo que la velocidad aún no dice

Octane, FrankenPHP e Inertia dan un sitio web rápido e indexable. Esta contención va aún más lejos: el siguiente paso retira la propia base de datos, y con ella todo almacenamiento local de datos personales.

Para recibir aviso cuando se abra la beta 0.1, únase a la lista de espera.

Esta obra se cuenta aquí, artículo a artículo. Súbase a bordo: sus comentarios dibujarán lo que viene.

Únase a la lista de espera