تفاوت React و Next.js

در درس قبل دیدیم که Next.js یک فریم‌ورک فول‌استک مبتنی بر React است. اکنون باید دقیق مشخص کنیم که چه بخش‌هایی را React ارائه می‌دهد و چه بخش‌هایی را Next.js اضافه می‌کند. درک این مرز به شما کمک می‌کند هنگام مشکل‌یابی بدانید باید سراغ مستندات کدام‌یک بروید و هنگام طراحی برنامه بدانید هر کار را کجا انجام دهید.

پیش‌نیاز

  • درس CH01-S01: Next.js چیست و چه مسئله‌ای را حل می‌کند؟
  • آشنایی پایه با کامپوننت‌ها، JSX، Props و State در React

توضیح شهودی: کتابخانه در برابر فریم‌ورک

React یک کتابخانه برای ساخت رابط کاربری است. کار اصلی آن این است که بگوید «با این داده‌ها، رابط کاربری چه شکلی دارد» و هنگام تغییر داده، رابط را به‌روز کند. React عمداً درباره‌ی مسیریابی، دریافت داده، ساختار پروژه، ابزار Build و استقرار تصمیم نمی‌گیرد و این انتخاب‌ها را به شما می‌سپارد.

Next.js یک فریم‌ورک است. یعنی علاوه بر استفاده از React برای رابط کاربری، درباره‌ی ساختار پروژه، مسیریابی، نحوه‌ی رندر، دریافت داده، کش و Build تصمیم گرفته و ابزار آماده ارائه می‌کند. تفاوت اصلی در همین است: React ابزار می‌دهد، Next.js یک مسیر ساخته‌شده و یکپارچه می‌دهد.

نکته‌ی مهم این است که این دو رقیب نیستند. وقتی در Next.js کامپوننت می‌نویسید، کامپوننت React نوشته‌اید و همه‌ی دانشی که از React دارید (JSX، Props، State، Hookها) همچنان کاربرد دارد.

توضیح فنی: هر کدام مسئول چه بخشی است؟

موضوع React Next.js
نوع ابزار کتابخانه‌ی رابط کاربری فریم‌ورک فول‌استک مبتنی بر React
کامپوننت‌ها، JSX، State و Hookها تعریف و ارائه می‌کند از همان‌ها استفاده می‌کند و مفهوم Server Component را هم در کنار آن به کار می‌گیرد
مسیریابی ندارد؛ باید کتابخانه‌ی جداگانه انتخاب کنید داخلی و مبتنی بر ساختار پوشه‌ها و فایل‌ها
ساختار پروژه تعیین نمی‌کند قراردادهای مشخص (مثل page.tsx و layout.tsx)
رندر روی سرور قابلیت‌های پایه فراهم است، اما راه‌اندازی کامل با شماست به‌صورت یکپارچه و آماده در چارچوب برنامه
دریافت داده راه‌حل یکپارچه‌ی از پیش تعیین‌شده ندارد دریافت داده در Server Componentها و ابزارهای کش و بازاعتبارسنجی
منطق سمت سرور پروژه‌ی سرور جدا لازم است Server Actions و Route Handlers در همان پروژه
Build و ابزار توسعه باید انتخاب و پیکربندی شود پیش‌فرض آماده (از جمله Turbopack در Next.js 16)
بهینه‌سازی تصویر، فونت و Metadata ندارد؛ به کتابخانه‌ها و پیکربندی خودتان وابسته است ابزارهای داخلی مانند next/image و next/font

یک نکته‌ی مهم: رابطه‌ی دو ابزار در عمل

React خودش هم راه‌های ساخت برنامه را پیشنهاد می‌کند و مستندات رسمی آن، استفاده از یک فریم‌ورک را برای پروژه‌های جدید توصیه می‌کند؛ Next.js یکی از این فریم‌ورک‌هاست. همچنین قابلیت‌هایی مثل Server Components بخشی از ایده‌ی React هستند و Next.js آن‌ها را در یک برنامه‌ی کامل به کار می‌گیرد. بنابراین مرز این دو همیشه به‌سادگی «این از React است و آن از Next.js» نیست، اما یک قاعده‌ی عملی وجود دارد:

  • اگر موضوع به کامپوننت، State، Props، Hook یا JSX مربوط است، سراغ مستندات React بروید.
  • اگر موضوع به مسیر، Layout، دریافت داده در سطح برنامه، کش، Route Handler، Metadata یا استقرار مربوط است، سراغ مستندات Next.js بروید.

مثال واقعی: همان صفحه در دو رویکرد

فرض کنید در DevNotes می‌خواهیم صفحه‌ای داشته باشیم که فهرست نوشته‌ها را نشان بدهد. ببینید هر رویکرد چه کارهایی از شما می‌خواهد.

