Prozkoumejte middleware v Next.js, mocný nástroj pro zachytávání a úpravu příchozích požadavků. Naučte se implementovat autentizaci, autorizaci, přesměrování a A/B testování s praktickými příklady.
Middleware v Next.js: Zvládnutí zachytávání požadavků pro dynamické aplikace
Middleware v Next.js poskytuje flexibilní a výkonný způsob, jak zachytit a upravit příchozí požadavky dříve, než se dostanou k vašim routám. Tato schopnost vám umožňuje implementovat širokou škálu funkcí, od autentizace a autorizace po přesměrování a A/B testování, a to vše při optimalizaci výkonu. Tento komplexní průvodce vás provede klíčovými koncepty middleware v Next.js a ukáže vám, jak ho efektivně využívat.
Co je middleware v Next.js?
Middleware v Next.js je funkce, která se spouští před dokončením požadavku. Umožňuje vám:
- Zachytit požadavky: Prozkoumat hlavičky, cookies a URL příchozího požadavku.
- Upravit požadavky: Přepsat URL, nastavit hlavičky nebo přesměrovat uživatele na základě specifických kritérií.
- Spustit kód: Spustit logiku na straně serveru před vykreslením stránky.
Funkce middleware jsou definovány v souboru middleware.ts
(nebo middleware.js
) v kořenovém adresáři vašeho projektu. Spouštějí se pro každou routu ve vaší aplikaci, nebo pro specifické routy na základě konfigurovatelných „matcherů“ (pravidel pro shodu).
Klíčové koncepty a výhody
Objekt Request
Objekt request
poskytuje přístup k informacím o příchozím požadavku, včetně:
request.url
: Plná URL adresa požadavku.request.method
: HTTP metoda (např. GET, POST).request.headers
: Objekt obsahující hlavičky požadavku.request.cookies
: Objekt reprezentující cookies požadavku.request.geo
: Poskytuje geolokační data spojená s požadavkem, pokud jsou k dispozici.
Objekt Response
Funkce middleware vracejí objekt Response
pro řízení výsledku požadavku. Můžete použít následující odpovědi:
NextResponse.next()
: Pokračuje v běžném zpracování požadavku a umožňuje mu dosáhnout zamýšlené routy.NextResponse.redirect(url)
: Přesměruje uživatele na jinou URL.NextResponse.rewrite(url)
: Přepíše URL požadavku, čímž efektivně zobrazí jinou stránku bez přesměrování. URL v prohlížeči zůstává stejná.- Vrácení vlastního objektu
Response
: Umožňuje vám doručit vlastní obsah, jako je chybová stránka nebo specifická JSON odpověď.
Matchers (pravidla pro shodu)
„Matchery“ vám umožňují specifikovat, na které routy se má váš middleware aplikovat. Můžete definovat „matchery“ pomocí regulárních výrazů nebo vzorů cest. To zajišťuje, že se váš middleware spouští pouze v nezbytných případech, což zlepšuje výkon a snižuje zátěž.
Edge Runtime
Middleware v Next.js běží na Edge Runtime, což je odlehčené běhové prostředí JavaScriptu, které může být nasazeno blízko vašich uživatelů. Tato blízkost minimalizuje latenci a zlepšuje celkový výkon vaší aplikace, zejména pro globálně distribuované uživatele. Edge Runtime je k dispozici na Vercel's Edge Network a dalších kompatibilních platformách. Edge Runtime má určitá omezení, konkrétně v použití Node.js API.
Praktické příklady: Implementace funkcí middleware
1. Autentizace
Autentizační middleware lze použít k ochraně rout, které vyžadují, aby byli uživatelé přihlášeni. Zde je příklad, jak implementovat autentizaci pomocí cookies:
// 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*'],
}
Tento middleware kontroluje přítomnost cookie auth_token
. Pokud cookie není nalezena, uživatel je přesměrován na stránku /login
. config.matcher
specifikuje, že tento middleware by se měl spouštět pouze pro routy pod /dashboard
.
Globální perspektiva: Přizpůsobte logiku autentizace tak, aby podporovala různé metody (např. OAuth, JWT) a integrovala se s různými poskytovateli identity (např. Google, Facebook, Azure AD), abyste vyhověli uživatelům z různých regionů.
2. Autorizace
Autorizační middleware lze použít k řízení přístupu ke zdrojům na základě rolí nebo oprávnění uživatelů. Můžete mít například administrátorský panel, ke kterému mají přístup pouze specifičtí uživatelé.
// 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))
}
// Příklad: Načtení rolí uživatele z API (nahraďte vaší skutečnou logikou)
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*'],
}
Tento middleware načte roli uživatele a zkontroluje, zda má roli admin
. Pokud ne, je přesměrován na stránku /unauthorized
. Tento příklad používá zástupný API endpoint. Nahraďte `https://api.example.com/userinfo` vaším skutečným endpointem autentizačního serveru.
Globální perspektiva: Při zpracování uživatelských dat dbejte na předpisy o ochraně osobních údajů (např. GDPR, CCPA). Implementujte vhodná bezpečnostní opatření k ochraně citlivých informací a zajistěte soulad s místními zákony.
3. Přesměrování
Přesměrovací middleware lze použít k přesměrování uživatelů na základě jejich polohy, jazyka nebo jiných kritérií. Můžete například přesměrovat uživatele na lokalizovanou verzi vašeho webu na základě jejich IP adresy.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const country = request.geo?.country || 'US'; // Výchozí hodnota je US, pokud geolokace selže
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: ['/'],
}
Tento middleware kontroluje zemi uživatele na základě jeho IP adresy a přesměrovává ho na příslušnou lokalizovanou verzi webu (/de
pro Německo, /fr
pro Francii). Pokud geolokace selže, výchozí je americká verze. Upozorňujeme, že toto závisí na dostupnosti vlastnosti geo
(např. při nasazení na Vercel).
Globální perspektiva: Zajistěte, aby vaše webové stránky podporovaly více jazyků a měn. Poskytněte uživatelům možnost ručně si vybrat preferovaný jazyk nebo region. Používejte vhodné formáty data a času pro každou lokalitu.
4. A/B testování
Middleware lze použít k implementaci A/B testování náhodným přiřazováním uživatelů k různým variantám stránky a sledováním jejich chování. Zde je zjednodušený příklad:
// 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: ['/'],
}
Tento middleware přiřazuje uživatele buď k variantě 'A' nebo 'B'. Pokud uživatel ještě nemá cookie variant
, je mu náhodně přiřazena a nastavena. Uživatelé přiřazení k variantě 'B' jsou přesměrováni (pomocí `rewrite`) na stránku /variant-b
. Poté byste sledovali výkon každé varianty, abyste určili, která je efektivnější.
Globální perspektiva: Při navrhování A/B testů zvažte kulturní rozdíly. Co funguje dobře v jednom regionu, nemusí rezonovat s uživateli v jiném. Zajistěte, aby vaše platforma pro A/B testování byla v souladu s předpisy o ochraně osobních údajů v různých regionech.
5. Feature Flags (příznaky funkcí)
„Feature flags“ (příznaky funkcí) vám umožňují povolit nebo zakázat funkce ve vaší aplikaci bez nasazení nového kódu. Middleware lze použít k určení, zda by měl mít uživatel přístup ke konkrétní funkci na základě jeho ID, polohy nebo jiných kritérií.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
// Příklad: Načtení feature flagů z 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) {
// Povolit novou funkci
return NextResponse.next();
} else {
// Zakázat novou funkci (např. přesměrovat na alternativní stránku)
return NextResponse.redirect(new URL('/alternative-page', request.url));
}
}
export const config = {
matcher: ['/new-feature'],
}
Tento middleware načítá „feature flags“ z API a kontroluje, zda je nastaven příznak new_feature_enabled
. Pokud ano, uživatel má přístup na stránku /new-feature
. V opačném případě je přesměrován na /alternative-page
.
Globální perspektiva: Používejte „feature flags“ k postupnému zavádění nových funkcí uživatelům v různých regionech. To vám umožní sledovat výkon a řešit případné problémy před vydáním funkce širšímu publiku. Také se ujistěte, že váš systém pro „feature flagging“ je globálně škálovatelný a poskytuje konzistentní výsledky bez ohledu na polohu uživatele. Zvažte regionální regulační omezení pro zavádění funkcí.
Pokročilé techniky
Řetězení middleware
Můžete zřetězit více funkcí middleware dohromady a provádět tak sérii operací na požadavku. To může být užitečné pro rozdělení složité logiky na menší, lépe spravovatelné moduly.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next();
// První funkce middleware
const token = request.cookies.get('auth_token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Druhá funkce middleware
response.headers.set('x-middleware-custom', 'value');
return response;
}
export const config = {
matcher: ['/dashboard/:path*'],
}
Tento příklad ukazuje dva middleware v jednom. První provádí autentizaci a druhý nastavuje vlastní hlavičku.
Použití proměnných prostředí
Ukládejte citlivé informace, jako jsou API klíče a přihlašovací údaje k databázi, do proměnných prostředí, místo abyste je napevno kódovali ve svých funkcích middleware. To zlepšuje bezpečnost a usnadňuje správu konfigurace vaší aplikace.
// 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'],
}
V tomto příkladu je API_KEY
načten z proměnné prostředí.
Zpracování chyb
Implementujte robustní zpracování chyb ve vašich funkcích middleware, abyste zabránili neočekávaným chybám, které by mohly způsobit pád vaší aplikace. Používejte bloky try...catch
k zachycení výjimek a správnému logování chyb.
// 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('Error fetching data:', error);
return NextResponse.error(); // Nebo přesměrovat na chybovou stránku
}
}
export const config = {
matcher: ['/data'],
}
Doporučené postupy
- Udržujte funkce middleware odlehčené: Vyhněte se provádění výpočetně náročných operací v middleware, protože to může ovlivnit výkon. Přesuňte komplexní zpracování na úlohy na pozadí nebo do dedikovaných služeb.
- Používejte „matchery“ efektivně: Aplikujte middleware pouze na routy, které to vyžadují.
- Důkladně testujte svůj middleware: Pište jednotkové testy, abyste se ujistili, že vaše funkce middleware fungují správně.
- Monitorujte výkon middleware: Používejte monitorovací nástroje ke sledování výkonu vašich funkcí middleware a identifikaci úzkých míst.
- Dokumentujte svůj middleware: Jasně dokumentujte účel a funkcionalitu každé funkce middleware.
- Zvažte omezení Edge Runtime: Buďte si vědomi omezení Edge Runtime, jako je absence Node.js API. Přizpůsobte tomu svůj kód.
Řešení běžných problémů
- Middleware se nespouští: Znovu zkontrolujte konfiguraci „matcheru“, abyste se ujistili, že se middleware aplikuje na správné routy.
- Problémy s výkonem: Identifikujte a optimalizujte pomalé funkce middleware. Použijte profilovací nástroje k nalezení úzkých míst výkonu.
- Kompatibilita s Edge Runtime: Ujistěte se, že váš kód je kompatibilní s Edge Runtime. Vyhněte se používání nepodporovaných Node.js API.
- Problémy s cookies: Ověřte, že jsou cookies správně nastavovány a načítány. Věnujte pozornost atributům cookies, jako jsou
domain
,path
asecure
. - Konflikty v hlavičkách: Buďte si vědomi možných konfliktů v hlavičkách při nastavování vlastních hlaviček v middleware. Ujistěte se, že vaše hlavičky nechtěně nepřepisují existující hlavičky.
Závěr
Middleware v Next.js je mocný nástroj pro tvorbu dynamických a personalizovaných webových aplikací. Zvládnutím zachytávání požadavků můžete implementovat širokou škálu funkcí, od autentizace a autorizace po přesměrování a A/B testování. Dodržováním doporučených postupů uvedených v této příručce můžete využít middleware v Next.js k vytváření vysoce výkonných, bezpečných a škálovatelných aplikací, které splňují potřeby vaší globální uživatelské základny. Využijte sílu middleware k odemknutí nových možností ve vašich projektech Next.js a poskytování výjimečných uživatelských zážitků.