Suomi

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:

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:

Response-objekti

Middleware-funktiot palauttavat Response-objektin hallitakseen pyynnön lopputulosta. Voit käyttää seuraavia vastauksia:

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

Yleisten ongelmien vianmääritys

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.

Next.js-middleware: Pyyntöjen sieppauksen hallinta dynaamisissa sovelluksissa | MLOG