با انتشار نسخه Next.js 13، یک دایرکتوری /appجدید به پروژه اضافه می‌شود که رویکردهای جدیدتری برای rendering و fetching داده‌ها دارد و همچنین از جدیدترین سرور کامپوننت های React استفاده می‌کند.

منظور از Rendering چیست؟

Rendering، کدی که می‌نویسیم را به رابط کاربری که کاربر با آن تعامل دارد تبدیل می‌کند. با React 18 و Next.js 13 تغییر کاملی در نحوه رندر کردن کد React به وجود آمده است.

قبل از اینکه بخواهیم مکانیسم‌های Rendering جدید با Next.js 13 را درک کنیم، می‌خواهیم برخی از اصطلاحات و تعاریف را دوباره مرور کنیم. در ادامه خلاصه‌ای از این تعاریف را باهم بررسی می‌کنیم.

Client

کلاینت به مرورگر دستگاه کاربر اشاره دارد که درخواستی را برای کد برنامه ما به سرور ارسال می‌کند. سپس پاسخ سرور را به رابطی تبدیل می‌کند که کاربر بتواند با آن تعامل داشته باشد.

Server

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

Client Componentها

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

نکته‌ای که وجود دارد این است که قبل از React 18، اصلی‌ترین راه برای رندر برنامه با استفاده از React، کاملاً روی کلاینت انجام می‌شد.

برای استفاده از یک Client Component در Next.js، یک فایل در داخل /appایجاد می‌کنیم و قبل از هر گونه importای، دایرکتیو “use Client” را در بالای فایل اضافه می‌نماییم.

در ادامه یک نمونه از کلاینت کامپوننت /app/Counter.js را داریم:

'use client';

import { useState } from 'react';
 
export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

Server Componentها

سرور کامپوننت یک مفهوم جدید است که در React 18 معرفی شده و توسط نسخه Next.js 13 در پوشه /app پذیرفته شده است.

سرور کامپوننت‌ها به ما این امکان را می‌دهند که کامپوننت‌ها را روی سرور رندر کنیم و مقدار جاوااسکریپت ارسال شده به کلاینت را کاهش دهیم.

همه کامپوننت‌های داخل دایرکتوری Next.js /app به طور پیش‌فرض سرور کامپوننت هستند.

چه چیزی باعث شد به سمت Server Componentها برویم؟

React Server Componentها این امکان را برای توسعه‌دهندگان فراهم می‌کنند تا از زیرساخت سرور استفاده کنند. قبل از معرفی سرور کامپوننت‌ها، React فقط قادر به رندر سمت کلاینت بود. اما با معرفی سرور کامپوننت‌ها، وابستگی‌های بزرگ می‌توانند به طور کامل روی سرور باقی بمانند و در نتیجه کارایی آن‌ها افزایش یابد.

اندازه bundle جاوااسکریپت سمت کلاینت زمانی کاهش می‌یابد که وابستگی‌های بزرگ در سرور حفظ شوند. زمانی که تعامل کاربر جدیدی وجود داشته باشد، همچنان می‌توانیم از کلاینت کامپوننت‌ها استفاده کنیم. اما به غیر از آن، اندازه bundle جاوااسکریپت زمان اجرای سمت کلاینت حداقل می‌باشد.

این موضوع یک پیروزی بزرگ برای React است و توسط Next.js 13 پذیرفته شده است.

Rendering کلاینت و سرور در سطح کامپوننت

نکته جالب در مورد این رویکرد جدید این است که می‌توانیم در برنامه خود کلاینت کامپوننت‌ها و سرور کامپوننت‌ها را به هم متصل کنیم. React در پشت صحنه، به طور یکپارچه کارکرد هر دو محیط را باهم ادغام می‌کند.

React می‌تواند روی کلاینت و سرور رندر بگیرد و ما می‌توانیم محیط رندر را در سطح کامپوننت انتخاب کنیم.

اگرچه می‌توانیم از هر دو کلاینت کامپوننت و سرور کامپوننت در یک برنامه استفاده کنیم، اما محدودیتی در React وجود دارد که در آن نمی‌توانیم یک سرور کامپوننت را در یک کلاینت کامپوننت import کنیم.

'use client';

// ❌ You cannot import a Server Component into a Client Component
import MyServerComponent from './MyServerComponent';

export default function ClientComponent() {
  return (
    <>
      <MyServerComponent />
    </>
  );
}

راه حل این مشکل این است که می‌توانیم یک سرور کامپوننت را به عنوان یک child یا یک prop به یک کلاینت کامپوننت ارسال کنیم، همانطور که در ادامه می‌بینیم:

// ✅ You can pass a Server Component as a child or prop of a Client Component.
import ClientComponent from "./ClientComponent";
import ServerComponent from "./ServerComponent";

export default function Page() {
  return (
    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
  );
}
'use client';

// ✅ You can pass a Server Component as a child or prop of a Client Component.
export default function ClientComponent({children}) {
  return (
    <>
      {children}
    </>
  );
}

چه زمانی باید از کلاینت کامپوننت‌ها و  چه زمانی باید ازسرور کامپوننت‌ها استفاده کنیم؟

ما فقط باید زمانی که کامپوننت‌ها از هوک‌های کلاینت مانند useState یا useEffect استفاده می‌کنند، آن ها را به عنوان “use Client” علامت‌گذاری کنیم.

بهتر است کامپوننت‌هایی که به هوک‌های کلاینت وابسته نیستند را بدون دستورالعمل رها کنیم تا زمانی که توسط کلاینت کامپوننت دیگری import نمی‌شوند، به طور خودکار به عنوان یک سرور کامپوننت رندر شوند.

این کار کمک می‌کند تا از کم‌ترین مقدار جاوااسکریپت در سمت کلاینت اطمینان حاصل کنیم. زیرا هدف ما این است که کم‌ترین مقدار جاوااسکریپت در سمت کلاینت ارسال شود.

استفاده از Client Componentها:

استفاده از Server Componentها: