Mejores Prácticas de Next.js
Principios para el desarrollo con el App Router de Next.js.
1. Componentes de Servidor vs Cliente
Árbol de Decisión
¿Necesita...?
│
├── useState, useEffect, manejadores de eventos
│ └── Componente Cliente ('use client')
│
├── Obtención directa de datos, sin interactividad
│ └── Componente de Servidor (por defecto)
│
└── ¿Ambos?
└── Dividir: Servidor padre + Cliente hijo
Por Defecto
| Tipo | Uso |
|---|
| Servidor | Obtención de datos, layout, contenido estático |
| Cliente | Formularios, botones, UI interactiva |
2. Patrones de Obtención de Datos
Estrategia de Obtención
| Patrón | Uso |
|---|
| Por defecto | Estático (almacenado en caché al compilar) |
| Revalidate | ISR (actualización basada en tiempo) |
| No-store | Dinámico (cada petición) |
Flujo de Datos
| Fuente | Patrón |
|---|
| Base de datos | Obtención en Componente de Servidor |
| API | fetch con caché |
| Entrada del usuario | Estado del cliente + acción de servidor |
3. Principios de Enrutamiento
Convenciones de Archivos
| Archivo | Propósito |
|---|
page.tsx | UI de la ruta |
layout.tsx | Layout compartido |
loading.tsx | Estado de carga |
error.tsx | Límite de error |
not-found.tsx | Página 404 |
Organización de Rutas
| Patrón | Uso |
|---|
Grupos de rutas (nombre) | Organizar sin URL |
Rutas paralelas @slot | Múltiples páginas al mismo nivel |
Interceptación (.) | Superposiciones modales |
4. Rutas de API
Manejadores de Ruta
| Método | Uso |
|---|
| GET | Leer datos |
| POST | Crear datos |
| PUT/PATCH | Actualizar datos |
| DELETE | Eliminar datos |
Mejores Prácticas
- Validar la entrada con Zod
- Devolver códigos de estado apropiados
- Manejar errores con elegancia
- Usar el runtime Edge cuando sea posible
5. Principios de Rendimiento
Optimización de Imágenes
- Usar el componente next/image
- Establecer prioridad para elementos visibles inicialmente
- Proporcionar un placeholder de desenfoque
- Usar tamaños responsivos
Optimización del Bundle
- Importaciones dinámicas para componentes pesados
- División de código por ruta (automática)
- Analizar con el analizador de bundles
6. Metadatos
Estáticos vs Dinámicos
| Tipo | Uso |
|---|
| Exportación estática | Metadatos fijos |
| generateMetadata | Dinámico por ruta |
Etiquetas Esenciales
- title (50-60 caracteres)
- description (150-160 caracteres)
- Imágenes Open Graph
- URL canónica
7. Estrategia de Caché
Capas de Caché
| Capa | Control |
|---|
| Solicitud | Opciones de fetch |
| Datos | revalidate/tags |
| Ruta completa | Configuración de ruta |
Revalidación
| Método | Uso |
|---|
| Basado en tiempo | revalidate: 60 |
| Bajo demanda | revalidatePath/Tag |
| Sin caché | no-store |
8. Acciones de Servidor
Casos de Uso
- Envíos de formularios
- Mutaciones de datos
- Disparadores de revalidación
Mejores Prácticas
- Marcar con 'use server'
- Validar todas las entradas
- Devolver respuestas tipadas
- Manejar errores
9. Antipatrones
| ❌ No hacer | ✅ Hacer |
|---|
| 'use client' en todas partes | Servidor por defecto |
| Obtención en componentes cliente | Obtención en servidor |
| Omitir estados de carga | Usar loading.tsx |
| Ignorar límites de error | Usar error.tsx |
| Bundles de cliente grandes | Importaciones dinámicas |
10. Estructura del Proyecto
app/
├── (marketing)/ # Grupo de rutas
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx # Layout del dashboard
│ └── page.tsx
├── api/
│ └── [resource]/
│ └── route.ts
└── components/
└── ui/
Recuerda: Los Componentes de Servidor son la opción por defecto por una razón. Empieza ahí, añade cliente solo cuando sea necesario.