Servir una SPA y una API juntas¶
Estado verificado al 28 de marzo de 2026. Esto encaja muy bien con builds de frameworks como Vite/React, Vue, Svelte, Astro o cualquier bundle estático.
Uno de los setups más cómodos en FastFN es este:
- tu build SPA vive en
dist/opublic/ - tus handlers API viven en otra carpeta como
api/ - FastFN sirve ambas cosas en la misma app con casi nada de configuración
Eso te deja sacar una SPA simple y una API pequeña juntas sin meter otra capa de proxy desde el día uno. Es una de las formas más limpias de mostrar el combo SPA + API de FastFN.
Qué vamos a construir¶
/sirve el shell SPA desdedist/index.html/dashboardvuelve al mismo shell SPA/api/hellodevuelve JSON desde un handler normal de FastFN
1. Estructura del proyecto¶
my-app/
├── fn.config.json
├── dist/
│ ├── index.html
│ └── assets/
│ └── app.js
└── api/
└── hello/
└── handler.js
dist/ puede ser la salida de build de Vite, React, Vue, Svelte, Astro o cualquier otra SPA.
2. Configuración raíz¶
Crea un fn.config.json en la raíz:
{
"assets": {
"directory": "dist",
"not_found_handling": "single-page-application",
"run_worker_first": false
}
}
La idea principal es:
directory: "dist"monta tu build SPA en/single-page-applicationhace que deep links como/dashboardvuelvan adist/index.htmlrun_worker_first: falsemantiene todo simple cuando tu API vive bajo/api/*
3. Agrega una ruta API¶
Crea api/hello/handler.js:
exports.handler = async () => ({
status: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
ok: true,
message: "hola desde FastFN",
}),
});
Eso te da un handler normal en /api/hello.
Si despues este handler API necesita paquetes externos, prefiere agregar un package.json o requirements.txt explicito.
FastFN puede inferir dependencias en Python y Node, incluyendo backends opcionales como pipreqs, detective y require-analyzer, pero ese camino es mas lento y conviene usarlo como ayuda mientras arrancas.
4. Ejecuta la app¶
5. Prueba las tres URLs importantes¶
Shell SPA:
Deep link SPA:
Ruta API:
Respuesta esperada:
Por qué este setup es fuerte¶
- tu frontend sigue siendo una salida de build normal de framework
- tu API sigue siendo file-based y fácil de crecer
- el desarrollo local sigue siendo un solo comando
- la SPA y la API comparten la misma base URL
- no necesitas meter un reverse proxy custom para empezar
Static-first vs worker-first¶
Para el caso más simple de SPA + API, deja tu API bajo /api/* y mantén run_worker_first en false.
Si quieres que las rutas runtime ganen antes que los archivos estáticos, cambia a:
{
"assets": {
"directory": "dist",
"not_found_handling": "single-page-application",
"run_worker_first": true
}
}
Eso sirve cuando el build del framework genera una ruta que debería perder frente a un handler.
Ejemplos ejecutables¶
examples/functions/assets-spa-fallbackexamples/functions/assets-worker-firstexamples/functions/assets-static-first