Español

Aprende a crear backends sin servidor directamente en tu aplicación Next.js con las Rutas API. Esta guía cubre desde la configuración básica hasta técnicas avanzadas.

Rutas API de Next.js: Construyendo tu Backend con Facilidad

Next.js ha revolucionado el desarrollo front-end con sus potentes características y su estructura intuitiva. ¿Pero sabías que también puede simplificar significativamente el desarrollo de backend? Las Rutas API de Next.js te permiten crear endpoints de API sin servidor directamente dentro de tu aplicación Next.js, eliminando en muchos casos la necesidad de un servidor backend separado. Esta guía completa te guiará a través del proceso de construcción de un backend robusto y escalable utilizando las Rutas API de Next.js.

¿Qué son las Rutas API de Next.js?

Las Rutas API son funciones sin servidor que creas dentro del directorio /pages/api en tu proyecto de Next.js. Estas funciones manejan las solicitudes HTTP entrantes y devuelven respuestas, al igual que una API de backend tradicional. La diferencia clave es que se despliegan como funciones sin servidor, lo que significa que no necesitas gestionar servidores o infraestructura.

Piénsalas como funciones de backend ligeras y bajo demanda que se integran perfectamente con tu front-end de Next.js.

Beneficios de Usar las Rutas API de Next.js

Primeros Pasos con las Rutas API de Next.js

Vamos a crear una ruta API simple que devuelva una respuesta JSON. Primero, asegúrate de tener un proyecto de Next.js configurado. Si no es así, crea uno usando:

npx create-next-app my-app
cd my-app

Ahora, crea un archivo llamado hello.js dentro del directorio /pages/api:

// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ name: 'John Doe' })
}

Este código define una ruta API simple que responde con un objeto JSON que contiene el nombre "John Doe". Para acceder a esta ruta API, inicia tu servidor de desarrollo de Next.js:

npm run dev

Luego, abre tu navegador y navega a http://localhost:3000/api/hello. Deberías ver la siguiente respuesta JSON:

{"name": "John Doe"}

Entendiendo el Manejador de la Ruta API

La función handler en tu ruta API recibe dos argumentos:

Puedes usar estos objetos para manejar diferentes tipos de solicitudes, leer datos del cuerpo de la solicitud, establecer cabeceras de respuesta y enviar diferentes tipos de respuestas.

Manejando Diferentes Métodos HTTP

Puedes usar la propiedad req.method para determinar el método HTTP de la solicitud entrante y manejar diferentes métodos en consecuencia. Por ejemplo:

// pages/api/method.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Manejar la solicitud GET
    res.status(200).json({ message: 'This is a GET request' })
  } else if (req.method === 'POST') {
    // Manejar la solicitud POST
    res.status(200).json({ message: 'This is a POST request' })
  } else {
    // Manejar otros métodos
    res.status(405).json({ message: 'Method Not Allowed' })
  }
}

En este ejemplo, la ruta API maneja tanto las solicitudes GET como las POST. Si el método de la solicitud es GET, responde con un objeto JSON que contiene el mensaje "This is a GET request". Si el método de la solicitud es POST, responde con un objeto JSON que contiene el mensaje "This is a POST request". Si el método de la solicitud es cualquier otro, responde con un error 405 Method Not Allowed.

Leyendo Datos del Cuerpo de la Solicitud

Para las solicitudes POST, PUT y PATCH, a menudo necesitas leer datos del cuerpo de la solicitud. Next.js proporciona soporte integrado para analizar cuerpos de solicitud en formato JSON y codificados como URL. Para analizar un cuerpo de solicitud JSON, puedes usar la propiedad req.body. Por ejemplo:

// pages/api/post.js
export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { name, email } = req.body

    // Procesar los datos
    console.log('Name:', name)
    console.log('Email:', email)

    res.status(200).json({ message: 'Data received successfully' })
  } else {
    res.status(405).json({ message: 'Method Not Allowed' })
  }
}

Para probar esta ruta API, puedes usar una herramienta como Postman o curl para enviar una solicitud POST con un cuerpo JSON:

curl -X POST -H "Content-Type: application/json" -d '{"name": "Jane Doe", "email": "jane.doe@example.com"}' http://localhost:3000/api/post

Estableciendo Cabeceras de Respuesta

Puedes usar el método res.setHeader() para establecer las cabeceras de respuesta. Esto es útil para establecer el tipo de contenido, el control de caché y otra información importante. Por ejemplo:

// pages/api/headers.js
export default function handler(req, res) {
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('Cache-Control', 's-maxage=3600')
  res.status(200).json({ message: 'Hello, world!' })
}

En este ejemplo, la ruta API establece la cabecera Content-Type a application/json, indicando que la respuesta es un objeto JSON. También establece la cabecera Cache-Control a s-maxage=3600, lo que le dice al navegador y al CDN que almacenen en caché la respuesta por hasta 1 hora.

Manejo de Errores

Es importante manejar los errores de manera elegante en tus rutas API. Puedes usar bloques try-catch para capturar excepciones y enviar respuestas de error apropiadas al cliente. Por ejemplo:

// pages/api/error.js
export default async function handler(req, res) {
  try {
    // Simular un error
    throw new Error('Something went wrong')
  } catch (error) {
    console.error(error)
    res.status(500).json({ message: 'Internal Server Error' })
  }
}

En este ejemplo, la ruta API simula un error lanzando un nuevo objeto Error. El bloque catch captura el error, lo registra en la consola y envía una respuesta 500 Internal Server Error al cliente. Considera usar un sistema de registro robusto como Sentry o Datadog para entornos de producción.

Conectando a una Base de Datos

