Volver a Next.js Básico
Metadata, Imágenes y Despliegue
Metadata Estática y Dinámica
// app/page.tsx — metadata estática
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Inicio | Mi App',
description: 'Bienvenido a mi aplicación Next.js',
openGraph: {
title: 'Mi App',
description: 'La mejor app',
images: [{ url: '/og-imagen.png' }],
},
};
export default function PaginaInicio() {
return <h1>¡Bienvenido!</h1>;
}
// app/blog/[slug]/page.tsx — metadata dinámica
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params;
const post = await obtenerPost(slug);
return {
title: `${post.titulo} | Blog`,
description: post.extracto,
openGraph: {
images: [post.imagenPortada],
},
};
}
Imágenes Optimizadas
import Image from 'next/image';
// Optimizada: convierte a WebP, redimensiona, carga diferida
function Avatar({ src, nombre }: { src: string; nombre: string }) {
return (
<Image
src={src}
alt={nombre}
width={64}
height={64}
className="rounded-full"
/>
);
}
// Llenar contenedor padre
function BannerHero() {
return (
<div className="relative h-96">
<Image
src="/hero.jpg"
alt="Hero"
fill
className="object-cover"
priority // Precarga — usar para imágenes visibles sin scroll
/>
</div>
);
}
Variables de Entorno
# .env.local (nunca subir a git)
DATABASE_URL="postgresql://user:pass@localhost:5432/midb"
NEXT_PUBLIC_API_URL="https://api.example.com" # Expuesta al navegador
// Solo en servidor (sin prefijo NEXT_PUBLIC_)
const db = new PrismaClient({
datasources: { db: { url: process.env.DATABASE_URL } },
});
// Disponible en el navegador
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Despliegue
Vercel (Recomendado)
npm install -g vercel
vercel # desplegar en preview
vercel --prod # desplegar en producción
O conecta tu repo de GitHub a Vercel y cada push despliega automáticamente.
Docker
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY /app/.next/standalone ./
COPY /app/.next/static ./.next/static
COPY /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
// next.config.ts
const nextConfig = {
output: 'standalone', // Requerido para Docker
};
export default nextConfig;
next.config.ts Esencial
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// Permitir imágenes de dominios externos
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'cdn.example.com' },
],
},
// Redirigir URLs antiguas
async redirects() {
return [
{ source: '/ruta-vieja', destination: '/ruta-nueva', permanent: true },
];
},
};
export default nextConfig;