نقش Frameworkها در Server Components

در طول این فصل بارها به یک نکته برگشتیم: Server Components در عمل به یک Framework نیاز دارند، و در درس‌های قبل گفتیم ویرایشگر درون‌صفحه‌ای آن‌ها را اجرا نمی‌کند. در این درس آخرِ بخش آموزشی فصل، دقیقاً روشن می‌کنیم یک Framework چه کاری انجام می‌دهد و چه چیزی را باید جزو React و چه چیزی را جزو Framework بدانیم.

یادآوری: چه چیزی باید جایی پیاده‌سازی شود

از درس‌های قبل می‌دانیم Server Components به چند چیز نیاز دارند:

  • یک Bundler که گراف importها را بر اساس "use client" به دو محیط جدا (سرور و مرورگر) تقسیم کند (درس ۲۴-۳).
  • یک محیط اجرا که Server Componentها را رندر کند و خروجی را به قالب قابل انتقال تبدیل کند (درس ۲۴-۴).
  • ارسال تدریجی خروجی به مرورگر و Hydration بخش‌به‌بخش (درس ۲۴-۷).
  • نقطه‌های ورود برای Server Functionها (درس ۲۴-۵).

هیچ‌کدام از این‌ها با نصب خود بسته react به‌تنهایی به دست نمی‌آید. این کارها باید توسط ابزاری که برنامه را Build و اجرا می‌کند انجام شود.

React معنا را تعریف می‌کند، Framework سیم‌کشی را

مستندات رسمی React تأکید می‌کند که Server Components و Suspense ویژگی‌های خود React هستند، نه ویژگی‌های یک Framework خاص. یعنی قواعدی که در این فصل دیدیم (Server Component چیست، چه مقادیری قابل Serialization‌اند، "use client" چه می‌کند، چگونه use و Suspense با هم کار می‌کنند) برای همه Frameworkها یکسان است. چیزی که بین Frameworkها فرق می‌کند، نحوه سیم‌کشی این قواعد به یک برنامه کامل است.

کارهایی که Framework به عهده می‌گیرد

  • Bundler و Build: تقسیم کد به دو محیط، و تصمیم‌گیری درباره اینکه کدام صفحه در زمان Build رندر شود و کدام با هر درخواست (دو حالت درس ۲۴-۱).
  • Routing: نگاشت آدرس URL به کامپوننت، و ساختار Layoutهای تودرتو. همان ایده فصل پانزدهم، این‌بار با کامپوننت‌هایی که می‌توانند روی سرور باشند.
  • رندر روی سرور و Streaming: اجرای Server Componentها، پیش‌رندر Client Componentها، و ارسال تدریجی همراه با مرزهای Suspense.
  • کش و به‌روزرسانی داده: اینکه نتیجه یک درخواست داده چقدر نگه داشته شود و چه زمانی دوباره گرفته شود. تابع cache درس ۲۴-۶ فقط در سطح یک رندر کار می‌کند؛ کش بلندمدت‌تر و روش‌های ابطال آن، تصمیم خود Framework است.
  • Server Functionها: ساختن نقطه‌های ارتباطی امن و مدیریت فراخوانی آن‌ها از مرورگر.
  • قراردادهای فایل: مثلاً نام و محل فایل‌هایی برای صفحه، Layout، خطا و Loading. چون Error Boundary یک Client Component است (درس ۲۴-۶)، Frameworkها معمولاً این کار را با فایل‌های قراردادی ساده می‌کنند.

مثال: ساختار فایل‌ها در یک Framework

html
app/
  layout.js        ← Server Component (هدر و ساختار مشترک)
  page.js          ← Server Component (داده را با await می‌خواند)
  LikeButton.js    ← "use client" (بخش تعاملی)
  actions.js       ← "use server" (Server Functionها)

این ساختار نمونه‌ای از قرارداد Next.js App Router است. نام فایل‌ها (مثل page.js و layout.js) قرارداد همان Framework است، نه بخشی از React. اما کدی که داخل هر فایل می‌نویسید، یعنی async Server Component، "use client" و "use server"، همان چیزی است که در این فصل یاد گرفتیم.

چرا نمی‌توان ساده‌تر خودمان این را بسازیم