Uno de los casos de uso más comunes para las rutas API es conectarse a una base de datos. Las Rutas API de Next.js se integran perfectamente con varias bases de datos, incluyendo:

Aquí hay un ejemplo de cómo conectarse a una base de datos MongoDB en una ruta API de Next.js:

// pages/api/mongodb.js
import { MongoClient } from 'mongodb'

const uri = process.env.MONGODB_URI
const options = {}

let client
let clientPromise

if (!process.env.MONGODB_URI) {
  throw new Error('Please add your Mongo URI to .env.local')
}

if (process.env.NODE_ENV === 'development') {
  // En modo de desarrollo, usa una variable global para que el valor
  // se conserve entre las recargas de módulos causadas por HMR (Hot Module Replacement).
  if (!global._mongoClientPromise) {
    client = new MongoClient(uri, options)
    global._mongoClientPromise = client.connect()
  }
  clientPromise = global._mongoClientPromise
} else {
  // En modo de producción, es mejor no usar una variable global.
  client = new MongoClient(uri, options)
  clientPromise = client.connect()
}

// Exporta una promesa MongoClient con alcance de módulo. Al hacer esto en un
// módulo separado, el cliente puede ser reutilizado de forma segura en múltiples
// funciones. Ver: https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/lib/mongodb.js
export default async function handler(req, res) {
  try {
    const client = await clientPromise
    const db = client.db(process.env.MONGODB_DB)
    const collection = db.collection('users')

    const users = await collection.find({}).toArray()

    res.status(200).json({ users })
  } catch (e) {
    console.error(e)
    res.status(500).json({ message: 'Failed to fetch users' })
  }
}

Antes de ejecutar este código, asegúrate de tener el paquete mongodb instalado:

npm install mongodb

También necesitas establecer las variables de entorno MONGODB_URI y MONGODB_DB. Estas variables deben definirse en tu archivo .env.local (o en la configuración de variables de entorno de tu proveedor de hosting para producción). La MONGODB_URI contiene la cadena de conexión a tu base de datos MongoDB, y MONGODB_DB especifica el nombre de la base de datos.

Autenticación y Autorización

Proteger tus rutas API es crucial para la seguridad. Las Rutas API de Next.js se pueden asegurar usando varias técnicas de autenticación y autorización, incluyendo:

Aquí hay un ejemplo de cómo proteger una ruta API usando autenticación JWT:

// pages/api/protected.js
import jwt from 'jsonwebtoken'

const secret = process.env.JWT_SECRET

export default function handler(req, res) {
  const token = req.headers.authorization?.split(' ')[1]

  if (!token) {
    return res.status(401).json({ message: 'Unauthorized' })
  }

  try {
    const decoded = jwt.verify(token, secret)
    // El objeto "decoded" contiene la información del usuario incrustada en el token
    // Por ejemplo: const userId = decoded.userId;

    // Continuar procesando la solicitud
    res.status(200).json({ message: 'Protected resource accessed successfully' })
  } catch (error) {
    return res.status(401).json({ message: 'Invalid token' })
  }
}

Antes de ejecutar este código, asegúrate de tener el paquete jsonwebtoken instalado:

npm install jsonwebtoken

También necesitas establecer la variable de entorno JWT_SECRET. Esta debe ser una clave secreta fuerte y generada aleatoriamente que se usa para firmar y verificar los JWT. Almacénala de forma segura y nunca la expongas en tu código del lado del cliente.

Middleware

Aunque Next.js no ofrece middleware tradicional para las rutas API de la misma manera que Express.js, puedes lograr una funcionalidad similar envolviendo tus manejadores de rutas API con funciones reutilizables. Esto te permite realizar tareas como:

Aquí hay un ejemplo de cómo crear un middleware de registro simple:

// utils/middleware.js
export function withLogging(handler) {
  return async function(req, res) {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`)
    return handler(req, res)
  }
}

Para usar este middleware, simplemente envuelve el manejador de tu ruta API con la función withLogging:

// pages/api/logged.js
import { withLogging } from '../../utils/middleware'

async function handler(req, res) {
  res.status(200).json({ message: 'This request was logged' })
}

export default withLogging(handler)

Mejores Prácticas para Construir Rutas API de Next.js

Técnicas Avanzadas

Tareas en Segundo Plano

Para tareas de larga duración que no deberían bloquear la respuesta de la API, considera usar tareas en segundo plano. Puedes usar bibliotecas como BullMQ o Bree para gestionar tus tareas en segundo plano y procesarlas de forma asíncrona.

WebSockets

Para aplicaciones en tiempo real, puedes usar WebSockets en tus rutas API de Next.js. Bibliotecas como Socket.IO y ws facilitan el establecimiento de conexiones persistentes entre el cliente y el servidor.

GraphQL

Si necesitas una forma más flexible y eficiente de obtener datos, considera usar GraphQL. Puedes usar bibliotecas como Apollo Server o Yoga para crear un endpoint de API GraphQL en tu aplicación Next.js.

Conclusión

Las Rutas API de Next.js proporcionan una forma potente y conveniente de construir backends sin servidor directamente dentro de tu aplicación Next.js. Al aprovechar los beneficios de la arquitectura sin servidor, puedes simplificar el desarrollo, mejorar el rendimiento y reducir los costos. Ya sea que estés construyendo un simple formulario de contacto o una compleja plataforma de comercio electrónico, las Rutas API de Next.js pueden ayudarte a crear un backend robusto y escalable con facilidad. Con una sólida comprensión de los fundamentos y la aplicación de las mejores prácticas, puedes aprovechar esta poderosa herramienta para crear aplicaciones eficientes, seguras y accesibles a nivel mundial.