14 puntos por xguru 2025-02-24 | 3 comentarios | Compartir por WhatsApp
  • La dirección futura de Next.js resulta interesante
  • Hubo algunos problemas con Server Actions, pero se ve potencial de mejora con useOptimistic y useFormStatus de React 19
    • El enfoque de useFetcher de Remix también ofrece una buena DX
  • El PPR (Partial Pre-rendering) de Next.js y el nuevo sistema de caché granular destacan especialmente
  • En general, deja una impresión muy positiva

The Big Picture

  • El nuevo sistema de caché se puede activar de forma experimental en next.config.js
  • Se pueden definir perfiles de caché para configurar distintos tiempos de expiración y ciclos de revalidación
// next.config.js
const config = {
  experimental: {
    // Activa el nuevo sistema de caché. Ahora puedes usar `use cache` en el código
    dynamicIO: true,
    // Opcional: configuración de perfiles de caché
    cacheLife: {
      blog: {
        stale: 3600, // Mantener caché del cliente: 1 hora
        revalidate: 900, // Refrescar en el servidor: 15 minutos
        expire: 86400, // Vida máxima: 1 día
      },
    },
  },
};

Uso básico de use cache

  • Se puede habilitar caché a nivel de archivo, componente o función mediante la declaración "use cache"
  • En los ejemplos de código, basta con agregar use cache para aplicar caché fácilmente
  • Con cacheTag, revalidateTag, etc., se puede invalidar la caché en el momento deseado
// 1. Caché a nivel de archivo
"use cache";
export default function Page() {
  return Cached Page

;
}

// 2. Caché a nivel de componente
export async function PriceDisplay() {
  "use cache";
  const price = await fetchPrice();
  return ${price}

;
}

// 3. Caché a nivel de función
export async function getData() {
  "use cache";
  return await db.query();
}

Caché basada en etiquetas

import { unstable_cacheTag as cacheTag, revalidateTag } from 'next/cache';

// Guardar en caché un grupo específico de datos
export async function ProductList() {
  'use cache';
  cacheTag('products');
  const products = await fetchProducts();
  return {products}

;
}

// Invalidar la caché cuando cambien los datos
export async function addProduct() {
  'use server';
  await db.products.add(...);
  revalidateTag('products');
}

Perfil de Cache personalizado

  • Con unstable_cacheLife se pueden cargar los perfiles de caché definidos en next.config.js
  • La política de caché se aplica usando el nombre del perfil declarado dentro del código (por ejemplo, "blog")
import { unstable_cacheLife as cacheLife } from "next/cache";

export async function BlogPosts() {
  "use cache";
  cacheLife("blog"); // Usa el perfil de caché predefinido para blog
  return await fetchPosts();
}

Puntos importantes que pueden pasar desapercibidos

Generación automática de claves de caché

  • Los props y los arguments del componente se incluyen automáticamente en la clave de caché
  • Los valores no serializables (como funciones) se manejan como "referencias no modificables"
export async function UserCard({ id, onDelete }) {
  "use cache";
  // id se incluye en la clave de caché
  // onDelete se pasa, pero no afecta el almacenamiento en caché
  const user = await fetchUser(id);
  return {user.name}

;
}

Mezcla de contenido dinámico y contenido en caché

  • Se puede combinar contenido en caché con contenido dinámico pasándolo como hijos dentro del contenido cacheado
  • Se puede especificar un arreglo de cacheTag para aplicar e invalidar varias etiquetas al mismo tiempo
export async function CachedWrapper({ children }) {
  "use cache";
  const header = await fetchHeader();
  return (

      {header}

      {children} {/* El contenido dinámico se mantiene tal cual */}

  );
}
export async function ProductPage({ id }) {
  "use cache";
  cacheTag(["products", `product-${id}`, "featured"]);
  // Se puede invalidar usando cualquiera de estas etiquetas
}

Jerarquía de caché

  • Si se declara "use cache" en el nivel superior, toda esa área queda en caché
  • Algunas partes específicas (por ejemplo, secciones dinámicas con Suspense) pueden excluirse del área cacheada
"use cache";
export default async function Page() {
  return (

           {/* Contenido dinámico */}

  );
}

Seguridad de tipos

  • Las cadenas como claves de caché y perfiles de caché se pueden manejar como constantes para reducir el uso de magic strings
  • Al usar un enfoque que genere etiquetas, como en el patrón de React Query, resulta más conveniente
// Gestionar claves de perfiles de caché como constantes
export const CACHE_LIFE_KEYS = {
  blog: "blog",
} as const;

const config = {
  experimental: {
    cacheLife: {
      [CACHE_LIFE_KEYS.blog]: {
        stale: 3600,
        revalidate: 900,
        expire: 86400,
      },
    },
  },
};

Cómo gestionar eficientemente las etiquetas de caché

  • Aplicar el patrón de fábrica de etiquetas al estilo React Query
export const CACHE_TAGS = {
  blog: {
    all: ["blog"] as const,
    list: () => [...CACHE_TAGS.blog.all, "list"] as const,
    post: (id: string) => [...CACHE_TAGS.blog.all, "post", id] as const,
    comments: (postId: string) =>
      [...CACHE_TAGS.blog.all, "post", postId, "comments"] as const,
  },
} as const;

// Configurar etiquetas de caché
function tagCache(tags: string[]) {
  cacheTag(...tags);
}

// Ejemplo de uso
export async function BlogList() {
  "use cache";
  tagCache(CACHE_TAGS.blog.list());
}

3 comentarios

 
schang124 2025-03-03

Parece que lo mejor es usar frameworks como Next.js o Remix solo cuando el SEO es importante y se necesita SSR.

Especialmente en servicios donde el SEO no es importante, como productos B2B o back office, creo que hay que pensar con cuidado antes de adoptar Next.js. Esto se debe a que las interfaces o la complejidad que impone Next.js pueden reducir la productividad de desarrollo.

Personalmente, creo que cuando el SEO no es necesario, Vite + React es mucho mejor en términos de productividad de desarrollo y flexibilidad.

 
[Este comentario fue ocultado.]
 
9vvin 2025-02-25

Next.js se volvió bastante usable desde la versión 13, pero últimamente de verdad me encanta muchísimo. Creo que se va a convertir en el estándar de facto del stack tecnológico para desarrollo web full-stack.