Română

Explorați middleware-ul Next.js, o funcționalitate puternică pentru interceptarea și modificarea cererilor. Învățați cum să implementați autentificare, autorizare, redirecționare și teste A/B cu exemple practice.

Middleware în Next.js: Stăpânirea interceptării cererilor pentru aplicații dinamice

Middleware-ul Next.js oferă o modalitate flexibilă și puternică de a intercepta și modifica cererile primite înainte ca acestea să ajungă la rutele dumneavoastră. Această capacitate vă permite să implementați o gamă largă de funcționalități, de la autentificare și autorizare la redirecționare și teste A/B, totul în timp ce optimizați performanța. Acest ghid complet vă va prezenta conceptele de bază ale middleware-ului Next.js și vă va demonstra cum să îl utilizați eficient.

Ce este middleware-ul Next.js?

Middleware-ul în Next.js este o funcție care rulează înainte ca o cerere să fie finalizată. Vă permite să:

Funcțiile middleware sunt definite în fișierul middleware.ts (sau middleware.js) la rădăcina proiectului dumneavoastră. Acestea sunt executate pentru fiecare rută din aplicația dumneavoastră sau pentru rute specifice, pe baza unor criterii de potrivire (matchers) configurabile.

Concepte cheie și beneficii

Obiectul Request

Obiectul request oferă acces la informații despre cererea primită, inclusiv:

Obiectul Response

Funcțiile middleware returnează un obiect Response pentru a controla rezultatul cererii. Puteți utiliza următoarele răspunsuri:

Matchers (Criterii de potrivire)

Criteriile de potrivire (matchers) vă permit să specificați la ce rute ar trebui aplicat middleware-ul. Puteți defini aceste criterii folosind expresii regulate sau modele de cale. Acest lucru asigură că middleware-ul rulează doar atunci când este necesar, îmbunătățind performanța și reducând supraîncărcarea.

Edge Runtime

Middleware-ul Next.js rulează pe Edge Runtime, care este un mediu de execuție JavaScript ușor, ce poate fi implementat aproape de utilizatorii dumneavoastră. Această proximitate minimizează latența și îmbunătățește performanța generală a aplicației dumneavoastră, în special pentru utilizatorii distribuiți la nivel global. Edge Runtime este disponibil pe Edge Network de la Vercel și pe alte platforme compatibile. Edge Runtime are unele limitări, în special în ceea ce privește utilizarea API-urilor Node.js.

Exemple practice: Implementarea funcționalităților middleware

1. Autentificare

Middleware-ul de autentificare poate fi folosit pentru a proteja rutele care necesită ca utilizatorii să fie autentificați. Iată un exemplu despre cum se implementează autentificarea folosind cookie-uri:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Acest middleware verifică prezența unui cookie auth_token. Dacă cookie-ul nu este găsit, utilizatorul este redirecționat către pagina /login. config.matcher specifică faptul că acest middleware ar trebui să ruleze doar pentru rutele de sub /dashboard.

Perspectivă globală: Adaptați logica de autentificare pentru a suporta diverse metode de autentificare (de ex., OAuth, JWT) și integrați-vă cu diferiți furnizori de identitate (de ex., Google, Facebook, Azure AD) pentru a vă adresa utilizatorilor din diverse regiuni.

2. Autorizare

