فرانت‌اند

React Server Components عمیق

چرا RSC باندل کلاینت رو کوچیک‌تر می‌کنه، چطور مشکل waterfall رو حل می‌کنه، و چطور با Client Component ترکیب می‌شه.

عارف بوساک
عارف بوساکنویسنده
۱۴۰۳/۰۵/۱۱۳ دقیقه۶ بازدید
React Server Components عمیق

React Server Components دقیقاً چی هستند؟

React Server Components (که به اختصار RSC صدایشان می‌کنیم) یک نوع کامپوننت جدید هستند که از قبل، توی محیط سرور رندر می‌شوند — جدا از اپلیکیشن کلاینت و جدا از سروری که SSR انجام می‌دهد. این رندر یا یک‌بار در زمان build اتفاق می‌افتد، یا برای هر ریکوئست روی سرور، قبل از باندل شدن.

فرق اصلیش با Client Component

مهم‌ترین محدودیت RSC این است که هیچ‌کدام از این‌ها را ندارد: useState، useReducer، useEffect، دسترسی به localStorage یا window، و event handler هایی مثل onClick. در عوض، می‌تواند مستقیم داخل بدنه‌ی خودش await کند:

// این یک Server Component معتبر است
async function Notes() {
  const notes = await db.notes.getAll();
  return <div>{notes.map(n => <p key={n.id}>{n.content}</p>)}</div>;
}

چرا مهم است: باندل کوچیک‌تر

فرض کنید بخواهید مارک‌داون را parse و sanitize کنید. بدون RSC، باید کتابخانه‌هایی مثل marked و sanitize-html (که مجموعاً حدود ۷۵ کیلوبایت gzip شده هستند) را به باندل کلاینت اضافه کنید. با RSC، این کتابخانه‌ها فقط روی سرور اجرا می‌شوند و هیچ‌وقت به مرورگر کاربر نمی‌رسند — کلاینت فقط HTML نهایی را می‌گیرد.

حل مشکل Waterfall

بدون RSC، فچ کردن داده‌های وابسته به هم معمولاً به شکل زنجیره‌ای (waterfall) اتفاق می‌افتد: کامپوننت اول باید فچش تمام شود تا کامپوننت دوم بتواند شروع کند. با RSC، چون هر کامپوننت مستقیم به دیتابیس یا سرویس دسترسی دارد، این فچ‌ها می‌توانند موازی اجرا شوند — بدون نیاز به state یا useEffect.

امنیت به‌عنوان یک مزیت جانبی

چون RSC مستقیم روی سرور اجرا می‌شود، می‌تواند بدون افشای هیچ credential ای مستقیم به دیتابیس وصل شود؛ توکن‌ها و کلیدهای API هیچ‌وقت به کلاینت نمی‌رسند، و کنترل دسترسی می‌تواند دقیقاً در لحظه‌ی رندر انجام شود.

ترکیب با Client Component

RSC می‌تواند یک Client Component را به‌عنوان فرزند رندر کند، و این‌طوری خروجی سرور و تعامل کلاینتی با هم ترکیب می‌شوند:

// Server Component
async function Notes() {
  const notes = await db.notes.getAll();
  return notes.map(n => <Expandable key={n.id}><p>{n.content}</p></Expandable>);
}

// Client Component
'use client';
function Expandable({ children }) {
  const [open, setOpen] = useState(false);
  return <div onClick={() => setOpen(!open)}>{open && children}</div>;
}

مرورگر فقط باندل Expandable را دریافت می‌کند؛ کد و منطق دیتابیسِ Notes هیچ‌وقت به کلاینت نمی‌رسد.

محدودیت‌ها

RSC نمی‌تواند Context جدید بسازد (فقط می‌تواند یک Provider که در یک Client Component تعریف شده را رندر کند)، و طبق مستندات ری‌اکت، APIهای زیرساختی باندلرِ RSC هنوز semver-compliant نیستند — یعنی فریم‌ورک‌ها باید نسخه‌ی React را ثابت نگه دارند.

جمع‌بندی

RSC یک تغییر بنیادی در نحوه‌ی فکر کردن به رندر کردن است: سادگی مدل درخواست/پاسخ سمت سرور را با تعامل اپ‌های مدرن ترکیب می‌کند، فچ‌های تکراری را حذف می‌کند، باندل را کوچیک‌تر می‌کند، و دسترسی امن مستقیم به بک‌اند می‌دهد.

منبع: مستندات رسمی React — Server Components

فرانت‌اند
عارف بوساک
عارف بوساک

طراحی وب، توسعه‌ی بهتر — وب‌سایت‌های سریع، مدرن و نتیجه‌محور.