رویکرد React خالص (اجرا در مرورگر)

  1. یک ابزار Build انتخاب و پیکربندی کنید.
  2. یک کتابخانه‌ی مسیریابی نصب کنید و مسیر /posts را در پیکربندی آن تعریف کنید.
  3. کامپوننت صفحه را بنویسید و داده‌ها را پس از بارگذاری، با درخواست از مرورگر دریافت کنید.
  4. حالت‌های انتظار و خطا را با State دستی مدیریت کنید.
  5. برای ذخیره‌ی نوشته‌ها یک سرور جداگانه بسازید.

رویکرد Next.js

  1. پروژه با یک فرمان ساخته می‌شود و ابزار Build آماده است.
  2. فایل app/posts/page.tsx را می‌سازید؛ مسیر /posts خودکار ایجاد می‌شود.
  3. داده را داخل همین کامپوننت روی سرور می‌خوانید.
  4. برای انتظار و خطا فایل‌های قراردادی مثل loading.tsx و error.tsx وجود دارند.
  5. منطق ذخیره‌سازی را می‌توانید در همان پروژه بنویسید.

مقایسه‌ی کد: همان صفحه، دو شکل نوشتن

دو نمونه‌ی زیر کاملاً ساده‌شده‌اند و فقط برای نشان‌دادن تفاوت الگوی کار هستند. نمونه‌ی اول فرض می‌کند در یک پروژه‌ی React خالص، فهرست نوشته‌ها از یک آدرس API در مرورگر دریافت می‌شود:

React خالص: دریافت داده در مرورگر

tsx
import { useEffect, useState } from "react";

type Post = { id: number; title: string };

export default function PostsPage() {
  const [posts, setPosts] = useState<Post[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("/api/posts")
      .then((res) => res.json())
      .then((data) => setPosts(data))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <p>در حال بارگذاری...</p>;

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Next.js: خواندن داده در Server Component

tsx
// app/posts/page.tsx
type Post = { id: number; title: string };

async function getPosts(): Promise<Post[]> {
  // در این مثال آموزشی، داده‌ی نمونه برمی‌گردد.
  return [
    { id: 1, title: "آشنایی با Next.js" },
    { id: 2, title: "مسیریابی در App Router" },
  ];
}

export default async function PostsPage() {
  const posts = await getPosts();

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

توضیح کد

  • در نمونه‌ی React خالص، چون کد در مرورگر اجرا می‌شود، ابتدا یک رندر بدون داده انجام می‌شود، سپس useEffect درخواست می‌فرستد و بعد از دریافت پاسخ، State تغییر می‌کند. مدیریت loading هم با خودتان است.
  • در نمونه‌ی Next.js، کامپوننت async است و مستقیماً await می‌کند. این کار در Server Component مجاز است. نتیجه‌ی رندر از سمت سرور آماده می‌شود و فهرست نوشته‌ها همراه HTML اولیه به مرورگر می‌رسد.
  • در نمونه‌ی Next.js نه useState لازم شد و نه useEffect؛ چون این کامپوننت روی سرور اجرا می‌شود و State یا Effect مرورگر در آن معنا ندارد.
  • تابع getPosts در این مثال فقط داده‌ی نمونه برمی‌گرداند. در فصل ۵ لایه‌ی دسترسی به داده را درست می‌سازیم و در فصل ۱۲ آن را به Prisma وصل می‌کنیم.

رفتار مورد انتظار

هر دو نمونه در نهایت یک فهرست از عنوان نوشته‌ها نشان می‌دهند. تفاوت در این است که در نمونه‌ی React خالص کاربر ابتدا پیام «در حال بارگذاری...» را می‌بیند و بعد فهرست ظاهر می‌شود، ولی در نمونه‌ی Next.js فهرست از ابتدا در HTML اولیه‌ی صفحه وجود دارد.

آیا Next.js همیشه بهتر است؟

نه لزوماً. Next.js برای برنامه‌هایی که صفحات متعدد، محتوای عمومی، نیاز به SEO، دریافت داده از سرور و منطق سمت سرور دارند انتخاب بسیار مناسبی است. اما برای یک ابزار کوچک و کاملاً سمت مرورگر، یک ویجت قابل‌جاسازی یا موارد مشابه که این نیازها را ندارند، ممکن است یک راه‌حل سبک‌تر کافی باشد. انتخاب باید بر اساس نیاز پروژه باشد.

جمع‌بندی

  • React کتابخانه‌ای برای ساخت رابط کاربری با کامپوننت‌هاست؛ Next.js فریم‌ورکی است که روی React ساخته شده و ساختار برنامه را هم تعیین می‌کند.
  • Next.js جایگزین React نیست؛ دانش React در Next.js مستقیماً کاربرد دارد.
  • مسیریابی، Layout، دریافت داده در سطح برنامه، کش، Route Handler، Server Action و استقرار از ابزارهایی هستند که Next.js ارائه می‌کند.
  • در Next.js کامپوننت‌ها به‌صورت پیش‌فرض Server Component هستند و می‌توانند داده را مستقیم و روی سرور بخوانند.
  • در درس بعد (CH01-S03) پیش‌نیازها و محیط توسعه را آماده می‌کنیم.