Tutustu Next.js-middlewareen, tehokkaaseen ominaisuuteen saapuvien pyyntöjen sieppaamiseksi ja muokkaamiseksi. Opi toteuttamaan autentikointi, auktorisointi, uudelleenohjaus ja A/B-testaus käytännön esimerkkien avulla.
Next.js-middleware: Pyyntöjen sieppauksen hallinta dynaamisissa sovelluksissa
Next.js-middleware tarjoaa joustavan ja tehokkaan tavan siepata ja muokata saapuvia pyyntöjä ennen kuin ne saavuttavat reittisi. Tämä ominaisuus mahdollistaa laajan valikoiman toiminnallisuuksia, kuten autentikoinnin, auktorisoinnin, uudelleenohjaukset ja A/B-testauksen, samalla optimoiden suorituskykyä. Tämä kattava opas johdattaa sinut Next.js-middlewaren ydin-käsitteisiin ja näyttää, kuinka sitä hyödynnetään tehokkaasti.
Mitä on Next.js-middleware?
Middleware Next.js:ssä on funktio, joka suoritetaan ennen kuin pyyntö käsitellään loppuun. Se antaa sinulle mahdollisuuden:
- Siepata pyyntöjä: Tutki saapuvan pyynnön otsakkeita, evästeitä ja URL-osoitetta.
- Muokata pyyntöjä: Kirjoita URL-osoitteita uudelleen, aseta otsakkeita tai uudelleenohjaa käyttäjiä tiettyjen kriteerien perusteella.
- Suorittaa koodia: Aja palvelinpuolen logiikkaa ennen sivun renderöintiä.
Middleware-funktiot määritellään middleware.ts
(tai middleware.js
) -tiedostossa projektisi juuressa. Ne suoritetaan jokaiselle sovelluksesi reitille tai tietyille reiteille määritettävien matchereiden perusteella.
Keskeiset käsitteet ja edut
Request-objekti
request
-objekti tarjoaa pääsyn saapuvaa pyyntöä koskeviin tietoihin, mukaan lukien:
request.url
: Pyynnön koko URL-osoite.request.method
: HTTP-metodi (esim. GET, POST).request.headers
: Objekti, joka sisältää pyynnön otsakkeet.request.cookies
: Objekti, joka edustaa pyynnön evästeitä.request.geo
: Tarjoaa pyyntöön liittyvän geosijaintitiedon, jos se on saatavilla.
Response-objekti
Middleware-funktiot palauttavat Response
-objektin hallitakseen pyynnön lopputulosta. Voit käyttää seuraavia vastauksia:
NextResponse.next()
: Jatkaa pyynnön käsittelyä normaalisti, sallien sen saavuttaa tarkoitetun reitin.NextResponse.redirect(url)
: Uudelleenohjaa käyttäjän toiseen URL-osoitteeseen.NextResponse.rewrite(url)
: Kirjoittaa pyynnön URL-osoitteen uudelleen, tarjoten tehokkaasti eri sivun ilman uudelleenohjausta. URL-osoite pysyy samana selaimessa.- Palauttamalla mukautetun
Response
-objektin: Mahdollistaa mukautetun sisällön, kuten virhesivun tai tietyn JSON-vastauksen, tarjoamisen.
Matcherit
Matcherien avulla voit määrittää, mihin reitteihin middleware-funktiotasi tulisi soveltaa. Voit määritellä matchereita käyttämällä säännöllisiä lausekkeita tai polkukuvioita. Tämä varmistaa, että middleware-funktiosi suoritetaan vain tarvittaessa, mikä parantaa suorituskykyä ja vähentää yleiskustannuksia.
Edge-ajoympäristö
Next.js-middleware suoritetaan Edge-ajoympäristössä, joka on kevyt JavaScript-ajoympäristö, joka voidaan sijoittaa lähelle käyttäjiäsi. Tämä läheisyys minimoi viiveen ja parantaa sovelluksesi yleistä suorituskykyä, erityisesti maailmanlaajuisesti hajautetuille käyttäjille. Edge-ajoympäristö on saatavilla Vercelin Edge-verkossa ja muilla yhteensopivilla alustoilla. Edge-ajoympäristöllä on joitain rajoituksia, erityisesti Node.js-API:en käytössä.
Käytännön esimerkkejä: Middleware-ominaisuuksien toteuttaminen
1. Autentikointi
Autentikointi-middlewarea voidaan käyttää suojaamaan reittejä, jotka vaativat käyttäjien olevan kirjautuneena sisään. Tässä on esimerkki siitä, kuinka autentikointi toteutetaan evästeiden avulla:
// 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*'],
}
Tämä middleware tarkistaa auth_token
-evästeen olemassaolon. Jos evästettä ei löydy, käyttäjä uudelleenohjataan /login
-sivulle. config.matcher
määrittää, että tämä middleware suoritetaan vain /dashboard
-polun alaisille reiteille.
Globaali näkökulma: Mukauta autentikointilogiikka tukemaan erilaisia todennusmenetelmiä (esim. OAuth, JWT) ja integroi se eri identiteetintarjoajiin (esim. Google, Facebook, Azure AD) palvellaksesi käyttäjiä eri alueilta.
2. Auktorisointi
Auktorisointi-middlewarea voidaan käyttää hallitsemaan pääsyä resursseihin käyttäjäroolien tai käyttöoikeuksien perusteella. Sinulla saattaa esimerkiksi olla ylläpitäjän hallintapaneeli, johon vain tietyt käyttäjät pääsevät.
// 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))
}
// Esimerkki: Hae käyttäjäroolit API:sta (korvaa omalla logiikallasi)
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*'],
}
Tämä middleware hakee käyttäjän roolin ja tarkistaa, onko hänellä admin
-rooli. Jos ei, hänet uudelleenohjataan /unauthorized
-sivulle. Tämä esimerkki käyttää paikkamerkki-API-päätepistettä. Korvaa `https://api.example.com/userinfo` todellisella autentikointipalvelimesi päätepisteellä.
Globaali näkökulma: Ota huomioon tietosuoja-asetukset (esim. GDPR, CCPA) käsitellessäsi käyttäjätietoja. Toteuta asianmukaiset turvatoimet suojataksesi arkaluontoisia tietoja ja varmistaaksesi paikallisten lakien noudattamisen.
3. Uudelleenohjaus
Uudelleenohjaus-middlewarea voidaan käyttää ohjaamaan käyttäjiä uudelleen heidän sijaintinsa, kielensä tai muiden kriteerien perusteella. Voit esimerkiksi uudelleenohjata käyttäjät verkkosivustosi lokalisoituun versioon heidän IP-osoitteensa perusteella.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const country = request.geo?.country || 'US'; // Oletuksena US, jos geosijainti epäonnistuu
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: ['/'],
}
Tämä middleware tarkistaa käyttäjän maan hänen IP-osoitteensa perusteella ja uudelleenohjaa hänet verkkosivuston asianmukaiseen lokalisoituun versioon (/de
Saksaan, /fr
Ranskaan). Jos geosijainti epäonnistuu, se oletuksena käyttää Yhdysvaltain versiota. Huomaa, että tämä perustuu geo-ominaisuuden saatavuuteen (esim. kun sovellus on Vercelissä).
Globaali näkökulma: Varmista, että verkkosivustosi tukee useita kieliä ja valuuttoja. Tarjoa käyttäjille mahdollisuus valita manuaalisesti haluamansa kieli tai alue. Käytä asianmukaisia päivämäärä- ja aikamuotoja kullekin lokaalille.
4. A/B-testaus
Middlewarea voidaan käyttää A/B-testauksen toteuttamiseen jakamalla käyttäjät satunnaisesti sivun eri versioihin ja seuraamalla heidän käyttäytymistään. Tässä on yksinkertaistettu esimerkki:
// 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: ['/'],
}
Tämä middleware jakaa käyttäjät joko varianttiin 'A' tai 'B'. Jos käyttäjällä ei vielä ole variant
-evästettä, sellainen arvotaan ja asetetaan. Varianttiin 'B' osoitetut käyttäjät ohjataan uudelleenkirjoituksella /variant-b
-sivulle. Tämän jälkeen seuraisit kunkin variantin suorituskykyä määrittääksesi, kumpi on tehokkaampi.
Globaali näkökulma: Ota huomioon kulttuurierot suunnitellessasi A/B-testejä. Se, mikä toimii hyvin yhdellä alueella, ei välttämättä resonoi käyttäjien kanssa toisella. Varmista, että A/B-testausalustasi on yhteensopiva eri alueiden tietosuojamääräysten kanssa.
5. Ominaisuusliput (Feature Flags)
Ominaisuuslippujen avulla voit ottaa käyttöön tai poistaa käytöstä sovelluksesi ominaisuuksia ilman uutta koodin julkaisua. Middlewarea voidaan käyttää määrittämään, pitäisikö käyttäjällä olla pääsy tiettyyn ominaisuuteen hänen käyttäjätunnuksensa, sijaintinsa tai muiden kriteerien perusteella.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
// Esimerkki: Hae ominaisuusliput API:sta
const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
headers: {
'X-User-Id': 'user123',
},
});
const featureFlags = await featureFlagsResponse.json();
if (featureFlags.new_feature_enabled) {
// Ota uusi ominaisuus käyttöön
return NextResponse.next();
} else {
// Poista uusi ominaisuus käytöstä (esim. uudelleenohjaa vaihtoehtoiselle sivulle)
return NextResponse.redirect(new URL('/alternative-page', request.url));
}
}
export const config = {
matcher: ['/new-feature'],
}
Tämä middleware hakee ominaisuusliput API:sta ja tarkistaa, onko new_feature_enabled
-lippu asetettu. Jos on, käyttäjä pääsee /new-feature
-sivulle. Muuten hänet uudelleenohjataan /alternative-page
-sivulle.
Globaali näkökulma: Käytä ominaisuuslippuja uusien ominaisuuksien asteittaiseen julkaisuun eri alueiden käyttäjille. Tämä antaa sinun seurata suorituskykyä ja korjata mahdolliset ongelmat ennen ominaisuuden julkaisemista laajemmalle yleisölle. Varmista myös, että ominaisuuslippujärjestelmäsi skaalautuu maailmanlaajuisesti ja antaa johdonmukaisia tuloksia käyttäjän sijainnista riippumatta. Ota huomioon alueelliset sääntelyrajoitukset ominaisuuksien julkaisuissa.
Edistyneet tekniikat
Middleware-funktioiden ketjuttaminen
Voit ketjuttaa useita middleware-funktioita yhteen suorittaaksesi sarjan operaatioita pyynnölle. Tämä voi olla hyödyllistä monimutkaisen logiikan jakamisessa pienempiin, hallittavampiin moduuleihin.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next();
// Ensimmäinen middleware-funktio
const token = request.cookies.get('auth_token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Toinen middleware-funktio
response.headers.set('x-middleware-custom', 'value');
return response;
}
export const config = {
matcher: ['/dashboard/:path*'],
}
Tämä esimerkki näyttää kaksi middlewarea yhdessä. Ensimmäinen suorittaa autentikoinnin ja toinen asettaa mukautetun otsakkeen.
Ympäristömuuttujien käyttö
Tallenna arkaluontoiset tiedot, kuten API-avaimet ja tietokannan tunnisteet, ympäristömuuttujiin sen sijaan, että kovakoodaisit ne middleware-funktioihisi. Tämä parantaa turvallisuutta ja helpottaa sovelluksesi konfiguraation hallintaa.
// 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'],
}
Tässä esimerkissä API_KEY
haetaan ympäristömuuttujasta.
Virheidenkäsittely
Toteuta vankka virheidenkäsittely middleware-funktioissasi estääksesi odottamattomien virheiden kaatamasta sovellustasi. Käytä try...catch
-lohkoja poikkeusten nappaamiseen ja virheiden kirjaamiseen asianmukaisesti.
// 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(); // Tai uudelleenohjaa virhesivulle
}
}
export const config = {
matcher: ['/data'],
}
Parhaat käytännöt
- Pidä middleware-funktiot kevyinä: Vältä laskennallisesti raskaiden operaatioiden suorittamista middlewaressa, sillä se voi vaikuttaa suorituskykyyn. Siirrä monimutkainen prosessointi taustatehtäviin tai erillisiin palveluihin.
- Käytä matchereita tehokkaasti: Sovella middlewarea vain niihin reitteihin, jotka sitä vaativat.
- Testaa middleware-funktiosi perusteellisesti: Kirjoita yksikkötestejä varmistaaksesi, että middleware-funktiosi toimivat oikein.
- Seuraa middlewaren suorituskykyä: Käytä seurantatyökaluja seurataksesi middleware-funktioidesi suorituskykyä ja tunnistaaksesi mahdolliset pullonkaulat.
- Dokumentoi middleware-funktiosi: Dokumentoi selkeästi kunkin middleware-funktion tarkoitus ja toiminnallisuus.
- Ota huomioon Edge-ajoympäristön rajoitukset: Ole tietoinen Edge-ajoympäristön rajoituksista, kuten Node.js-API:en puutteesta. Mukauta koodiasi vastaavasti.
Yleisten ongelmien vianmääritys
- Middleware ei suoritu: Tarkista matcherin konfiguraatio varmistaaksesi, että middlewarea sovelletaan oikeisiin reitteihin.
- Suorituskykyongelmat: Tunnista ja optimoi hitaat middleware-funktiot. Käytä profilointityökaluja suorituskyvyn pullonkaulojen paikantamiseen.
- Edge-ajoympäristön yhteensopivuus: Varmista, että koodisi on yhteensopiva Edge-ajoympäristön kanssa. Vältä käyttämästä Node.js-API:eja, joita ei tueta.
- Evästeongelmat: Varmista, että evästeet asetetaan ja haetaan oikein. Kiinnitä huomiota evästeiden attribuutteihin, kuten
domain
,path
jasecure
. - Otsakekonfliktit: Ole tietoinen mahdollisista otsakekonflikteista, kun asetat mukautettuja otsakkeita middlewaressa. Varmista, että otsakkeesi eivät korvaa olemassa olevia otsakkeita tahattomasti.
Johtopäätös
Next.js-middleware on tehokas työkalu dynaamisten ja personoitujen verkkosovellusten rakentamiseen. Hallitsemalla pyyntöjen sieppausta voit toteuttaa laajan valikoiman ominaisuuksia autentikoinnista ja auktorisoinnista uudelleenohjauksiin ja A/B-testaukseen. Noudattamalla tässä oppaassa esitettyjä parhaita käytäntöjä voit hyödyntää Next.js-middlewarea luodaksesi suorituskykyisiä, turvallisia ja skaalautuvia sovelluksia, jotka vastaavat maailmanlaajuisen käyttäjäkuntasi tarpeisiin. Hyödynnä middlewaren voima avataksesi uusia mahdollisuuksia Next.js-projekteissasi ja tarjotaksesi poikkeuksellisia käyttäjäkokemuksia.