همان‌طور که در درس ۲۴-۱ گفتیم، Server Components در React 19 پایدار هستند، اما APIهای زیرینی که یک Bundler یا Framework برای پیاده‌سازی آن‌ها استفاده می‌کند، از Semver پیروی نمی‌کنند و ممکن است بین نسخه‌های Minor شکسته شوند. توصیه رسمی برای کسی که خودش می‌خواهد این پشتیبانی را بسازد، پین کردن یک نسخه مشخص React یا استفاده از نسخه Canary است. برای تقریباً همه برنامه‌نویس‌ها، منطقی‌تر است این هزینه را به یک Framework نگه‌داری‌شده سپرد.

وضعیت Frameworkها در زمان نگارش

صفحه «Creating a React App» در مستندات رسمی React، Next.js (App Router)، React Router (v7) و Expo را به‌عنوان Frameworkهای توصیه‌شده معرفی می‌کند، و TanStack Start را (در وضعیت Beta) در فهرست «سایر Frameworkها» می‌آورد. همان صفحه می‌گوید در حال حاضر Next.js App Router کامل‌ترین پیاده‌سازی Server Components است، و تیم React با توسعه‌دهندگان Bundlerها کار می‌کند تا پیاده‌سازی این ویژگی‌ها در نسل بعدی Frameworkها آسان‌تر شود. سطح پشتیبانی هر Framework دیگر ممکن است تغییر کند؛ پیش از انتخاب، مستندات خود آن Framework را درباره Server Components بررسی کنید.

Framework لزوماً یعنی «سرور زنده» نیست

یک سوءبرداشت رایج این است که استفاده از Framework یعنی حتماً باید یک سرور همیشه روشن داشته باشید. مستندات رسمی اشاره می‌کند Frameworkهای Full-stack لزوماً به سرور نیاز ندارند و بسیاری از آن‌ها خروجی ثابت (Static Export) هم پشتیبانی می‌کنند. این همان حالت «Server Components بدون سرور» درس ۲۴-۱ است: رندر یک‌بار در زمان Build و عرضه خروجی ثابت. برای حالتی که با هر درخواست رندر می‌شود، یک محیط اجرا (مثلاً Node.js، سرویس Serverless یا یک کانتینر) لازم است.

آیا همیشه به Server Components نیاز داریم؟

خیر. Server Components یک امکان‌اند، نه الزام. اگر برنامه‌تان یک SPA کاملاً تعاملی و بدون نیاز به رندر سمت سرور است، یا یک ابزار داخلی ساده، ممکن است Client Component معمولی و ابزارهای فصل چهاردهم کافی باشد. بیشترین سود Server Components وقتی است که محتوای زیادی به داده سرور وابسته است، حجم جاوااسکریپت مرورگر مهم است، یا ارسال سریع محتوای اولیه (مثلاً برای موتورهای جست‌وجو) اهمیت دارد.

ادامه در فصل بعد

انتخاب بین Framework و ساختن برنامه با یک Build Tool ساده، و مقایسه گزینه‌های مختلف، موضوع فصل بیست‌وپنجم (اکوسیستم React) است، بخصوص درس‌های ۲۵-۱ و ۲۵-۸. در این درس فقط نقش Framework را در رابطه با Server Components دیدیم.

چرا این درس مثال قابل اجرا ندارد

این درس درباره ابزارهای Build و اجرا است، نه یک رفتار قابل نمایش در یک کامپوننت. برای دیدن آن‌ها یک پروژه با Framework مناسب بسازید و ساختار فایل‌ها و رفتار Build را بررسی کنید.

جمع‌بندی

Server Components و Suspense ویژگی‌های خود React هستند، اما اجرای عملی آن‌ها به یک Bundler و محیط اجرای آگاه از دو محیط Server و Client نیاز دارد که Framework فراهم می‌کند: Build، Routing، رندر و Streaming، کش داده، Server Functionها و قراردادهای فایل. چون APIهای زیرین هنوز از Semver پیروی نمی‌کنند، استفاده از یک Framework نگه‌داری‌شده معمول است. در زمان نگارش، Next.js App Router کامل‌ترین پیاده‌سازی است و Frameworkهای دیگر سطوح مختلفی از پشتیبانی دارند. Framework لزوماً سرور زنده نمی‌خواهد و Server Components الزامی نیستند. با این درس، بخش آموزشی فصل بیست‌وچهارم پایان می‌یابد و در ادامه به آزمون فصل ۲۴ می‌رویم.