Middleware-ul de autorizare poate fi folosit pentru a controla accesul la resurse pe baza rolurilor sau permisiunilor utilizatorului. De exemplu, ați putea avea un panou de administrare la care doar anumiți utilizatori pot avea acces.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Exemplu: Preluarea rolurilor utilizatorului de la un API (înlocuiți cu logica dvs. reală)
 const userResponse = await fetch('https://api.example.com/userinfo', {
 headers: {
 Authorization: `Bearer ${token}`,
 },
 });
 const userData = await userResponse.json();

 if (userData.role !== 'admin') {
 return NextResponse.redirect(new URL('/unauthorized', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/admin/:path*'],
}

Acest middleware preia rolul utilizatorului și verifică dacă are rolul de admin. Dacă nu, este redirecționat către o pagină /unauthorized. Acest exemplu folosește un endpoint API fictiv. Înlocuiți `https://api.example.com/userinfo` cu endpoint-ul serverului dumneavoastră real de autentificare.

Perspectivă globală: Fiți conștienți de reglementările privind confidențialitatea datelor (de ex., GDPR, CCPA) atunci când gestionați datele utilizatorilor. Implementați măsuri de securitate adecvate pentru a proteja informațiile sensibile și pentru a asigura conformitatea cu legile locale.

3. Redirecționare

Middleware-ul de redirecționare poate fi folosit pentru a redirecționa utilizatorii în funcție de locația, limba sau alte criterii. De exemplu, ați putea redirecționa utilizatorii către o versiune localizată a site-ului dumneavoastră pe baza adresei lor IP.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const country = request.geo?.country || 'US'; // Valoare implicită SUA dacă geo-localizarea eșuează

 if (country === 'DE') {
 return NextResponse.redirect(new URL('/de', request.url))
 }

 if (country === 'FR') {
 return NextResponse.redirect(new URL('/fr', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/'],
}

Acest middleware verifică țara utilizatorului pe baza adresei IP și îl redirecționează către versiunea localizată corespunzătoare a site-ului web (/de pentru Germania, /fr pentru Franța). Dacă geo-localizarea eșuează, se folosește implicit versiunea pentru SUA. Rețineți că acest lucru se bazează pe disponibilitatea proprietății geo (de ex., atunci când este implementat pe Vercel).

Perspectivă globală: Asigurați-vă că site-ul dumneavoastră suportă mai multe limbi și monede. Oferiți utilizatorilor opțiunea de a selecta manual limba sau regiunea preferată. Utilizați formate de dată și oră adecvate pentru fiecare localitate.

4. Teste A/B

Middleware-ul poate fi folosit pentru a implementa teste A/B prin atribuirea aleatorie a utilizatorilor la diferite variante ale unei pagini și urmărirea comportamentului acestora. Iată un exemplu simplificat:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

function getRandomVariant() {
 return Math.random() < 0.5 ? 'A' : 'B';
}

export function middleware(request: NextRequest) {
 let variant = request.cookies.get('variant')?.value;

 if (!variant) {
 variant = getRandomVariant();
 const response = NextResponse.next();
 response.cookies.set('variant', variant);
 return response;
 }

 if (variant === 'B') {
 return NextResponse.rewrite(new URL('/variant-b', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/'],
}

Acest middleware atribuie utilizatorii fie variantei 'A', fie 'B'. Dacă un utilizator nu are deja un cookie variant, unul este atribuit și setat aleatoriu. Utilizatorii atribuiți variantei 'B' sunt direcționați prin rescriere către pagina /variant-b. Apoi, ați urmări performanța fiecărei variante pentru a determina care este mai eficientă.

Perspectivă globală: Luați în considerare diferențele culturale atunci când proiectați teste A/B. Ceea ce funcționează bine într-o regiune s-ar putea să nu rezoneze cu utilizatorii din alta. Asigurați-vă că platforma dumneavoastră de testare A/B este conformă cu reglementările privind confidențialitatea din diferite regiuni.

5. Feature Flags

Feature flags (steaguri de funcționalități) vă permit să activați sau să dezactivați funcționalități în aplicația dumneavoastră fără a implementa cod nou. Middleware-ul poate fi folosit pentru a determina dacă un utilizator ar trebui să aibă acces la o anumită funcționalitate pe baza ID-ului de utilizator, locației sau altor criterii.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 // Exemplu: Preluarea de feature flags de la un API
 const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
 headers: {
 'X-User-Id': 'user123',
 },
 });
 const featureFlags = await featureFlagsResponse.json();

 if (featureFlags.new_feature_enabled) {
 // Activează noua funcționalitate
 return NextResponse.next();
 } else {
 // Dezactivează noua funcționalitate (de ex., redirecționare către o pagină alternativă)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

export const config = {
 matcher: ['/new-feature'],
}

Acest middleware preia feature flags de la un API și verifică dacă steagul new_feature_enabled este setat. Dacă da, utilizatorul poate accesa pagina /new-feature. Altfel, este redirecționat către o pagină /alternative-page.

Perspectivă globală: Folosiți feature flags pentru a lansa treptat noi funcționalități utilizatorilor din diferite regiuni. Acest lucru vă permite să monitorizați performanța și să rezolvați orice problemă înainte de a lansa funcționalitatea unui public mai larg. De asemenea, asigurați-vă că sistemul dumneavoastră de feature flagging se scalează la nivel global și oferă rezultate consistente, indiferent de locația utilizatorului. Luați în considerare constrângerile regulatorii regionale pentru lansarea de funcționalități.

Tehnici avansate

Înlănțuirea de middleware-uri

Puteți înlănțui mai multe funcții middleware pentru a efectua o serie de operațiuni asupra unei cereri. Acest lucru poate fi util pentru a descompune logica complexă în module mai mici și mai ușor de gestionat.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const response = NextResponse.next();

 // Prima funcție middleware
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // A doua funcție middleware
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Acest exemplu arată două middleware-uri într-unul singur. Primul efectuează autentificarea, iar al doilea setează un antet personalizat.

Utilizarea variabilelor de mediu

Stocați informațiile sensibile, cum ar fi cheile API și credențialele bazei de date, în variabile de mediu, în loc să le scrieți direct în codul funcțiilor middleware. Acest lucru îmbunătățește securitatea și facilitează gestionarea configurației aplicației dumneavoastră.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const API_KEY = process.env.API_KEY;

export async function middleware(request: NextRequest) {
 const response = await fetch('https://api.example.com/data', {
 headers: {
 'X-API-Key': API_KEY,
 },
 });

 // ...
}

export const config = {
 matcher: ['/data'],
}

În acest exemplu, API_KEY este preluat dintr-o variabilă de mediu.

Gestionarea erorilor

Implementați o gestionare robustă a erorilor în funcțiile dumneavoastră middleware pentru a preveni ca erorile neașteptate să blocheze aplicația. Folosiți blocuri try...catch pentru a prinde excepțiile și a înregistra erorile în mod corespunzător.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 try {
 const response = await fetch('https://api.example.com/data');
 // ...
 } catch (error) {
 console.error('Eroare la preluarea datelor:', error);
 return NextResponse.error(); // Sau redirecționează către o pagină de eroare
 }
}

export const config = {
 matcher: ['/data'],
}

Cele mai bune practici

Depanarea problemelor comune

Concluzie

Middleware-ul Next.js este un instrument puternic pentru construirea de aplicații web dinamice și personalizate. Prin stăpânirea interceptării cererilor, puteți implementa o gamă largă de funcționalități, de la autentificare și autorizare la redirecționare și teste A/B. Urmând cele mai bune practici prezentate în acest ghid, puteți valorifica middleware-ul Next.js pentru a crea aplicații performante, sigure și scalabile, care să răspundă nevoilor bazei dumneavoastră globale de utilizatori. Profitați de puterea middleware-ului pentru a debloca noi posibilități în proiectele dumneavoastră Next.js și pentru a oferi experiențe excepționale utilizatorilor.