فارسی

تکنیک‌های پیشرفته اصلاح درخواست با میدل‌ور Next.js را کاوش کنید. مدیریت مسیریابی پیچیده، احراز هویت، تست A/B و استراتژی‌های محلی‌سازی برای اپلیکیشن‌های وب قوی را بیاموزید.

موارد خاص میدل‌ور Next.js: تسلط بر الگوهای اصلاح درخواست

میدل‌ور Next.js یک مکانیزم قدرتمند برای رهگیری و اصلاح درخواست‌ها قبل از رسیدن به مسیرهای اپلیکیشن شما فراهم می‌کند. این قابلیت طیف گسترده‌ای از امکانات را باز می‌کند، از بررسی‌های ساده احراز هویت گرفته تا سناریوهای پیچیده تست A/B و استراتژی‌های بین‌المللی‌سازی. با این حال، استفاده مؤثر از میدل‌ور نیازمند درک عمیق از موارد خاص و مشکلات احتمالی آن است. این راهنمای جامع به بررسی الگوهای پیشرفته اصلاح درخواست می‌پردازد و مثال‌های عملی و بینش‌های کاربردی را برای کمک به شما در ساخت اپلیکیشن‌های Next.js قوی و با عملکرد بالا ارائه می‌دهد.

درک مبانی میدل‌ور Next.js

قبل از پرداختن به الگوهای پیشرفته، بیایید مبانی میدل‌ور Next.js را مرور کنیم. توابع میدل‌ور قبل از تکمیل یک درخواست اجرا می‌شوند و به شما امکان می‌دهند:

توابع میدل‌ور در فایل middleware.js یا middleware.ts در دایرکتوری /pages یا /app شما قرار دارند (بسته به نسخه و تنظیمات Next.js شما). آنها یک شیء NextRequest را که نماینده درخواست ورودی است دریافت می‌کنند و می‌توانند یک شیء NextResponse را برای کنترل رفتار بعدی برگردانند.

مثال: میدل‌ور احراز هویت پایه

این مثال یک بررسی احراز هویت ساده را نشان می‌دهد. اگر کاربر احراز هویت نشده باشد (مثلاً توکن معتبری در کوکی وجود نداشته باشد)، به صفحه ورود هدایت می‌شود.


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*'],
}

این میدل‌ور فقط برای مسیرهایی اجرا می‌شود که با /protected/:path* مطابقت دارند. این میدل‌ور وجود کوکی authToken را بررسی می‌کند. اگر کوکی وجود نداشته باشد، کاربر به صفحه /login ریدایرکت می‌شود. در غیر این صورت، با استفاده از NextResponse.next() اجازه داده می‌شود که درخواست به طور عادی ادامه یابد.

الگوهای پیشرفته اصلاح درخواست

اکنون، بیایید برخی از الگوهای پیشرفته اصلاح درخواست را که قدرت واقعی میدل‌ور Next.js را به نمایش می‌گذارند، بررسی کنیم.

۱. تست A/B با استفاده از کوکی‌ها

تست A/B یک تکنیک حیاتی برای بهینه‌سازی تجربیات کاربری است. میدل‌ور می‌تواند برای تخصیص تصادفی کاربران به نسخه‌های مختلف اپلیکیشن شما و ردیابی رفتار آنها استفاده شود. این الگو برای حفظ نسخه تخصیص داده شده به کاربر به کوکی‌ها متکی است.

مثال: تست A/B یک صفحه فرود


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: ['/'],
}

در این مثال، زمانی که یک کاربر برای اولین بار از مسیر ریشه (/) بازدید می‌کند، میدل‌ور به طور تصادفی او را به یکی از نسخه‌های variantA یا variantB اختصاص می‌دهد. این نسخه در یک کوکی ذخیره می‌شود. درخواست‌های بعدی از همان کاربر بسته به نسخه تخصیص داده شده به آنها، به /variant-a یا /variant-b بازنویسی می‌شوند. این به شما امکان می‌دهد صفحات فرود مختلفی را ارائه دهید و ردیابی کنید که کدام یک عملکرد بهتری دارد. اطمینان حاصل کنید که مسیرهایی برای /variant-a و /variant-b در اپلیکیشن Next.js خود تعریف کرده‌اید.

ملاحظات جهانی: هنگام انجام تست A/B، تغییرات منطقه‌ای را در نظر بگیرید. طرحی که در آمریکای شمالی طنین‌انداز می‌شود ممکن است در آسیا به همان اندازه مؤثر نباشد. می‌توانید از داده‌های موقعیت جغرافیایی (که از طریق جستجوی آدرس IP یا ترجیحات کاربر به دست می‌آید) برای تطبیق تست A/B با مناطق خاص استفاده کنید.

