Italiano

Scopri come creare backend serverless con le Route API di Next.js. Questa guida copre configurazione, autenticazione, persistenza dati e tecniche avanzate.

Route API di Next.js: Costruire il Tuo Backend con Facilità

Next.js ha rivoluzionato lo sviluppo front-end con le sue potenti funzionalità e la sua struttura intuitiva. Ma sapevi che può anche semplificare notevolmente lo sviluppo del backend? Le Route API di Next.js ti permettono di creare endpoint API serverless direttamente all'interno della tua applicazione Next.js, eliminando in molti casi la necessità di un server backend separato. Questa guida completa ti accompagnerà nel processo di costruzione di un backend robusto e scalabile utilizzando le Route API di Next.js.

Cosa sono le Route API di Next.js?

Le Route API sono funzioni serverless che crei all'interno della directory /pages/api nel tuo progetto Next.js. Queste funzioni gestiscono le richieste HTTP in entrata e restituiscono risposte, proprio come un'API backend tradizionale. La differenza principale è che vengono distribuite come funzioni serverless, il che significa che non devi gestire server o infrastrutture.

Pensa a loro come a funzioni backend leggere e on-demand che si integrano perfettamente con il tuo front-end Next.js.

Vantaggi dell'utilizzo delle Route API di Next.js

Iniziare con le Route API di Next.js

Creiamo una semplice rotta API che restituisce una risposta JSON. Per prima cosa, assicurati di aver configurato un progetto Next.js. In caso contrario, creane uno usando:

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

Ora, crea un file chiamato hello.js all'interno della directory /pages/api:

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

Questo codice definisce una semplice rotta API che risponde con un oggetto JSON contenente il nome "John Doe". Per accedere a questa rotta API, avvia il tuo server di sviluppo Next.js:

npm run dev

Quindi, apri il browser e vai su http://localhost:3000/api/hello. Dovresti vedere la seguente risposta JSON:

{"name": "John Doe"}

Comprendere l'Handler della Rotta API

La funzione handler nella tua rotta API riceve due argomenti:

Puoi usare questi oggetti per gestire diversi tipi di richieste, leggere dati dal corpo della richiesta, impostare gli header di risposta e inviare diversi tipi di risposte.

Gestire i Diversi Metodi HTTP

Puoi usare la proprietà req.method per determinare il metodo HTTP della richiesta in arrivo e gestire i diversi metodi di conseguenza. Per esempio:

// pages/api/method.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Gestisce la richiesta GET
    res.status(200).json({ message: 'This is a GET request' })
  } else if (req.method === 'POST') {
    // Gestisce la richiesta POST
    res.status(200).json({ message: 'This is a POST request' })
  } else {
    // Gestisce altri metodi
    res.status(405).json({ message: 'Method Not Allowed' })
  }
}

In questo esempio, la rotta API gestisce sia le richieste GET che POST. Se il metodo della richiesta è GET, risponde con un oggetto JSON contenente il messaggio "This is a GET request". Se il metodo della richiesta è POST, risponde con un oggetto JSON contenente il messaggio "This is a POST request". Se il metodo della richiesta è un altro, risponde con un errore 405 Method Not Allowed.

Leggere i Dati dal Corpo della Richiesta

Per le richieste POST, PUT e PATCH, spesso è necessario leggere i dati dal corpo della richiesta. Next.js fornisce un supporto integrato per il parsing dei corpi di richiesta JSON e URL-encoded. Per analizzare un corpo di richiesta JSON, puoi usare la proprietà req.body. Ad esempio:

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

    // Elabora i dati
    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' })
  }
}

Per testare questa rotta API, puoi usare uno strumento come Postman o curl per inviare una richiesta POST con un corpo JSON:

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

Impostare gli Header di Risposta

Puoi usare il metodo res.setHeader() per impostare gli header di risposta. Questo è utile per impostare il tipo di contenuto, il controllo della cache e altre informazioni importanti. Ad esempio:

// 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!' })
}

In questo esempio, la rotta API imposta l'header Content-Type su application/json, indicando che la risposta è un oggetto JSON. Imposta anche l'header Cache-Control su s-maxage=3600, che indica al browser e alla CDN di memorizzare nella cache la risposta per un massimo di 1 ora.

Gestione degli Errori

È importante gestire gli errori in modo corretto nelle tue route API. Puoi usare i blocchi try-catch per catturare le eccezioni e inviare risposte di errore appropriate al client. Ad esempio:

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

