برخی از دادهها در برنامههای وب تنها زمانی مشخص میشوند که کاربر یک درخواست (Request) واقعی به سرور ارسال کند. به ابزارهایی که این اطلاعات لحظهای را در اختیار ما قرار میدهند، Runtime APIs میگویند. این ابزارها عبارتند از:
cookies: مدیریت و خواندن دیتای کوکیهای کاربر.
headers: دسترسی به هدرهای درخواست (مثل User-Agent).
searchParams: پارامترهای کوئری در آدرس مرورگر (مانند ?page=2).
params: پارامترهای پویا در مسیر روتر (مثلاً آیدی موجود در /products/[id])؛ مگر اینکه از قبل مقدار متناظر آن با generateStaticParams تولید شده باشد.
چرا کامپوننتهای متصل به Runtime APIها به <Suspense> نیاز دارند؟
چطور مقادیر زمان اجرا را به عنوان آرگومان به توابع کششده پاس دهیم؟
تفاوت رفتاری کش در محیطهای Memory (درون حافظه) و محیطهای بدون سرور (Serverless) چیست؟
<Suspense> برای ابزارهای زمان اجراوقتی یک کامپوننت به دیتای زمان اجرا (مثل کوکیها) متصل میشود، ساختار آن دیگر نمیتواند در مرحله کامپایل به صورت کاملاً استاتیک ذخیره شود، چون پاسخ آن به اطلاعات لحظهای کاربر وابسته است.
برای اینکه سرعت لود اولیه صفحه (پوسته استاتیک) حفظ شود، حتماً باید این کامپوننتها را درون تگ <Suspense> قرار دهید. با این کار، ریآکت ابتدا بخشهای ثابت صفحه را رندر کرده و به مرورگر میفرستد، سپس به محض خوانده شدن دیتای زمان اجرا روی سرور، خروجی نهایی کامپوننت را جایگزین لودینگ میکند:
// page.tsx
import { cookies } from 'next/headers'
import { Suspense } from 'react'
async function UserGreeting() {
// دسترسی به API زمان اجرا (نیاز به انتظار دارد)
const cookieStore = await cookies()
const theme = cookieStore.get('theme')?.value || 'light'
return <p>تم انتخابی شما: {theme}</p>
}
export default function Page() {
return (
<>
<h1>داشبورد کاربری</h1>
{/* کامپوننت وابسته به رویدادهای زمان اجرا در تگ Suspense قرار میگیرد */}
<Suspense fallback={<p>در حال بارگذاری تنظیمات...</p>}>
<UserGreeting />
</Suspense>
</>
)
}
یک الگوی فوقالعاده کاربردی در Next.js این است که دیتای داینامیک زمان اجرا (مثل توکن یا آیدی جلسه کاربر) را استخراج کرده و آن را به عنوان ورودی (prop یا آرگومان) به یک تابع یا کامپوننت کششده بفرستید.
همانطور که در درس قبل اشاره شد، آرگومانهای ورودی یک تابع کششده به صورت خودکار به کلید کش (Cache Key) تبدیل میشوند. بنابراین، اگر کاربر دیگری با یک شناسه متفاوت وارد شود، Next.js یک حافظه کش مجزا برای او ساخته و اطلاعات کاربران با هم تداخل پیدا نمیکند:
به این ساختار تفکیکشده نگاه کنید:
// app/profile/page.tsx
import { cookies } from 'next/headers'
import { Suspense } from 'react'
export default function Page() {
return (
<Suspense fallback={<div>در حال دریافت اطلاعات پروفایل...</div>}>
<ProfileContent />
</Suspense>
)
}
// ۱. این کامپوننت کَش نمیشود و مستقیماً اطلاعات زمان اجرا را میخواند
async function ProfileContent() {
const session = (await cookies()).get('session')?.value
// مقدار داینامیک به عنوان پروپ به کامپوننت کششده فرستاده میشود
return <CachedContent sessionId={session} />
}
// ۲. این کامپوننت به صورت پارامتریک کَش میشود
async function CachedContent({ sessionId }: { sessionId: string }) {
'use cache'
// متغیر sessionId به بخشی از کلید کش تبدیل میشود
const data = await fetchUserData(sessionId)
return <div>{data}</div>
}
در لحظه درخواست (Request time):
ریآکت بررسی میکند که آیا قبلاً درخواستی با همین sessionId دقیق پردازش و کش شده است یا خیر.
اگر دیتای متناظر در صف کش موجود باشد، فوراً و بدون اجرای کدهای داخلی، خروجی کششده را تحویل میدهد.
اگر وجود نداشته باشد (Cache Miss)، کدهای تابع CachedContent برای اولین بار اجرا شده و نتیجه برای درخواستهای بعدی با همین sessionId ذخیره میشود.
به صورت پیشفرض، دایرکتیو "use cache" دیتای شما را در حافظه موقت رم سرور (In-memory) ذخیره میکند. این موضوع در سرورهای سنتی (مثل VPSها یا داکر) عالی کار میکند، اما در محیطهای بدون سرور (Serverless مانند Vercel یا AWS Lambda) چالشبرانگیز است؛ چرا که در این سرویسها، حافظه رم سرور پس از اتمام درخواست کاربر پایداری ندارد و مرتباً ریست میشود. در نتیجه، کامپوننت شما ممکن است در هر درخواست مجدداً از نو ارزیابی و اجرا شود.
اگر در لایه سرورلس کار میکنید و نیاز به یک کش پایدار، ماندگار و مشترک بین تمام نمونههای سرور دارید، باید کش خود را به حالت توزیعشده (Remote) تغییر دهید تا اطلاعات در یک پایگاه داده کش خارجی (مثل Redis) ذخیره شوند:
async function CachedContent({ sessionId }) {
'use cache: remote' // استفاده از کش توزیعشده و پایدار به جای حافظه موقت رم
// ...
}
ابزارهایی مثل cookies، headers و searchParams فقط در زمان درخواست کاربر مقداردهی میشوند.
کامپوننتهایی که به این APIها متصل هستند را برای حفظ ساختار استاتیک لود اولیه صفحه، حتماً در <Suspense> قرار دهید.
مقادیر استخراجشده از زمان اجرا وقتی به توابع کششده پاس داده شوند، کلیدهای کش اختصاصی و تفکیکشده (Parameterized) ایجاد میکنند.
سیستم کش پیشفرض Next.js مبتنی بر حافظه رم (in-memory) است؛ در محیطهای Serverless برای داشتن کش ماندگار از دایرکتیو 'use cache: remote' استفاده کنید.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://nextjs.org/docs/app