Čeština

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:

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ě:

Objekt Response

Funkce middleware vracejí objekt Response pro řízení výsledku požadavku. Můžete použít následující odpovědi:

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

Řešení běžných problémů

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ů.

Middleware v Next.js: Zvládnutí zachytávání požadavků pro dynamické aplikace | MLOG