In questo esempio, la rotta API simula un errore lanciando un nuovo oggetto Error. Il blocco catch cattura l'errore, lo registra nella console e invia una risposta 500 Internal Server Error al client. Considera l'uso di un sistema di logging robusto come Sentry o Datadog per gli ambienti di produzione.

Connettersi a un Database

Uno dei casi d'uso più comuni per le route API è la connessione a un database. Le Route API di Next.js si integrano perfettamente con vari database, tra cui:

Ecco un esempio di come connettersi a un database MongoDB in una rotta API di 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') {
  // In modalità di sviluppo, usa una variabile globale in modo che il valore
  // venga preservato tra i ricaricamenti dei moduli causati dall'HMR (Hot Module Replacement).
  if (!global._mongoClientPromise) {
    client = new MongoClient(uri, options)
    global._mongoClientPromise = client.connect()
  }
  clientPromise = global._mongoClientPromise
} else {
  // In modalità di produzione, è meglio non usare una variabile globale.
  client = new MongoClient(uri, options)
  clientPromise = client.connect()
}

// Esporta una promise MongoClient con scope a livello di modulo. Facendo questo in un
// modulo separato, il client può essere riutilizzato in sicurezza tra più
// funzioni. Vedi: 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' })
  }
}

Prima di eseguire questo codice, assicurati di aver installato il pacchetto mongodb:

npm install mongodb

Devi anche impostare le variabili d'ambiente MONGODB_URI e MONGODB_DB. Queste variabili dovrebbero essere definite nel tuo file .env.local (o nelle impostazioni delle variabili d'ambiente del tuo provider di hosting per la produzione). La MONGODB_URI contiene la stringa di connessione al tuo database MongoDB, e MONGODB_DB specifica il nome del database.

Autenticazione e Autorizzazione

Proteggere le tue route API è fondamentale per la sicurezza. Le Route API di Next.js possono essere protette utilizzando varie tecniche di autenticazione e autorizzazione, tra cui:

Ecco un esempio di come proteggere una rotta API utilizzando l'autenticazione 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)
    // L'oggetto "decoded" contiene le informazioni dell'utente incorporate nel token
    // Ad esempio: const userId = decoded.userId;

    // Continua l'elaborazione della richiesta
    res.status(200).json({ message: 'Protected resource accessed successfully' })
  } catch (error) {
    return res.status(401).json({ message: 'Invalid token' })
  }
}

Prima di eseguire questo codice, assicurati di aver installato il pacchetto jsonwebtoken:

npm install jsonwebtoken

Devi anche impostare la variabile d'ambiente JWT_SECRET. Questa dovrebbe essere una chiave segreta forte, generata casualmente, utilizzata per firmare e verificare i JWT. Conservala in modo sicuro e non esporla mai nel codice lato client.

Middleware

Anche se Next.js non offre un middleware tradizionale per le route API come fa Express.js, puoi ottenere funzionalità simili avvolgendo i tuoi gestori di route API con funzioni riutilizzabili. Questo ti permette di eseguire attività come:

Ecco un esempio di come creare un semplice middleware di logging:

// 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)
  }
}

Per usare questo middleware, avvolgi semplicemente il gestore della tua rotta API con la funzione 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)

Best Practice per la Creazione di Route API di Next.js

Tecniche Avanzate

Processi in Background (Background Jobs)

Per attività di lunga durata che non dovrebbero bloccare la risposta dell'API, considera l'uso di processi in background. Puoi usare librerie come BullMQ o Bree per gestire i tuoi processi in background ed elaborarli in modo asincrono.

WebSockets

Per applicazioni in tempo reale, puoi usare i WebSockets nelle tue route API di Next.js. Librerie come Socket.IO e ws rendono facile stabilire connessioni persistenti tra il client e il server.

GraphQL

Se hai bisogno di un modo più flessibile ed efficiente per recuperare i dati, considera l'uso di GraphQL. Puoi usare librerie come Apollo Server o Yoga per creare un endpoint API GraphQL nella tua applicazione Next.js.

Conclusione

Le Route API di Next.js forniscono un modo potente e conveniente per costruire backend serverless direttamente all'interno della tua applicazione Next.js. Sfruttando i vantaggi dell'architettura serverless, puoi semplificare lo sviluppo, migliorare le prestazioni e ridurre i costi. Che tu stia costruendo un semplice modulo di contatto o una complessa piattaforma di e-commerce, le Route API di Next.js possono aiutarti a creare un backend robusto e scalabile con facilità. Con una solida comprensione dei fondamenti e l'applicazione delle best practice, puoi sfruttare questo potente strumento per creare applicazioni efficienti, sicure e accessibili a livello globale.