۲. محلی‌سازی (i18n) با بازنویسی URL

بین‌المللی‌سازی (i18n) برای دستیابی به مخاطبان جهانی ضروری است. میدل‌ور می‌تواند برای تشخیص خودکار زبان ترجیحی کاربر و هدایت آنها به نسخه محلی‌سازی شده مناسب سایت شما استفاده شود.

مثال: ریدایرکت بر اساس هدر `Accept-Language`


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).*)'
  ],
}

این میدل‌ور هدر Accept-Language را از درخواست استخراج کرده و زبان ترجیحی کاربر را تعیین می‌کند. اگر URL از قبل حاوی پیشوند زبان نباشد (مثلاً /en/about)، میدل‌ور کاربر را به URL محلی‌سازی شده مناسب (مثلاً /fr/about برای زبان فرانسه) ریدایرکت می‌کند. اطمینان حاصل کنید که ساختار پوشه مناسبی در دایرکتوری `/pages` یا `/app` خود برای زبان‌های مختلف دارید. برای مثال، شما به یک فایل `/pages/en/about.js` و `/pages/fr/about.js` نیاز خواهید داشت.

ملاحظات جهانی: اطمینان حاصل کنید که پیاده‌سازی i18n شما به درستی از زبان‌های راست به چپ (مانند عربی، عبری) پشتیبانی می‌کند. همچنین، استفاده از یک شبکه تحویل محتوا (CDN) را برای ارائه دارایی‌های محلی‌سازی شده از سرورهای نزدیک‌تر به کاربران خود در نظر بگیرید تا عملکرد بهبود یابد.

۳. پرچم‌های ویژگی (Feature Flags)

پرچم‌های ویژگی به شما امکان می‌دهند ویژگی‌ها را در اپلیکیشن خود بدون استقرار کد جدید فعال یا غیرفعال کنید. این امر به ویژه برای عرضه تدریجی ویژگی‌های جدید یا برای آزمایش ویژگی‌ها در محیط پروداکشن مفید است. میدل‌ور می‌تواند برای بررسی وضعیت یک پرچم ویژگی و اصلاح درخواست بر اساس آن استفاده شود.

مثال: فعال‌سازی یک ویژگی بتا


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*'],
}

این میدل‌ور مقدار متغیر محیطی BETA_FEATURE_ENABLED را بررسی می‌کند. اگر این مقدار روی true تنظیم شده باشد و کاربر در تلاش برای دسترسی به مسیری تحت /new-feature باشد، درخواست اجازه عبور پیدا می‌کند. در غیر این صورت، کاربر به صفحه /feature-unavailable ریدایرکت می‌شود. به یاد داشته باشید که متغیرهای محیطی را برای محیط‌های مختلف (توسعه، استیجینگ، پروداکشن) به درستی پیکربندی کنید.

ملاحظات جهانی: هنگام استفاده از پرچم‌های ویژگی، پیامدهای قانونی فعال‌سازی ویژگی‌هایی را که ممکن است با مقررات همه مناطق سازگار نباشند، در نظر بگیرید. به عنوان مثال، ویژگی‌های مربوط به حریم خصوصی داده‌ها ممکن است نیاز به غیرفعال شدن در برخی کشورها داشته باشند.

۴. تشخیص دستگاه و مسیریابی تطبیقی

اپلیکیشن‌های وب مدرن باید واکنش‌گرا باشند و با اندازه‌های مختلف صفحه نمایش و قابلیت‌های دستگاه‌ها سازگار شوند. میدل‌ور می‌تواند برای تشخیص نوع دستگاه کاربر و هدایت آنها به نسخه‌های بهینه‌سازی شده سایت شما استفاده شود.

مثال: ریدایرکت کاربران موبایل به یک زیردامنه بهینه‌سازی شده برای موبایل


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: ['/'],
}

این مثال از کتابخانه `detection` برای تعیین نوع دستگاه کاربر بر اساس هدر User-Agent استفاده می‌کند. اگر کاربر از تلفن همراه استفاده می‌کند، به زیردامنه m.example.com ریدایرکت می‌شود (با فرض اینکه شما یک نسخه بهینه‌سازی شده برای موبایل از سایت خود را در آنجا میزبانی می‌کنید). به یاد داشته باشید که بسته `detection` را نصب کنید: `npm install detection`.

ملاحظات جهانی: اطمینان حاصل کنید که منطق تشخیص دستگاه شما تغییرات منطقه‌ای در استفاده از دستگاه‌ها را در نظر می‌گیرد. به عنوان مثال، تلفن‌های ساده (feature phones) هنوز در برخی از کشورهای در حال توسعه رایج هستند. برای یک راه حل قوی‌تر، ترکیبی از تشخیص User-Agent و تکنیک‌های طراحی واکنش‌گرا را در نظر بگیرید.

