یکی از جذابترین ویژگیهای معماری مدرن Next.js این است که به شما اجازه میدهد دادههای خود را مستقیماً درون کامپوننتهای سروری دریافت (Fetch) کنید. از آنجا که این کدها صرفاً روی سرور آپلود و اجرا میشوند، شما محدودیتی در استفاده از ابزارهای ناهمگام (Asynchronous I/O) ندارید.
شما میتوانید به دو روش اصلی دیتای خود را تامین کنید:
استفاده از متد بومی fetch API
اتصال مستقیم به دیتابیس از طریق یک ORM (مثل Prisma یا Drizzle) یا کلاینتِ دیتابیس.
نحوه تبدیل کامپوننت به یک تابع async برای دریافت دیتا
مکانیزم بهینهسازی Memoization در درخواستهای مشابه
دوری از بلاک شدن صفحه در زمان لود دیتا به کمک <Suspense>
کوئری زدن مستقیم و امن به دیتابیس بدون نیاز به ساخت API Route مجزا
fetch APIبرای دریافت اطلاعات از یک API خارجی، کافی است کامپوننت خود را به یک تابع ناهمگام (async function) تبدیل کرده و پشت متد fetch از کلمه کلیدی await استفاده کنید:
// app/blog/page.tsx
export default async function Page() {
// ۱. ارسال درخواست به API و انتظار برای پاسخ سرور
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
// ۲. رندر خروجی به صورت کاملاً آماده در سمت سرور
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
مفهوم Memoization (بهخاطرسپاری خودکار): اگر در جاهای مختلفی از درخت کامپوننتهای خود (مثلاً در هدر، سایدبار و صفحه اصلی) نیاز به یک دیتای مشترک از یک آدرس fetch یکسان داشته باشید، ریاکت به صورت خودکار آن درخواست را دیدوپلیکیت (Deduplicate) میکند. یعنی فقط یکبار درخواست را به سرور مقصد میفرستد و بقیه جاها از کشِ همان رندر استفاده میکنند. پس نیازی به پاس دادن طولانی دیتا از والد به فرزند (Props Drilling) ندارید!
درخواستها رندر را بلاک میکنند: متد fetch به صورت پیشفرض کَش نمیشود و تا زمانی که پاسخ خود را کامل از اینترنت دریافت نکند، اجازه رندر شدن و نمایش صفحه را به کاربر نمیدهد. برای حل این مشکل دو راه دارید: یا از دایرکتیو جدید use cache برای ذخیره پاسخ استفاده کنید، یا کامپوننت دریافتکننده دیتا را درون یک تگ <Suspense> کلاینتی بپیچید تا سیستم بتواند کدهای صفحه را به صورت استریم (Streaming) و قطرهچکانی به مرورگر بفرستد.
لاگگیری کدهای شبکه: در محیط توسعه (Development)، میتوانید لاگهای مربوط به فراخوانیهای fetch را در ترمینال فعال کنید تا متوجه شوید چه درخواستی در چه زمانی به سرور فرستاده میشود.
از آنجا که این کامپوننتها به هیچ عنوان سر از مرورگر کاربر در نمیآورند، جاوااسکریپت آنها به کلاینت فرستاده نشده و در نتیجه تمام اطلاعات حساس پروژه (مثل کلمات عبور دیتابیس، امضای کوئریها و منطقهای SQL) کاملاً پنهان و امن باقی میمانند.
بنابراین، شما میتوانید بدون نیاز به ساختن یک API Route واسط، مستقیماً دیتابیس خود را در همان فایل صفحه صدا بزنید:
// app/blog/page.tsx
import { db, posts } from '@/lib/db' // ایمپورت کلاینت دیتابیس یا ORM پروژه
export default async function Page() {
// کوئری زدن مستقیم به دیتابیس روی سرور خودمان!
const allPosts = await db.select().from(posts)
return (
<ul>
{allPosts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
⚠️ یک تذکر امنیتی مهم: اتصال مستقیم به دیتابیس دست شما را برای کوئری زدن بسیار باز میگذارد، اما همیشه باید مطمئن شوید که درخواستهای ورودی به درستی احراز هویت (Authentication) و اعتبارسنجی سطح دسترسی (Authorization) شده باشند تا کاربری نتواند به دیتای کاربران دیگر دسترسی پیدا کند.
کامپوننتهای سروری را با چسباندن کلمه کلیدی async آماده دریافت مستقیم دیتا کنید.
متد fetch درخواستهای کاملاً همشکل را در یک دور رندر پاکسازی (Memoize) میکند تا از تکرار بیهوده جلوگیری شود.
برای جلوگیری از معطل شدن کاربر پشت لودینگهای سنگین شبکه، از ابزار استریمینگ مانند <Suspense> استفاده کنید.
با خیال راحت و امنیت صددرصدی، کوئریهای خود را مستقیماً با ORM درون فایل کامپوننت بنویسید و دیتابیس را شخم بزنید!
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://nextjs.org/docs/app