Next.js middleware yordamida so'rovlarni o'zgartirishning ilg'or usullarini o'rganing. Mustahkam veb-ilovalar uchun murakkab marshrutlash, autentifikatsiya, A/B testlash va lokalizatsiya strategiyalarini boshqarishni o'rganing.
Next.js Middleware ning murakkab holatlari: So'rovlarni o'zgartirish naqshlarini o'zlashtirish
Next.js middleware ilovangiz marshrutlariga yetib borgunga qadar so'rovlarni ushlab turish va o'zgartirish uchun kuchli mexanizmni taqdim etadi. Bu qobiliyat oddiy autentifikatsiya tekshiruvlaridan tortib, murakkab A/B testlash stsenariylari va xalqarolashtirish strategiyalarigacha bo'lgan keng imkoniyatlarni ochadi. Biroq, middlewaredan samarali foydalanish uning murakkab holatlari va yuzaga kelishi mumkin bo'lgan muammolarni chuqur tushunishni talab qiladi. Ushbu keng qamrovli qo'llanma sizga mustahkam va unumdor Next.js ilovalarini yaratishda yordam berish uchun amaliy misollar va foydali ma'lumotlarni taqdim etgan holda so'rovlarni o'zgartirishning ilg'or naqshlarini o'rganadi.
Next.js Middleware asoslarini tushunish
Ilg'or naqshlarga sho'ng'ishdan oldin, Next.js middleware asoslarini takrorlab o'tamiz. Middleware funksiyalari so'rov bajarilishidan oldin ishga tushiriladi va sizga quyidagilarni amalga oshirish imkonini beradi:
- URL'larni qayta yozish: Foydalanuvchilarni ma'lum mezonlar asosida boshqa sahifalarga yo'naltirish.
- Foydalanuvchilarni yo'naltirish: Foydalanuvchilarni butunlay boshqa URL'larga yuborish, ko'pincha autentifikatsiya yoki avtorizatsiya maqsadlarida.
- Sarlavhalarni o'zgartirish: HTTP sarlavhalarini qo'shish, olib tashlash yoki yangilash.
- To'g'ridan-to'g'ri javob berish: Next.js marshrutlarini chetlab o'tib, to'g'ridan-to'g'ri middlewaredan javob qaytarish.
Middleware funksiyalari sizning /pages
yoki /app
katalogingizdagi (Next.js versiyangiz va sozlamalaringizga qarab) middleware.js
yoki middleware.ts
faylida joylashadi. Ular kiruvchi so'rovni ifodalovchi NextRequest
obyektini qabul qiladi va keyingi xatti-harakatni boshqarish uchun NextResponse
obyektini qaytarishi mumkin.
Misol: Oddiy autentifikatsiya Middleware'i
Ushbu misol oddiy autentifikatsiya tekshiruvini ko'rsatadi. Agar foydalanuvchi autentifikatsiyadan o'tmagan bo'lsa (masalan, cookie'da yaroqli token bo'lmasa), u login sahifasiga yo'naltiriladi.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const authToken = request.cookies.get('authToken')
if (!authToken) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/protected/:path*'],
}
Ushbu middleware faqat /protected/:path*
ga mos keladigan marshrutlar uchun ishlaydi. U authToken
cookie'si mavjudligini tekshiradi. Agar cookie mavjud bo'lmasa, foydalanuvchi /login
sahifasiga yo'naltiriladi. Aks holda, so'rov NextResponse.next()
yordamida odatdagidek davom etishiga ruxsat beriladi.
So'rovlarni o'zgartirishning ilg'or naqshlari
Endi, Next.js middleware'ning haqiqiy kuchini namoyish etadigan ba'zi ilg'or so'rovlarni o'zgartirish naqshlarini ko'rib chiqamiz.
1. Cookie'lar yordamida A/B testlash
A/B testlash foydalanuvchi tajribasini optimallashtirish uchun muhim usuldir. Middleware foydalanuvchilarni ilovangizning turli variantlariga tasodifiy ravishda tayinlash va ularning xatti-harakatlarini kuzatish uchun ishlatilishi mumkin. Ushbu naqsh foydalanuvchiga tayinlangan variantni saqlab qolish uchun cookie'larga tayanadi.
Misol: Bosh sahifani A/B testlash
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const VARIANT_A = 'variantA'
const VARIANT_B = 'variantB'
export function middleware(request: NextRequest) {
let variant = request.cookies.get('variant')?.value
if (!variant) {
// Randomly assign a variant
variant = Math.random() < 0.5 ? VARIANT_A : VARIANT_B
const response = NextResponse.next()
response.cookies.set('variant', variant)
return response
}
if (variant === VARIANT_A) {
return NextResponse.rewrite(new URL('/variant-a', request.url))
} else if (variant === VARIANT_B) {
return NextResponse.rewrite(new URL('/variant-b', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/'],
}
Ushbu misolda, foydalanuvchi birinchi marta asosiy yo'lga (/
) tashrif buyurganida, middleware ularni tasodifiy ravishda variantA
yoki variantB
ga tayinlaydi. Bu variant cookie'da saqlanadi. Xuddi shu foydalanuvchidan keyingi so'rovlar ularga tayinlangan variantga qarab /variant-a
yoki /variant-b
ga qayta yoziladi. Bu sizga turli xil bosh sahifalarni taqdim etish va qaysi biri yaxshiroq ishlashini kuzatish imkonini beradi. Next.js ilovangizda /variant-a
va /variant-b
uchun marshrutlar belgilanganligiga ishonch hosil qiling.
Global mulohazalar: A/B testlashni amalga oshirayotganda, mintaqaviy farqlarni hisobga oling. Shimoliy Amerikada yaxshi ishlaydigan dizayn Osiyoda unchalik samarali bo'lmasligi mumkin. Muayyan mintaqalarga moslashtirilgan A/B testini yaratish uchun geolokatsiya ma'lumotlaridan (IP-manzilni aniqlash yoki foydalanuvchi afzalliklari orqali olingan) foydalanishingiz mumkin.
2. URL'larni qayta yozish orqali lokalizatsiya (i18n)
Xalqarolashtirish (i18n) global auditoriyaga erishish uchun zarurdir. Middleware foydalanuvchining afzal ko'rgan tilini avtomatik ravishda aniqlash va ularni saytingizning tegishli lokalizatsiya qilingan versiyasiga yo'naltirish uchun ishlatilishi mumkin.
Misol: `Accept-Language` sarlavhasiga asoslanib yo'naltirish
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const SUPPORTED_LANGUAGES = ['en', 'fr', 'es', 'de']
const DEFAULT_LANGUAGE = 'en'
function getPreferredLanguage(request: NextRequest): string {
const acceptLanguage = request.headers.get('accept-language')
if (!acceptLanguage) {
return DEFAULT_LANGUAGE
}
const languages = acceptLanguage.split(',').map((lang) => lang.split(';')[0].trim())
for (const lang of languages) {
if (SUPPORTED_LANGUAGES.includes(lang)) {
return lang
}
}
return DEFAULT_LANGUAGE
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname
// Check if there's an existing locale in the pathname
if (
SUPPORTED_LANGUAGES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
)
) {
return NextResponse.next()
}
const preferredLanguage = getPreferredLanguage(request)
return NextResponse.redirect(
new URL(`/${preferredLanguage}${pathname}`, request.url)
)
}
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico).*)'
],
}
Ushbu middleware so'rovdan Accept-Language
sarlavhasini oladi va foydalanuvchining afzal ko'rgan tilini aniqlaydi. Agar URLda allaqachon til prefiksi (masalan, /en/about
) bo'lmasa, middleware foydalanuvchini tegishli lokalizatsiya qilingan URLga (masalan, fransuz tili uchun /fr/about
) yo'naltiradi. Turli tillar uchun `/pages` yoki `/app` katalogingizda mos papka tuzilmasi mavjudligiga ishonch hosil qiling. Masalan, sizga `/pages/en/about.js` va `/pages/fr/about.js` fayllari kerak bo'ladi.
Global mulohazalar: i18n tatbiqingiz o'ngdan chapga yoziladigan tillarni (masalan, arab, ibroniy) to'g'ri ishlashiga ishonch hosil qiling. Shuningdek, foydalanuvchilaringizga yaqinroq serverlardan lokalizatsiya qilingan aktivlarni taqdim etish va unumdorlikni oshirish uchun Kontent Yetkazib Berish Tarmog'idan (CDN) foydalanishni o'ylab ko'ring.
3. Xususiyat bayroqlari (Feature Flags)
Xususiyat bayroqlari ilovangizda yangi kodni joylashtirmasdan turib xususiyatlarni yoqish yoki o'chirish imkonini beradi. Bu ayniqsa yangi xususiyatlarni bosqichma-bosqich joriy etish yoki xususiyatlarni ishlab chiqarish muhitida sinab ko'rish uchun foydalidir. Middleware xususiyat bayrog'ining holatini tekshirish va so'rovni shunga mos ravishda o'zgartirish uchun ishlatilishi mumkin.
Misol: Beta xususiyatni yoqish
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const BETA_FEATURE_ENABLED = process.env.BETA_FEATURE_ENABLED === 'true'
export function middleware(request: NextRequest) {
if (BETA_FEATURE_ENABLED && request.nextUrl.pathname.startsWith('/new-feature')) {
return NextResponse.next()
}
// Optionally redirect to a "feature unavailable" page
return NextResponse.rewrite(new URL('/feature-unavailable', request.url))
}
export const config = {
matcher: ['/new-feature/:path*'],
}
Ushbu middleware BETA_FEATURE_ENABLED
muhit o'zgaruvchisining qiymatini tekshiradi. Agar u true
ga o'rnatilgan bo'lsa va foydalanuvchi /new-feature
ostidagi marshrutga kirishga harakat qilsa, so'rovning davom etishiga ruxsat beriladi. Aks holda, foydalanuvchi /feature-unavailable
sahifasiga yo'naltiriladi. Turli muhitlar (ishlab chiqish, sinov, ishlab chiqarish) uchun muhit o'zgaruvchilarini to'g'ri sozlashni unutmang.
Global mulohazalar: Xususiyat bayroqlaridan foydalanganda, barcha mintaqalardagi qoidalarga mos kelmasligi mumkin bo'lgan xususiyatlarni yoqishning huquqiy oqibatlarini hisobga oling. Masalan, ma'lumotlar maxfiyligi bilan bog'liq xususiyatlar ba'zi mamlakatlarda o'chirib qo'yilishi kerak bo'lishi mumkin.
4. Qurilmani aniqlash va moslashuvchan marshrutlash
Zamonaviy veb-ilovalar sezgir bo'lishi va turli ekran o'lchamlari va qurilma imkoniyatlariga moslashishi kerak. Middleware foydalanuvchining qurilma turini aniqlash va ularni saytingizning optimallashtirilgan versiyalariga yo'naltirish uchun ishlatilishi mumkin.
Misol: Mobil foydalanuvchilarni mobil uchun optimallashtirilgan subdomenga yo'naltirish
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { device } from 'detection'
export function middleware(request: NextRequest) {
const userAgent = request.headers.get('user-agent')
if (userAgent) {
const deviceType = device(userAgent)
if (deviceType.type === 'phone') {
const mobileUrl = new URL(request.url)
mobileUrl.hostname = 'm.example.com'
return NextResponse.redirect(mobileUrl)
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/'],
}
Ushbu misol foydalanuvchining qurilma turini User-Agent
sarlavhasi asosida aniqlash uchun `detection` kutubxonasidan foydalanadi. Agar foydalanuvchi mobil telefonda bo'lsa, u m.example.com
subdomeniga yo'naltiriladi (u yerda saytingizning mobil uchun optimallashtirilgan versiyasi joylashtirilgan deb faraz qilinadi). `detection` paketini o'rnatishni unutmang: `npm install detection`.
Global mulohazalar: Qurilmani aniqlash mantig'ingiz qurilmalardan foydalanishdagi mintaqaviy farqlarni hisobga olishiga ishonch hosil qiling. Masalan, oddiy funksiyali telefonlar ba'zi rivojlanayotgan mamlakatlarda hali ham keng tarqalgan. Yana-da mustahkam yechim uchun User-Agent'ni aniqlash va sezgir dizayn usullarini birgalikda qo'llashni o'ylab ko'ring.
5. So'rov sarlavhalarini boyitish
Middleware ilova marshrutlaringiz tomonidan qayta ishlanishidan oldin so'rov sarlavhalariga ma'lumot qo'shishi mumkin. Bu foydalanuvchi rollari, autentifikatsiya holati yoki so'rov identifikatorlari kabi ilovangiz mantig'i tomonidan ishlatilishi mumkin bo'lgan maxsus metama'lumotlarni qo'shish uchun foydalidir.
Misol: So'rov identifikatorini qo'shish
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
export function middleware(request: NextRequest) {
const requestId = uuidv4()
const response = NextResponse.next()
response.headers.set('x-request-id', requestId)
return response
}
export const config = {
matcher: ['/api/:path*'], // Only apply to API routes
}
Ushbu middleware uuid
kutubxonasi yordamida noyob so'rov identifikatorini yaratadi va uni x-request-id
sarlavhasiga qo'shadi. Keyinchalik bu identifikator jurnallash (logging), kuzatish va nosozliklarni tuzatish maqsadlarida ishlatilishi mumkin. `uuid` paketini o'rnatishni unutmang: `npm install uuid`.
Global mulohazalar: Maxsus sarlavhalarni qo'shayotganda, sarlavha hajmi cheklovlaridan ehtiyot bo'ling. Bu cheklovlardan oshib ketish kutilmagan xatolarga olib kelishi mumkin. Shuningdek, sarlavhalarga qo'shilgan har qanday maxfiy ma'lumot to'g'ri himoyalanganligiga ishonch hosil qiling, ayniqsa ilovangiz teskari proksi yoki CDN orqasida bo'lsa.
6. Xavfsizlikni kuchaytirish: So'rovlarni cheklash (Rate Limiting)
Middleware so'rovlarni cheklashni amalga oshirish orqali zararli hujumlarga qarshi birinchi himoya chizig'i bo'lib xizmat qilishi mumkin. Bu mijozning ma'lum bir vaqt oralig'ida qila oladigan so'rovlar sonini cheklash orqali suiiste'mol qilishning oldini oladi.
Misol: Oddiy ombor yordamida asosiy so'rovlarni cheklash
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const requestCounts: { [ip: string]: number } = {}
const WINDOW_SIZE_MS = 60000; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 100;
export function middleware(request: NextRequest) {
const clientIP = request.ip || '127.0.0.1' // Get client IP, default to localhost for local testing
if (!requestCounts[clientIP]) {
requestCounts[clientIP] = 0;
}
requestCounts[clientIP]++;
if (requestCounts[clientIP] > MAX_REQUESTS_PER_WINDOW) {
return new NextResponse(
JSON.stringify({ message: 'Too many requests' }),
{ status: 429, headers: { 'Content-Type': 'application/json' } }
);
}
// Reset count after window
setTimeout(() => {
requestCounts[clientIP]--;
if (requestCounts[clientIP] <= 0) {
delete requestCounts[clientIP];
}
}, WINDOW_SIZE_MS);
return NextResponse.next();
}
export const config = {
matcher: ['/api/:path*'], // Apply to all API routes
}
Ushbu misol har bir IP-manzildan kelayotgan so'rovlar sonini kuzatish uchun oddiy xotiradagi omborni (requestCounts
) saqlaydi. Agar mijoz WINDOW_SIZE_MS
ichida MAX_REQUESTS_PER_WINDOW
dan oshib ketsa, middleware 429 Too Many Requests
xatosini qaytaradi. Muhim: Bu soddalashtirilgan misol bo'lib, ishlab chiqarish muhitlari uchun mos kelmaydi, chunki u kengaytirilmaydi va xizmat ko'rsatishni rad etish (denial-of-service) hujumlariga zaif. Ishlab chiqarishda foydalanish uchun Redis yoki maxsus so'rovlarni cheklash xizmati kabi yanada mustahkam yechimni ko'rib chiqing.
Global mulohazalar: So'rovlarni cheklash strategiyalari ilovangizning o'ziga xos xususiyatlariga va foydalanuvchilaringizning geografik taqsimotiga moslashtirilishi kerak. Turli mintaqalar yoki foydalanuvchi segmentlari uchun turli xil so'rov cheklovlarini qo'llashni o'ylab ko'ring.
Murakkab holatlar va yuzaga kelishi mumkin bo'lgan muammolar
Middleware kuchli vosita bo'lsa-da, uning cheklovlari va yuzaga kelishi mumkin bo'lgan muammolardan xabardor bo'lish muhim:
- Unumdorlikka ta'siri: Middleware har bir so'rovga qo'shimcha yuklama qo'shadi. Middleware'da hisoblash jihatidan qimmat operatsiyalarni bajarishdan saqlaning, chunki bu unumdorlikka sezilarli ta'sir qilishi mumkin. Har qanday unumdorlik muammolarini aniqlash va optimallashtirish uchun middleware'ingizni profillang.
- Murakkablik: Middleware'dan haddan tashqari ko'p foydalanish ilovangizni tushunish va saqlashni qiyinlashtirishi mumkin. Middleware'dan oqilona foydalaning va har bir middleware funksiyasi aniq va yaxshi belgilangan maqsadga ega ekanligiga ishonch hosil qiling.
- Testlash: Middleware'ni testlash qiyin bo'lishi mumkin, chunki u HTTP so'rovlarini simulyatsiya qilishni va natijaviy javoblarni tekshirishni talab qiladi. Middleware funksiyalaringiz uchun keng qamrovli birlik va integratsiya testlarini yozish uchun Jest va Supertest kabi vositalardan foydalaning.
- Cookie'larni boshqarish: Middleware'da cookie'larni o'rnatayotganda ehtiyot bo'ling, chunki bu keshlash xatti-harakatiga ta'sir qilishi mumkin. Cookie'ga asoslangan keshlashning oqibatlarini tushunishingizga va keshlash sarlavhalarini shunga mos ravishda sozlashingizga ishonch hosil qiling.
- Muhit o'zgaruvchilari: Middleware'da ishlatiladigan barcha muhit o'zgaruvchilari turli muhitlar (ishlab chiqish, sinov, ishlab chiqarish) uchun to'g'ri sozlanganligiga ishonch hosil qiling. Muhit o'zgaruvchilarini boshqarish uchun Dotenv kabi vositadan foydalaning.
- Chekka funksiyalari cheklovlari: Unutmangki, middleware Chekka funksiyalari (Edge Functions) sifatida ishlaydi, ularning bajarilish vaqti, xotira hajmi va paketlangan kod hajmiga cheklovlar mavjud. Middleware funksiyalaringizni yengil va samarali saqlang.
Next.js Middleware'dan foydalanish bo'yicha eng yaxshi amaliyotlar
Next.js middleware'ning afzalliklarini maksimal darajada oshirish va yuzaga kelishi mumkin bo'lgan muammolarni oldini olish uchun quyidagi eng yaxshi amaliyotlarga rioya qiling:
- Sodda tuting: Har bir middleware funksiyasi yagona, yaxshi belgilangan mas'uliyatga ega bo'lishi kerak. Bir nechta vazifalarni bajaradigan haddan tashqari murakkab middleware funksiyalarini yaratishdan saqlaning.
- Unumdorlik uchun optimallashtiring: Unumdorlik muammolarini oldini olish uchun middleware'da bajariladigan qayta ishlash hajmini minimallashtiring. Takroriy hisob-kitoblarga bo'lgan ehtiyojni kamaytirish uchun keshlash strategiyalaridan foydalaning.
- Puxta sinovdan o'tkazing: Middleware funksiyalaringiz kutilganidek ishlashiga ishonch hosil qilish uchun keng qamrovli birlik va integratsiya testlarini yozing.
- Kodingizni hujjatlashtiring: Saqlashni yaxshilash uchun har bir middleware funksiyasining maqsadi va funksionalligini aniq hujjatlashtiring.
- Ilovangizni kuzatib boring: Middleware funksiyalaringizning unumdorligi va xatolik darajasini kuzatish uchun monitoring vositalaridan foydalaning.
- Bajarilish tartibini tushuning: Middleware funksiyalarining bajarilish tartibidan xabardor bo'ling, chunki bu ularning xatti-harakatiga ta'sir qilishi mumkin.
- Muhit o'zgaruvchilaridan oqilona foydalaning: Middleware funksiyalaringizni turli muhitlar uchun sozlashda muhit o'zgaruvchilaridan foydalaning.
Xulosa
Next.js middleware so'rovlarni o'zgartirish va ilovangiz xatti-harakatlarini chekkada moslashtirishning kuchli usulini taklif etadi. Ushbu qo'llanmada muhokama qilingan ilg'or so'rovlarni o'zgartirish naqshlarini tushunib, siz mustahkam, unumdor va global miqyosda ishlay oladigan Next.js ilovalarini yarata olasiz. Middleware funksiyalaringiz ishonchli va saqlanadigan bo'lishini ta'minlash uchun murakkab holatlar va yuzaga kelishi mumkin bo'lgan muammolarni diqqat bilan ko'rib chiqishni va yuqorida keltirilgan eng yaxshi amaliyotlarga rioya qilishni unutmang. Ajoyib foydalanuvchi tajribalarini yaratish va veb-ilovalar uchun yangi imkoniyatlarni ochish uchun middleware kuchidan foydalaning.