۵. غنی‌سازی هدر درخواست

میدل‌ور می‌تواند اطلاعاتی را قبل از پردازش توسط مسیرهای اپلیکیشن شما به هدرهای درخواست اضافه کند. این کار برای افزودن متادیتای سفارشی مانند نقش‌های کاربر، وضعیت احراز هویت یا شناسه‌های درخواست که می‌تواند توسط منطق اپلیکیشن شما استفاده شود، مفید است.

مثال: افزودن شناسه درخواست


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
}

این میدل‌ور با استفاده از کتابخانه uuid یک شناسه درخواست منحصر به فرد تولید می‌کند و آن را به هدر x-request-id اضافه می‌کند. سپس این شناسه می‌تواند برای اهداف لاگ‌گیری، ردیابی و دیباگ استفاده شود. به یاد داشته باشید که بسته `uuid` را نصب کنید: `npm install uuid`.

ملاحظات جهانی: هنگام افزودن هدرهای سفارشی، به محدودیت‌های اندازه هدر توجه داشته باشید. فراتر رفتن از این محدودیت‌ها می‌تواند منجر به خطاهای غیرمنتظره شود. همچنین، اطمینان حاصل کنید که هرگونه اطلاعات حساس اضافه شده به هدرها به درستی محافظت می‌شود، به خصوص اگر اپلیکیشن شما پشت یک پروکسی معکوس یا CDN قرار دارد.

۶. بهبودهای امنیتی: محدودسازی نرخ درخواست (Rate Limiting)

میدل‌ور می‌تواند با پیاده‌سازی محدودسازی نرخ درخواست به عنوان اولین خط دفاعی در برابر حملات مخرب عمل کند. این کار با محدود کردن تعداد درخواست‌هایی که یک کلاینت می‌تواند در یک بازه زمانی مشخص انجام دهد، از سوءاستفاده جلوگیری می‌کند.

مثال: محدودسازی نرخ درخواست پایه با استفاده از یک ذخیره‌ساز ساده


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
}

این مثال یک ذخیره‌ساز ساده در حافظه (requestCounts) را برای ردیابی تعداد درخواست‌ها از هر آدرس IP نگهداری می‌کند. اگر یک کلاینت از MAX_REQUESTS_PER_WINDOW در بازه زمانی WINDOW_SIZE_MS فراتر رود، میدل‌ور یک خطای 429 Too Many Requests برمی‌گرداند. مهم: این یک مثال ساده‌سازی شده است و برای محیط‌های پروداکشن مناسب نیست زیرا مقیاس‌پذیر نیست و در برابر حملات محروم‌سازی از سرویس آسیب‌پذیر است. برای استفاده در پروداکشن، از یک راه حل قوی‌تر برای محدودسازی نرخ درخواست مانند Redis یا یک سرویس اختصاصی محدودسازی نرخ استفاده کنید.

ملاحظات جهانی: استراتژی‌های محدودسازی نرخ درخواست باید متناسب با ویژگی‌های خاص اپلیکیشن شما و توزیع جغرافیایی کاربران شما تنظیم شوند. استفاده از محدودیت‌های نرخ متفاوت برای مناطق مختلف یا بخش‌های کاربری مختلف را در نظر بگیرید.

موارد خاص و مشکلات احتمالی

در حالی که میدل‌ور یک ابزار قدرتمند است، آگاهی از محدودیت‌ها و مشکلات احتمالی آن ضروری است:

بهترین شیوه‌ها برای استفاده از میدل‌ور Next.js

برای به حداکثر رساندن مزایای میدل‌ور Next.js و جلوگیری از مشکلات احتمالی، این بهترین شیوه‌ها را دنبال کنید:

نتیجه‌گیری

میدل‌ور Next.js راهی قدرتمند برای اصلاح درخواست‌ها و سفارشی‌سازی رفتار اپلیکیشن شما در لبه (edge) ارائه می‌دهد. با درک الگوهای پیشرفته اصلاح درخواست که در این راهنما مورد بحث قرار گرفت، می‌توانید اپلیکیشن‌های Next.js قوی، با عملکرد بالا و آگاه از مسائل جهانی بسازید. به یاد داشته باشید که موارد خاص و مشکلات احتمالی را با دقت در نظر بگیرید و بهترین شیوه‌های ذکر شده در بالا را دنبال کنید تا اطمینان حاصل کنید که توابع میدل‌ور شما قابل اعتماد و قابل نگهداری هستند. از قدرت میدل‌ور برای ایجاد تجربیات کاربری استثنایی و باز کردن امکانات جدید برای اپلیکیشن‌های وب خود استقبال کنید.