Português

Aprenda a usar as Rotas de API do Next.js para construir backends serverless diretamente na sua aplicação Next.js. Este guia cobre tudo, desde a configuração básica até técnicas avançadas para lidar com autenticação, persistência de dados e muito mais.

Rotas de API do Next.js: Construindo seu Backend com Facilidade

O Next.js revolucionou o desenvolvimento front-end com seus recursos poderosos e estrutura intuitiva. Mas você sabia que ele também pode simplificar significativamente o desenvolvimento backend? As Rotas de API do Next.js permitem criar endpoints de API serverless diretamente na sua aplicação Next.js, eliminando a necessidade de um servidor backend separado em muitos casos. Este guia completo irá orientá-lo no processo de construção de um backend robusto e escalável usando as Rotas de API do Next.js.

O que são as Rotas de API do Next.js?

As Rotas de API são funções serverless que você cria no diretório /pages/api do seu projeto Next.js. Essas funções lidam com requisições HTTP recebidas e retornam respostas, assim como uma API backend tradicional. A principal diferença é que elas são implantadas como funções serverless, o que significa que você não precisa gerenciar servidores ou infraestrutura.

Pense nelas como funções backend leves e sob demanda que são perfeitamente integradas ao seu front-end Next.js.

Benefícios de Usar as Rotas de API do Next.js

Começando com as Rotas de API do Next.js

Vamos criar uma rota de API simples que retorna uma resposta JSON. Primeiro, certifique-se de que você tem um projeto Next.js configurado. Se não, crie um usando:

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

Agora, crie um arquivo chamado hello.js dentro do diretório /pages/api:

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

Este código define uma rota de API simples que responde com um objeto JSON contendo o nome "John Doe". Para acessar esta rota de API, inicie seu servidor de desenvolvimento Next.js:

npm run dev

Em seguida, abra seu navegador e navegue para http://localhost:3000/api/hello. Você deverá ver a seguinte resposta JSON:

{"name": "John Doe"}

Entendendo o Manipulador da Rota de API

A função handler na sua rota de API recebe dois argumentos:

Você pode usar esses objetos para lidar com diferentes tipos de requisições, ler dados do corpo da requisição, definir cabeçalhos de resposta e enviar diferentes tipos de respostas.

Lidando com Diferentes Métodos HTTP

Você pode usar a propriedade req.method para determinar o método HTTP da requisição recebida e lidar com diferentes métodos de acordo. Por exemplo:

// pages/api/method.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Lida com a requisição GET
    res.status(200).json({ message: 'Esta é uma requisição GET' })
  } else if (req.method === 'POST') {
    // Lida com a requisição POST
    res.status(200).json({ message: 'Esta é uma requisição POST' })
  } else {
    // Lida com outros métodos
    res.status(405).json({ message: 'Método Não Permitido' })
  }
}

Neste exemplo, a rota de API lida com requisições GET e POST. Se o método da requisição for GET, ela responde com um objeto JSON contendo a mensagem "Esta é uma requisição GET". Se o método for POST, responde com um objeto JSON contendo a mensagem "Esta é uma requisição POST". Se o método da requisição for qualquer outro, ela responde com um erro 405 Método Não Permitido.

Lendo Dados do Corpo da Requisição

Para requisições POST, PUT e PATCH, você frequentemente precisa ler dados do corpo da requisição. O Next.js fornece suporte integrado para analisar corpos de requisição JSON e codificados por URL. Para analisar um corpo de requisição JSON, você pode usar a propriedade req.body. Por exemplo:

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

    // Processa os dados
    console.log('Nome:', name)
    console.log('Email:', email)

    res.status(200).json({ message: 'Dados recebidos com sucesso' })
  } else {
    res.status(405).json({ message: 'Método Não Permitido' })
  }
}

Para testar esta rota de API, você pode usar uma ferramenta como o Postman ou curl para enviar uma requisição POST com um corpo JSON:

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

Definindo Cabeçalhos de Resposta

Você pode usar o método res.setHeader() para definir cabeçalhos de resposta. Isso é útil para definir o tipo de conteúdo, controle de cache e outras informações importantes. Por exemplo:

// 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: 'Olá, mundo!' })
}

Neste exemplo, a rota de API define o cabeçalho Content-Type para application/json, indicando que a resposta é um objeto JSON. Ela também define o cabeçalho Cache-Control para s-maxage=3600, que informa ao navegador e à CDN para armazenar a resposta em cache por até 1 hora.

Tratamento de Erros

É importante tratar os erros de forma elegante em suas rotas de API. Você pode usar blocos try-catch para capturar exceções e enviar respostas de erro apropriadas ao cliente. Por exemplo:

// pages/api/error.js
export default async function handler(req, res) {
  try {
    // Simula um erro
    throw new Error('Algo deu errado')
  } catch (error) {
    console.error(error)
    res.status(500).json({ message: 'Erro Interno do Servidor' })
  }
}

