😵💫 Server Components en Next.js 15: Lo que entendí mal (y bien)
Publicado en Mayo 27, 2025
Este no es un tutorial, sino un devlog de mi travesía trabajando con los server components de Next.js, y la importancia de no confiar ciegamente en la IA y leer documentación oficial ☝🏻
Cuando me propuse construir mi blog personal con Next.js 15, estaba emocionado de aprovechar los famosos ✨ Server Components ✨. Nunca les había dado verdaderamente una oportunidad, y “Es lo de hoy”, pensé. Pero lo que no sabía era que me iba a meter en una bola de bugs, errores de build, sesiones que desaparecen y documentación... confusa?
Este post no es un tutorial, es más bien una historia de cómo no volverte loco cuando las cosas no salen como esperas usando Server Components y cómo (para sorpresa de nadie) las IA son muy complacientes si no las encaminas a la verdadera solución. Spoiler: aprendí más de lo que pensaba.
El primer problema: el fetch que nunca llegó
Todo empezó cuando mi homepage donde quería mostrar las últimas cinco entradas de mi blog simplemente... no mostraba nada. Para darte contexto, por cuestiones de simplicidad hice uso de las API routes de Next.js con el App router para manejar el "backend". El homepage es un server component que se genera estáticamente al momento que hace la build, hace un fetch a la API interna para obtener los últimos 5 posts y renderizarlos en la página, pero, oh sorpresa: al momento de hacer deploy en Vercel, los logs de la build mostraban un error:
Error: Internal server error
at a (.next/server/app/page.js:1:5127)
at async p (.next/server/app/page.js:1:3031)
Esto no interrumpía la ejecución, pero era un poco alarmante que lo mostrara, al momento de mirar la página desplegada, la lista estaba totalmente vacía... En mi mente sólo fue:

Por alguna razón pretendía que todo saliera bien al ser un proyecto "sencillo", y después de unas cuantas preguntas fallidas a ChatGPT, luego a Grok porque ✨ Plan gratuito ✨, y un coffee break ☕️ recordé de tengo una mente propia y que en la prehistoria usábamos Google y Stackoverflow para resolver nuestros problemas. Tuve un pequeño momento de eureka:
Cómo pretendo que una página estática obtenga los posts de una API la cual aún no está corriendo?
Y me hizo mucho sentido, en mi ambiente local, el servidor de node siempre está corriendo, por lo que tiene acceso a la las rutas de la API todo el tiempo, ahora si que aplica la de "Pero en mi máquina sí funciona", caso contrario de cuando hago deploy y se ejecuta el comando de npm run build
, no hay ningún servidor de node corriendo, por lo que no tiene de dónde agarrar la información.
Solución: tuve que hacer la consulta directamente a la base de datos desde el Server Component. Sí, se siente como que estoy rompiendo una abstracción, pero al menos funcionó.
La confusión con las sesiones
En otra vista, necesitaba obtener un post individual. En este caso, sí funcionaba el fetch a mi API, era también un server component, pero la diferencia está en que las rutas son dinámicas, ya que el fetch sucede cuando alguien visita el post en específico, la consulta se hace en el servidor y al final te regresa toda la página con la info completa del post. Hasta ahí, todo bien.
El problema vino cuando desde esa misma API necesitaba acceder a la sesión del usuario para hacer unas validaciones en base a esa información. Después de probar diferentes escenarios me di cuenta que la sesión dentro de las API routes siempre venía como null
.
Y va de nuevo... intentos fallidos con una IA esperando a que me resuelva la vida, cosa que se pudo haber solucionado si tal vez me pusiera a leer la documentación oficial de las tecnologías que estoy usando 😅
Después de razonarlo un poco, decidí seguir intentando con Grok, tratando de encaminarlo hacia la solución, les comparto el prompt (no juzguen mi precario inglés, podría preguntarle todo en español pero me da satisfacción hacerlo así, y como sé que esta cosa es más inteligente que yo, no me molesto en corregir mis errores gramaticales 🤣):
it didn't work, still coming as null, but doesn't this have to do that I am using an internal API route to fetch a post, but this post is being fetched in a server component. I just tried to get the session data in the fetch itself and not inside my API routes and it worked
Ya sé lo que estarás pensando, este contexto se lo pude haber dicho desde el principio, pero mi experiencia con estas cosas es que si le sueltas demasiada información de una sola vez, ignora la mitad de lo que dices y te responde lo que le da la gana... en fin.
La solución: Al hacer fetch desde un Server Component, no se mandan las cookies 🍪 del navegador de forma automática. Y sin cookies, no hay sesión, por lo que hay que mandarle las cookies manualmente, y casualmente Next.js tiene las herramientas necesarias para hacerlo.
Esto depende de la técnica de autenticación que se esté usando en una aplicación, en mi caso uso JWT
(JSON Web Token), que en conjunto con NextAuth.js utilizan cookies para acceder a la información de la sesión del usuario.
import { cookies } from "next/headers";
const cookieStore = cookies();
const cookieString = cookieStore
.getAll()
.map((cookie) => `${cookie.name}=${cookie.value}`)
.join("; ");
// Fetch from internal API route, passing cookies
const response = await fetch(`http://localhost:3000/api/post/${params.id}`, {
headers: {
Cookie: cookieString, // Forward session cookies
},
});
Documentación - 1 | IA - 0
Ya que al parecer me estoy convirtiendo en un pseudo Vibe Coder, quisiera resaltar las veces que la IA no te ofrece la mejor calidad en sus soluciones, y recordarte que siempre hay que cuestionar todo.
El código anterior, es un extracto de la respuesta de Grok, puedes notar que hizo un .map
seguido de un .join
para construir una sola cadena de texto que contenga todas las cookies. Si tan sólo siguieras las prácticas del siglo pasado y te diriges a la documentación oficial, te darás cuenta de que la función de cookies()
ya tiene un método llamado toString()
que justo te devuelve lo mismo que la IA acaba de hacer... mucho ojo 👁️
¿Entonces, qué aprendí?
Server Components están muy cool, pero tienen muchas gotchas. Si vas a usarlos, entiende bien dónde y cómo corre tu código.
Hacer fetch a tus propias API routes desde un Server Component vs. Hacer la consulta directamente a la base de datos. Como vimos, dependiendo de los factores y el caso de uso, conviene mejor una que otra.
Las cookies no se mandan solitas en los fetch del servidor. Si necesitas sesión, mándalas tú manualmente.
No dependas ciegamente de una IA para resolver tus problemas. A veces, la vieja confiable (leer docs) te salva horas de frustración.
Cosas que puedo mejorar
Definitivamente me hizo mucho ruido el tener que hacer la consulta directamente a la base de datos en un server component. Yo sé que tú que me estás leyendo también tienes esa ✨ punzada ✨ de cuando algo no te convence, algo dentro de ti te dice "Esto se ve mal y seguramente hay una mejor forma de hacerlo", pues en base a mi experiencia te puedo decir que siempre hay que confiar en la punzada.
Siempre que decido ignorar a la punzada, más tarde me llegan los code reviews, o comentarios de mi manager de EXACTAMENTE lo que yo pensé que estaba mal y me mandan a corregirlo, estoy trabajando en ello y por supuesto que este es un buen momento para ponerlo en práctica.
Estaba buscando mis bookmarks de twitter porque estaba seguro que podía incluir referencias en este post, y me encontré con este tweet de @asidorenko que explica exactamente lo de separar tus llamadas a la db, sabía que de algún lado había sacado esa idea. Recuerda siempre que cuando se trata del frontend, todo puede ser expuesto, así que mucho cuidado.
Reflexiones finales del tío Juan
Recuerdo cuando empezó este concepto de los server components, en la muy bonita y nada tóxica plataforma que es tuirer / x le estaba cayendo mucho hate al concepto, y que esto se estaba convirtiendo en el nuevo PHP, haciendo alusión a que era un retroceso en el desarrollo web. Por mi parte (y como en todo) no me subo al barco de las tendencias tan rápido, me he resistido a frameworks CSS como Tailwind, al uso diario de la inteligencia artificial y sustituo de motores de búsqueda, y a los server components (si, mis antiguos proyectos de Next.js era automáticamente ponerle use client
al principio de todo), pero al final me doy por vencido, los pruebo y me termina gustando.
Pero me estoy desviando del tema, mi punto es que el intentar cosas nuevas te abre a expandir tu conocimiento y enfrentar nuevos retos, es bonito darte el tiempo de razonar el por qué y para qué de lo que estás haciendo e incluso tú mismo ponerte esos retos, como seguir un patrón de diseño en específico o evitar usar librerías para absolutamente todo.
No pude encontrar la fuente original, pero alguna vez leí (tal vez en reddit o en algún tweet), que una duda muy recurrente era saber cuando usar use client
y cuando no. La respuesta fue que siempre que se pudiera, trabajar con server components, y que cuando se necesitara recurrir a acciones que requieran de use client
, como los hooks, useState
, useEffect
, en vez de convertir todo el archivo en un client component, sólo mover la parte interactiva en un componente por separado, así parezca muy absurdo a primera vista.
Me guardé el consejo por mucho tiempo, y ahora que me he dado la oportunidad de construir mi blog desde cero, me propuse seguir esta filosofía... no sólo te ayuda a tener una mejor composición de tus componentes (lo que es chistoso porque justo hay un patrón en React llamado Composition que te ayuda a entenderlo mejor este apporach) si no que, de haber seguido haciendo todo con use client
, jamás me hubiera topado con estas dificultades y no hubiera tenido un mejor entendimiento de los server components, ni de sus ventajas y desventajas, es por eso que las empresas valoran mucho la experiencia al momento de contratar, porque una cosa es tener todos los conceptos memorizados en tu cabeza, pero otra muy diferente son los retos a los que te has enfrentado y cómo los has solucionado, cosa que sólo se consigue trabajando en proyectos con un enfoque más realista, que van mas allá de una calculadora en js y un todo list hecho en react.
Escribiendo este post me di cuenta que tengo otro tweet de @asidorenko_ explicando lo de separar la parte interactiva en otro componente. Les juro que nadie me está pagando por promocionar sus tweets, de verdad síganlo si quieren ver mas cosas de Next.js.
Y de paso por favor estudien el Composition pattern, si llegaste hasta aquí ahora ya sabes que existe, que lo has estado implementando sin saberlo, y tener conciencia de eso, estudiarlo y aplicarlo te da más puntos en las entrevistas 😉
Al final, este fue más un diario de guerra que un tutorial, pero si te ahorré aunque sea un par de horas de debug con esto, ya valió la pena.
¿Tú también te has peleado con los Server Components? Cuéntamelo que no quiero sentirme solo 😅 también se aceptan sugerencias y correcciones, estoy lejos de ser perfecto, pero tampoco le tengo miedo a ser transparente y mostrarles mi razonamiento cuando me enfrento a estos problemas.