Next.js 16 vs Remix
Next.js 16 (Turbopack por defecto, Partial Prerendering) frente a Remix (Shopify, estándares web) — comparación de meta-frameworks de React en 2026.
Capa de React renderizada previamente en el servidor, con cero JS por defecto
Forma clásica y madura de usar React, renderizada en el navegador
En superficies con mucho contenido y críticas para SEO, RSC aporta una ganancia medible: en el propio ejemplo de react.dev, una librería de 75K gzip nunca llega al cliente. En paneles internos muy interactivos (dashboard, admin), el enfoque client-first es más simple y presenta menos superficie de errores. La advertencia crítica es real: pasar un objeto completo como prop de Server a Client serializa todos sus campos en el flight payload; si trazas mal el límite, la ganancia se erosiona en silencio. Decide con mediciones, no con modas.
| Categoría | React Server Components | Client-side React (SPA) |
|---|---|---|
| Rendimiento | 8/10 | 6/10 |
| Facilidad de aprendizaje | 4/10 | 8/10 |
| Ecosistema | 7/10 | 9/10 |
| Comunidad | 7/10 | 9/10 |
| Mercado laboral | 7/10 | 8/10 |
| A prueba de futuro | 9/10 | 7/10 |
// Next.js App Router — Server Component (por defecto)
// app/posts/[slug]/page.tsx
import { db } from '@/lib/db';
import LikeButton from './like-button'; // Client Component (en archivo separado con 'use client')
interface PageProps {
params: Promise<{ slug: string }>;
}
export default async function PostPage({ params }: PageProps) {
const { slug } = await params;
// Await directo en el servidor — sin waterfall cliente-servidor,
// librerías pesadas como marked/sanitize-html nunca entran al bundle del cliente
const post = await db.post.findUnique({ where: { slug } });
if (!post) return <div>No encontrado</div>;
return (
<article>
<h1>{post.title}</h1>
{/* Solo los props serializables pasan al Client Component */}
<div dangerouslySetInnerHTML={{ __html: post.renderedHtml }} />
<LikeButton postId={post.id} initialCount={post.likeCount} />
</article>
);
}
// app/posts/[slug]/like-button.tsx
'use client';
import { useState, useTransition } from 'react';
export default function LikeButton({ postId, initialCount }: { postId: string; initialCount: number }) {
const [count, setCount] = useState(initialCount);
const [isPending, startTransition] = useTransition();
return (
<button
disabled={isPending}
onClick={() => startTransition(async () => {
setCount((c) => c + 1);
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
})}
>
Me gusta ({count})
</button>
);
}// Vite + React — SPA del lado del cliente
// src/pages/PostPage.tsx
import { useEffect, useState } from 'react';
import { useParams } from 'react-router';
interface Post {
id: string;
title: string;
renderedHtml: string;
likeCount: number;
}
export default function PostPage() {
const { slug } = useParams();
const [post, setPost] = useState<Post | null>(null);
const [isLiking, setIsLiking] = useState(false);
useEffect(() => {
// Toda la obtención de datos ocurre en el cliente — aquí empieza el riesgo de waterfall
let cancelled = false;
fetch(`/api/posts/${slug}`)
.then((res) => res.json())
.then((data) => { if (!cancelled) setPost(data); });
return () => { cancelled = true; };
}, [slug]);
if (!post) return <div>Cargando...</div>; // Esta pantalla nunca aparece sin que el JS se ejecute
async function handleLike() {
setIsLiking(true);
setPost((p) => (p ? { ...p, likeCount: p.likeCount + 1 } : p));
await fetch(`/api/posts/${post!.id}/like`, { method: 'POST' });
setIsLiking(false);
}
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.renderedHtml }} />
<button disabled={isLiking} onClick={handleLike}>
Me gusta ({post.likeCount})
</button>
</article>
);
}
// vite.config.ts — el code-splitting se delega a Rollup
export default {
build: {
rollupOptions: {
output: { manualChunks: { vendor: ['react', 'react-dom', 'react-router'] } },
},
},
};En superficies con mucho contenido y críticas para SEO, RSC aporta una ganancia medible: en el propio ejemplo de react.dev, una librería de 75K gzip nunca llega al cliente. En paneles internos muy interactivos (dashboard, admin), el enfoque client-first es más simple y presenta menos superficie de errores. La advertencia crítica es real: pasar un objeto completo como prop de Server a Client serializa todos sus campos en el flight payload; si trazas mal el límite, la ganancia se erosiona en silencio. Decide con mediciones, no con modas.
Solicita una consultoría gratuitaEn superficies con mucho contenido, críticas para SEO y donde importa la carga inicial (LCP/TTI) — blog, página de producto, página de comparación — RSC aporta una ganancia medible: obtención de datos en el servidor y menos JS en el cliente. Según los propios datos de Next.js 16.3, al pasar a streams nativos de Node.js en el renderizado del lado del servidor se pueden procesar un 22% más de solicitudes bajo carga. En paneles internos muy interactivos (dashboard, admin), el enfoque client-first suele ofrecer una experiencia de desarrollo más simple.