Neste exemplo, a rota de API simula um erro lançando um novo objeto Error. O bloco catch captura o erro, o registra no console e envia uma resposta 500 Erro Interno do Servidor para o cliente. Considere usar um sistema de registro robusto como Sentry ou Datadog para ambientes de produção.

Conectando a um Banco de Dados

Um dos casos de uso mais comuns para rotas de API é a conexão a um banco de dados. As Rotas de API do Next.js se integram perfeitamente com vários bancos de dados, incluindo:

Aqui está um exemplo de como se conectar a um banco de dados MongoDB em uma rota de API do 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('Por favor, adicione sua URI do Mongo ao .env.local')
}

if (process.env.NODE_ENV === 'development') {
  // Em modo de desenvolvimento, use uma variável global para que o valor
  // seja preservado entre as recargas de módulo causadas pelo HMR (Hot Module Replacement).
  if (!global._mongoClientPromise) {
    client = new MongoClient(uri, options)
    global._mongoClientPromise = client.connect()
  }
  clientPromise = global._mongoClientPromise
} else {
  // Em modo de produção, é melhor não usar uma variável global.
  client = new MongoClient(uri, options)
  clientPromise = client.connect()
}

// Exporte uma promessa MongoClient com escopo de módulo. Ao fazer isso em um
// módulo separado, o cliente pode ser reutilizado com segurança em várias
// funções. Veja: 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: 'Falha ao buscar usuários' })
  }
}

Antes de executar este código, certifique-se de que você tem o pacote mongodb instalado:

npm install mongodb

Você também precisa definir as variáveis de ambiente MONGODB_URI e MONGODB_DB. Essas variáveis devem ser definidas em seu arquivo .env.local (ou nas configurações de variáveis de ambiente do seu provedor de hospedagem para produção). A MONGODB_URI contém a string de conexão para seu banco de dados MongoDB, e MONGODB_DB especifica o nome do banco de dados.

Autenticação e Autorização

Proteger suas rotas de API é crucial para a segurança. As Rotas de API do Next.js podem ser protegidas usando várias técnicas de autenticação e autorização, incluindo:

Aqui está um exemplo de como proteger uma rota de API usando autenticação 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: 'Não autorizado' })
  }

  try {
    const decoded = jwt.verify(token, secret)
    // O objeto "decoded" contém as informações do usuário embutidas no token
    // Por exemplo: const userId = decoded.userId;

    // Continua o processamento da requisição
    res.status(200).json({ message: 'Recurso protegido acessado com sucesso' })
  } catch (error) {
    return res.status(401).json({ message: 'Token inválido' })
  }
}

Antes de executar este código, certifique-se de que você tem o pacote jsonwebtoken instalado:

npm install jsonwebtoken

Você também precisa definir a variável de ambiente JWT_SECRET. Esta deve ser uma chave secreta forte e gerada aleatoriamente, usada para assinar e verificar JWTs. Armazene-a com segurança e nunca a exponha em seu código do lado do cliente.

Middleware

Embora o Next.js não ofereça middleware tradicional para rotas de API da mesma forma que o Express.js, você pode alcançar uma funcionalidade semelhante envolvendo seus manipuladores de rotas de API com funções reutilizáveis. Isso permite que você execute tarefas como:

Aqui está um exemplo de como criar um middleware de registro simples:

// 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, simplesmente envolva seu manipulador de rota de API com a função withLogging:

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

async function handler(req, res) {
  res.status(200).json({ message: 'Esta requisição foi registrada' })
}

export default withLogging(handler)

Melhores Práticas para Construir Rotas de API no Next.js

Técnicas Avançadas

Tarefas em Segundo Plano (Background Jobs)

Para tarefas de longa duração que não devem bloquear a resposta da API, considere o uso de tarefas em segundo plano. Você pode usar bibliotecas como BullMQ ou Bree para gerenciar suas tarefas em segundo plano e processá-las de forma assíncrona.

WebSockets

Para aplicações em tempo real, você pode usar WebSockets em suas rotas de API do Next.js. Bibliotecas como Socket.IO e ws facilitam o estabelecimento de conexões persistentes entre o cliente e o servidor.

GraphQL

Se você precisa de uma maneira mais flexível e eficiente de buscar dados, considere usar GraphQL. Você pode usar bibliotecas como Apollo Server ou Yoga para criar um endpoint de API GraphQL em sua aplicação Next.js.

Conclusão

As Rotas de API do Next.js fornecem uma maneira poderosa e conveniente de construir backends serverless diretamente em sua aplicação Next.js. Ao aproveitar os benefícios da arquitetura serverless, você pode simplificar o desenvolvimento, melhorar o desempenho e reduzir custos. Seja construindo um formulário de contato simples ou uma plataforma de e-commerce complexa, as Rotas de API do Next.js podem ajudá-lo a criar um backend robusto e escalável com facilidade. Com uma sólida compreensão dos fundamentos e a aplicação das melhores práticas, você pode aproveitar esta ferramenta poderosa para criar aplicações eficientes, seguras e globalmente acessíveis.