مقدمة في Next.js

Next.js هو إطار عمل لبناء تطبيقات ويب حديثة بإستخدام React. يوفر Next.js العديد من الميزات التي تساعد المطورين على بناء تطبيقات قوية وسريعة وقابلة للتطوير.

لماذا نستخدم Next.js؟

  • تصيير المحتوى على الخادم (SSR) يعني أن المحتوى يتم تجهيزه على الخادم قبل وصوله للمستخدم.
  • توليد المواقع الثابتة (SSG) لإنشاء صفحات HTML ثابتة وقت البناء.
  • التحميل التلقائي للمكونات مما يحسن الأداء.
  • نظام توجيه مبني على الملفات يسهل على المطورين إنشاء وإدارة صفحات التطبيق.
  • دعم API داخلي لبناء نقاط نهاية (endpoints) للخدمات الخلفية.
  • تحسينات أداء تلقائية لتسريع تحميل التطبيق.

كيف يعمل Next.js؟

يعمل Next.js من خلال تحويل ملفات React إلى HTML ديناميكي سواء على الخادم أو أثناء البناء. يقوم بتحميل JavaScript المطلوب فقط للصفحة المحددة، مما يسرع من وقت التحميل. يدعم Next.js ثلاثة أنواع من التصيير:

التصيير الثابت (SSG)

توليد HTML ثابت وقت البناء. مناسب للصفحات التي لا تتغير بيانتها باستمرار.

التصيير على الخادم (SSR)

توليد HTML في كل طلب. مناسب للصفحات التي تحتاج بيانات محدثة دائماً.

التصيير من جانب العميل (CSR)

توليد HTML في المتصفح. مناسب للصفحات التفاعلية بشكل كبير.

ما هي نظم الإصدارات في Next.js؟

يتم تطوير Next.js باستمرار وقد مر بالعديد من الإصدارات الرئيسية. الإصدار الحالي المستقر هو 14.x الذي يأتي مع نظام App Router الجديد ويتضمن تحسينات كبيرة في الأداء والواجهة البرمجية.

الفرق بين Pages Router و App Router

الميزة Pages Router (التقليدي) App Router (الجديد)
المكان دليل /pages دليل /app
التصيير SSG, SSR, CSR SSG, SSR, CSR بشكل أكثر تكاملاً
مكونات الخادم غير متوفر متوفر افتراضياً
تحميل البيانات getStaticProps, getServerSideProps fetch API داخل المكونات مباشرة

إعداد المشروع

لبدء مشروع جديد باستخدام Next.js، ستحتاج إلى Node.js مثبت على جهازك. يوفر Next.js أداة سهلة لإنشاء مشاريع جديدة.

متطلبات ما قبل البدء

  • Node.js الإصدار 16.8.0 أو أحدث
  • مدير الحزم npm أو yarn أو pnpm
  • محرر أكواد (VS Code موصى به)

إنشاء مشروع جديد

لإنشاء مشروع جديد، قم بتنفيذ الأمر التالي في Terminal:

npx create-next-app@latest my-next-app

سيقوم هذا الأمر بإنشاء مشروع جديد ويطرح عليك بعض الأسئلة لضبط الإعدادات:

? Would you like to use TypeScript? Yes
? Would you like to use ESLint? Yes
? Would you like to use Tailwind CSS? Yes
? Would you like to use `src/` directory? No
? Would you like to use App Router? Yes
? Would you like to customize the default import alias? No

هيكل المشروع

بعد إنشاء المشروع، ستجد هيكل الملفات الأساسي. فيما يلي شرح لأهم الملفات والمجلدات:

my-next-app/
├── app/              // دليل التطبيق الرئيسي في نظام App Router
│   ├── favicon.ico   // أيقونة الموقع
│   ├── globals.css   // ملف CSS عام للتطبيق
│   ├── layout.tsx    // تخطيط الصفحات الرئيسي
│   └── page.tsx      // صفحة الرئيسية
├── public/           // ملفات الوسائط والملفات الثابتة
├── node_modules/     // حزم npm المثبتة
├── .eslintrc.json   // إعدادات ESLint
├── .gitignore       // قائمة الملفات التي يتم تجاهلها في Git
├── next.config.js   // ملف إعدادات Next.js
├── package.json     // إعدادات المشروع والتبعيات
├── postcss.config.js // إعدادات PostCSS (لـ Tailwind)
├── README.md        // توثيق المشروع
├── tailwind.config.js // إعدادات Tailwind CSS
└── tsconfig.json    // إعدادات TypeScript

تشغيل المشروع

لتشغيل المشروع بوضع التطوير، انتقل إلى مجلد المشروع وقم بتنفيذ:

cd my-next-app
npm run dev

سيبدأ الخادم المحلي في العمل على العنوان http://localhost:3000، ويمكنك الآن البدء بتطوير تطبيقك.

ملاحظة مهمة

تقوم ميزة التحديث التلقائي (Hot Reloading) في Next.js بإعادة تحميل التطبيق تلقائياً عند إجراء أي تغييرات على الكود، مما يوفر تجربة تطوير سريعة. لا حاجة لإعادة تشغيل الخادم في كل مرة تقوم فيها بتعديل الكود.

نظام الصفحات والتوجيه

يعتمد Next.js على نظام توجيه قائم على الملفات، حيث يتم تحويل هيكل الملفات والمجلدات إلى مسارات URL تلقائياً.

نظام App Router (الإصدار 13 وما بعده)

في نظام App Router، توجد الصفحات والمسارات في مجلد app. كل مجلد يمثل جزءاً من المسار، والملفات الخاصة تحدد السلوك.

هيكل الملفات

app/
├── layout.tsx       // تخطيط عام
├── page.tsx         // الصفحة الرئيسية "/"
├── about/
│   └── page.tsx     // صفحة "عن الموقع" على "/about"
├── blog/
│   ├── layout.tsx   // تخطيط خاص بقسم المدونة
│   ├── page.tsx     // صفحة المدونة الرئيسية "/blog"
│   └── [slug]/      // متغير ديناميكي
│       └── page.tsx // صفحة مقال فردي "/blog/:slug"

الملفات الخاصة

  • page.tsx - يصبح صفحة قابلة للوصول بعنوان URL
  • layout.tsx - يحدد واجهة مشتركة لعدة صفحات
  • loading.tsx - يظهر أثناء تحميل المحتوى
  • error.tsx - يظهر عند حدوث خطأ
  • not-found.tsx - يظهر عند عدم وجود صفحة
  • route.ts - يحدد API خاص بهذا المسار

إنشاء الصفحات

لإنشاء صفحة جديدة، قم بإنشاء ملف page.tsx أو page.js في المسار المطلوب:

// app/about/page.tsx

export default function AboutPage() {
  return (
    <div className="container mx-auto py-8">
      <h1 className="text-3xl font-bold">عن الموقع</h1>
      <p className="mt-4">هذه هي صفحة معلومات عن الموقع.</p>
    </div>
  );
}

بمجرد إنشاء هذا الملف، ستكون الصفحة متاحة على /about.

التوجيه الديناميكي

يمكنك إنشاء مسارات ديناميكية باستخدام الأقواس المربعة:

// app/products/[id]/page.tsx

export default function ProductPage({ params }) {
  // params.id يحتوي على قيمة المعامل من عنوان URL
  return (
    <div>
      <h1>المنتج: {params.id}</h1>
    </div>
  );
}

هذا سيعمل مع مسارات مثل /products/1، /products/shoes إلخ.

التخطيطات (Layouts)

التخطيطات تسمح بمشاركة واجهة مشتركة بين عدة صفحات:

// app/blog/layout.tsx

export default function BlogLayout({ children }) {
  return (
    <div className="blog-container">
      <nav className="blog-sidebar">
        <h3>أقسام المدونة</h3>
        <ul>
          <li><a href="/blog/tech">تقنية</a></li>
          <li><a href="/blog/design">تصميم</a></li>
        </ul>
      </nav>
      
      <main className="blog-content">
        {children}
      </main>
    </div>
  );
}

التخطيط أعلاه سيظهر لكل الصفحات داخل مجلد /blog.

ملاحظة مهمة

ملفات التخطيط (layout) تحافظ على حالتها بين تنقلات الصفحات، مما يعني أنه لا يتم إعادة تحميلها مع كل تحميل لصفحة جديدة. هذا يجعل التطبيق أكثر سلاسة وأسرع.

التنقل بين الصفحات

يجب استخدام مكون Link من Next.js للتنقل بين الصفحات بدلاً من الروابط العادية <a>:

// مثال للتنقل بين الصفحات

import Link from 'next/link';

export default function Navigation() {
  return (
    <nav>
      <ul>
        <li>
          <Link href="/">الرئيسية</Link>
        </li>
        <li>
          <Link href="/about">عن الموقع</Link>
        </li>
        <li>
          <Link href={`/blog/${postId}`}>مقالة معينة</Link>
        </li>
      </ul>
    </nav>
  );
}

مكون Link يستخدم تقنية التنقل من جانب العميل (Client-Side Navigation) مما يعني أنه لا يتم إعادة تحميل الصفحة بالكامل عند التنقل.

المكونات في Next.js

يعتمد Next.js على نظام المكونات الخاص بـ React، ولكنه يضيف ميزة مهمة وهي التفريق بين مكونات الخادم (Server Components) ومكونات العميل (Client Components).

مكونات الخادم (Server Components)

في Next.js 13 وما بعده، تكون جميع المكونات افتراضياً هي مكونات خادم. هذه المكونات تنفذ على الخادم وتوفر العديد من المزايا:

  • الوصول المباشر لموارد الخادم (قواعد البيانات، ملفات الخادم، الخ)
  • تقليل حجم JavaScript المرسل للمتصفح
  • عدم تسرب بيانات حساسة للعميل
  • تحسين الأداء والأمان

مثال لمكون خادم:

// هذا مكون خادم افتراضي
async function UserProfile({ userId }) {
  // استرجاع بيانات من قاعدة البيانات مباشرة (لا يمكن القيام بذلك في مكونات العميل)
  const user = await db.user.findUnique({ where: { id: userId } });
  
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

مكونات العميل (Client Components)

مكونات العميل هي مكونات تنفذ في المتصفح وتكون تفاعلية. لتعريف مكون كمكون عميل، نضيف توجيه "use client" في بداية الملف:

"use client" // هذا التوجيه يخبر Next.js أن هذا مكون عميل

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>العدد الحالي: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        زيادة
      </button>
    </div>
  );
}

متى تستخدم مكونات العميل؟

استخدم مكونات العميل عندما تحتاج إلى:

  • استخدام الأحداث (onClick, onChange, الخ)
  • استخدام React Hooks مثل useState وuseEffect
  • استخدام API متصفح مثل window أو localStorage
  • إضافة تفاعلية للمكون

دمج مكونات الخادم والعميل

يمكن دمج مكونات الخادم والعميل معاً، حيث يمكن لمكونات الخادم أن تحتوي على مكونات العميل:

// ArticlePage.js - مكون خادم
import LikeButton from './LikeButton'; // مكون عميل

async function getArticle(id) {
  const res = await fetch(`https://api.example.com/articles/${id}`);
  return res.json();
}

export default async function ArticlePage({ params }) {
  const article = await getArticle(params.id);
  
  return (
    <article>
      <h1>{article.title}</h1>
      <p>{article.content}</p>
      <LikeButton articleId={article.id} /> // استخدام مكون عميل
    </article>
  );
}

وهذا مكون العميل المشار إليه:

"use client" // LikeButton.js - مكون عميل

import { useState } from 'react';

export default function LikeButton({ articleId }) {
  const [likes, setLikes] = useState(0);
  const [isLiked, setIsLiked] = useState(false);
  
  function handleLike() {
    if (isLiked) {
      setLikes(likes - 1);
      setIsLiked(false);
    } else {
      setLikes(likes + 1);
      setIsLiked(true);
    }
    
    // يمكن هنا إرسال طلب للخادم لتحديث عدد الإعجابات
  }
  
  return (
    <button
      onClick={handleLike}
      className={`btn ${isLiked ? 'btn-liked' : ''}`}
    >
      {isLiked ? 'إلغاء الإعجاب' : 'إعجاب'} ({likes})
    </button>
  );
}

استرجاع البيانات

يوفر Next.js عدة طرق لاسترجاع البيانات، خصوصاً في مكونات الخادم التي تدعم استخدام async/await مباشرة.

استرجاع البيانات في مكونات الخادم

في مكونات الخادم، يمكنك استخدام fetch مباشرة لاسترجاع البيانات:

// app/users/page.tsx

async function getUsers() {
  const res = await fetch('https://api.example.com/users');
  if (!res.ok) {
    throw new Error('فشل في استرجاع المستخدمين');
  }
  return res.json();
}

export default async function UsersPage() {
  const users = await getUsers();
  
  return (
    <div>
      <h1>المستخدمون</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

تخزين البيانات مؤقتًا (Caching)

في Next.js، يتم تخزين طلبات fetch مؤقتًا افتراضيًا. يمكنك التحكم في سلوك التخزين المؤقت باستخدام خيارات fetch:

// استرجاع بيانات مع تخزين مؤقت (افتراضي)
const staticData = await fetch('https://api.example.com/static-data');

// استرجاع بيانات جديدة في كل طلب (بدون تخزين مؤقت)
const dynamicData = await fetch('https://api.example.com/dynamic-data', { cache: 'no-store' });

// استرجاع بيانات مع تخزين مؤقت لمدة 10 ثوان
const revalidatedData = await fetch('https://api.example.com/data', { 
  next: { revalidate: 10 } 
});

استرجاع البيانات من جانب العميل

في مكونات العميل، يمكنك استخدام React Hooks مثل useEffect للاسترجاع:

"use client"

import { useState, useEffect } from 'react';

export default function ClientFetching() {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    async function fetchData() {
      try {
        const res = await fetch('https://api.example.com/data');
        const jsonData = await res.json();
        setData(jsonData);
      } catch (err) {
        setError(err.message);
      } finally {
        setIsLoading(false);
      }
    }
    
    fetchData();
  }, []);
  
  if (isLoading) return <p>جاري التحميل...</p>;
  if (error) return <p>حدث خطأ: {error}</p>;
  
  return (
    <div>
      <h1>البيانات</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

استخدام SWR لاستجراع البيانات

SWR هي مكتبة من Vercel (الشركة المطورة لـ Next.js) تساعد في استرجاع البيانات مع إمكانيات مثل إعادة التحقق في الخلفية وتخزين البيانات مؤقتاً:

"use client"

import useSWR from 'swr';

const fetcher = async (url) => {
  const res = await fetch(url);
  if (!res.ok) {
    throw new Error('فشل في استرجاع البيانات');
  }
  return res.json();
};

export default function Profile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher);
  
  if (isLoading) return <p>جاري التحميل...</p>;
  if (error) return <p>حدث خطأ</p>;
  
  return (
    <div>
      <h1>مرحباً {data.name}!</h1>
    </div>
  );
}

واجهة برمجة التطبيقات (API)

يوفر Next.js طريقة سهلة لإنشاء واجهات برمجة تطبيقات (API) مباشرة في المشروع، مما يسمح لك بإنشاء نقاط نهاية للتعامل مع الطلبات HTTP.

إنشاء Route Handlers

في App Router، يتم إنشاء Route Handlers في ملفات route.js أو route.ts:

// app/api/users/route.ts

export async function GET() {
  const users = [
    { id: 1, name: 'أحمد' },
    { id: 2, name: 'محمد' },
    { id: 3, name: 'سارة' },
  ];

  return Response.json(users);
}

export async function POST(request) {
  const data = await request.json();
  
  // التحقق من صحة البيانات والمعالجة
  if (!data.name) {
    return Response.json(
      { error: 'اسم المستخدم مطلوب' },
      { status: 400 }
    );
  }
  
  // إضافة مستخدم جديد (في حالة حقيقية سيكون في قاعدة بيانات)
  const newUser = { id: 4, name: data.name };
  
  return Response.json(newUser, { status: 201 });
}

يمكنك الآن الوصول إلى هذه الـ API عبر العنوان /api/users، ويمكنك استخدام طرق HTTP المختلفة مثل GET وPOST وPUT وDELETE.

استخدام المعلمات الديناميكية

يمكنك استخدام المعلمات الديناميكية في واجهات API بنفس طريقة استخدامها في الصفحات:

// app/api/users/[id]/route.ts

export async function GET(request, { params }) {
  const userId = params.id;
  
  // استرجاع المستخدم حسب المعرف (مثال)
  const user = { id: userId, name: `المستخدم ${userId}` };
  
  return Response.json(user);
}

export async function DELETE(request, { params }) {
  const userId = params.id;
  
  // حذف المستخدم (في حالة حقيقية)
  // await db.user.delete({ where: { id: userId } });
  
  return Response.json({ message: `تم حذف المستخدم ${userId} بنجاح` });
}

التعامل مع الجلسات والمصادقة

يمكنك استخدام ملفات API للتعامل مع المصادقة والجلسات:

// app/api/login/route.ts

import { cookies } from 'next/headers';
import { sign } from 'jsonwebtoken';

export async function POST(request) {
  const { email, password } = await request.json();
  
  // التحقق من بيانات المستخدم (مثال)
  if (email === '[email protected]' && password === 'password123') {
    // إنشاء توكن JWT
    const token = sign(
      { id: 1, email },
      process.env.JWT_SECRET,
      { expiresIn: '1h' }
    );
    
    // وضع التوكن في كوكيز
    cookies().set('token', token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      maxAge: 3600, // ساعة واحدة
      path: '/',
    });
    
    return Response.json({ success: true });
  }
  
  return Response.json(
    { error: 'بيانات غير صحيحة' },
    { status: 401 }
  );
}

التنسيق والتصميم

يدعم Next.js العديد من طرق تنسيق التطبيق، بما في ذلك CSS العادي، وCSS Modules، وSCSS، وTailwind CSS، والمكتبات الأخرى.

CSS العالمي

يمكنك استيراد ملفات CSS العالمية مباشرة في ملف layout.js الرئيسي:

// app/layout.tsx

import './globals.css';

export default function RootLayout({
  children,
}) {
  return (
    <html lang="ar" dir="rtl">
      <body>{children}</body>
    </html>
  );
}

CSS Modules

تسمح وحدات CSS بإنشاء أنماط محلية النطاق لتجنب تضارب الأسماء وتعزيز إعادة استخدام المكونات. يتم استخدامها عن طريق تسمية ملفات CSS بصيغة [name].module.css.

// styles/Button.module.css

.button {
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  font-weight: 500;
  transition: all 0.2s;
}

.primary {
  background-color: #FF4C29;
  color: white;
}

.secondary {
  background-color: #2C394B;
  color: white;
}

ثم يمكنك استيراد هذه الأنماط واستخدامها في المكونات:

// components/Button.js

import styles from '../styles/Button.module.css';

export default function Button({ children, variant = 'primary', onClick }) {
  return (
    <button
      className={`${styles.button} ${styles[variant]}`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

عند تجميع التطبيق، سيقوم Next.js بتحويل أسماء الفئات إلى أسماء فريدة لضمان عدم وجود تعارض أسماء.

Tailwind CSS

Tailwind CSS هو إطار عمل CSS مفيد يسمح بإنشاء تصاميم باستخدام فئات مباشرة في HTML. Next.js يوفر دعمًا مباشرًا لـ Tailwind CSS.

// تثبيت Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

بعد التثبيت، قم بتكوين Tailwind من خلال تعديل ملف tailwind.config.js:

// tailwind.config.js

module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      colors: {
        // إضافة ألوان مخصصة
        primary: '#FF4C29',
        secondary: '#2C394B',
      },
    },
  },
  plugins: [],
}

ثم يمكنك استخدام فئات Tailwind مباشرة في المكونات:

// مثال لاستخدام Tailwind CSS

export default function Card({ title, description }) {
  return (
    <div className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
      <h2 className="text-xl font-bold text-gray-900 mb-2">{title}</h2>
      <p className="text-gray-600">{description}</p>
    </div>
  );
}

CSS-in-JS

يمكنك أيضًا استخدام مكتبات CSS-in-JS مثل styled-components و Emotion. عند استخدام منهج App Router، تحتاج إلى بعض الإعدادات الإضافية.

// مثال باستخدام styled-components (مع توجيه "use client")
"use client"

import styled from 'styled-components';

const Button = styled.button`
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  font-weight: 500;
  background-color: ${props => props.primary ? '#FF4C29' : '#2C394B'};
  color: white;
  transition: all 0.2s;
  
  &:hover {
    opacity: 0.9;
  }
`;

export default function StyledButton({ children, primary, onClick }) {
  return (
    <Button primary={primary} onClick={onClick}>
      {children}
    </Button>
  );
}

تحسين الأداء

يقدم Next.js العديد من التقنيات والأدوات لتحسين أداء التطبيق وتجربة المستخدم.

تحسين الصور

يوفر Next.js مكون Image المدمج لتحسين أداء الصور وتحميلها بكفاءة:

import Image from 'next/image';

export default function ProfileImage() {
  return (
    <Image
      src="/images/profile.jpg"
      alt="صورة الملف الشخصي"
      width={300}
      height={300}
      priority
    />
  );
}

مكون Image يقوم تلقائيًا بتحسين الصور من خلال:

  • تحميل الصور عند الحاجة (Lazy Loading)
  • تغيير حجم الصور تلقائيًا حسب الجهاز
  • تقديم الصور بتنسيقات حديثة مثل WebP وAVIF
  • منع تحرك المحتوى أثناء تحميل الصور (CLS)

تقسيم الكود (Code Splitting)

يقوم Next.js تلقائيًا بتقسيم الكود على مستوى الصفحات والمكونات الديناميكية، ويمكنك استخدام التحميل الديناميكي للمكونات:

import dynamic from 'next/dynamic';

// استيراد المكون ديناميكيًا (يتم تحميله فقط عند الحاجة)
const DynamicChart = dynamic(() => import('../components/Chart'), {
  loading: () => <p>جاري تحميل الرسم البياني...</p>,
  ssr: false, // للمكونات التي تعتمد على متصفح فقط
});

export default function Dashboard() {
  return (
    <div>
      <h1>لوحة التحكم</h1>
      <DynamicChart data={chartData} />
    </div>
  );
}

تحسين الخطوط (Fonts)

يقدم Next.js أدوات لتحسين الخطوط وتجنب تحركات المحتوى أثناء تحميلها:

import { Inter } from 'next/font/google';

// تكوين الخط
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
});

export default function RootLayout({ children }) {
  return (
    <html lang="ar" dir="rtl" className={inter.className}>
      <body>{children}</body>
    </html>
  );
}

تحسين بيانات التعريف (Metadata)

يمكنك تحسين محركات البحث (SEO) من خلال إضافة بيانات التعريف لكل صفحة:

// app/page.tsx

import { Metadata } from 'next';

// تكوين بيانات التعريف للصفحة
export const metadata: Metadata = {
  title: 'الصفحة الرئيسية | اسم المشروع',
  description: 'وصف الصفحة الرئيسية',
  openGraph: {
    title: 'اسم المشروع',
    description: 'وصف المشروع',
    images: ['/images/og-image.jpg'],
  },
};

export default function Home() {
  return (
    <main>
      // محتوى الصفحة
    </main>
  );
}

نشر التطبيق

بعد الانتهاء من تطوير التطبيق، يمكنك نشره على الإنترنت. توفر Vercel (الشركة خلف Next.js) أفضل تجربة نشر، ولكن يمكنك أيضًا استخدام منصات أخرى.

النشر على Vercel

الطريقة الأسهل لنشر تطبيق Next.js هي استخدام منصة Vercel:

  1. قم بإنشاء حساب مجاني على Vercel.com
  2. ادفع الكود الخاص بك إلى مستودع (GitHub, GitLab, أو Bitbucket)
  3. قم بتسجيل الدخول إلى Vercel وإستيراد المشروع من المستودع
  4. اضبط أي متغيرات بيئية مطلوبة
  5. انقر على "نشر" وسيتم نشر تطبيقك تلقائيًا

مع Vercel، يتم إعادة نشر التطبيق تلقائيًا مع كل تغيير تقوم بدفعه للمستودع.

بناء التطبيق محليًا

لبناء التطبيق محليًا قبل النشر على أي منصة أخرى:

// بناء التطبيق للإنتاج
npm run build

// اختبار البناء محليًا
npm start

نشر التطبيق على منصات أخرى

يمكنك أيضًا نشر تطبيق Next.js على خدمات استضافة أخرى مثل:

  • Netlify
  • AWS Amplify
  • DigitalOcean App Platform
  • خوادم VPS الخاصة (باستخدام Docker)

ملاحظة مهمة

عند نشر تطبيق Next.js على منصة غير Vercel، قد تحتاج إلى ضبط بعض الإعدادات الإضافية في ملف next.config.js وإضافة ملف Dockerfile أو ملفات تكوين أخرى حسب المنصة المستخدمة.

الخلاصة

يعتبر Next.js إطار عمل قوي ومرن لبناء تطبيقات الويب الحديثة، ويوفر العديد من الميزات التي تجعل تجربة التطوير سلسة وممتعة.

في هذا الدليل، تعلمت كيفية:

  • إعداد مشروع Next.js جديد
  • استخدام نظام التوجيه القائم على الملفات
  • بناء مكونات الخادم والعميل
  • استرجاع البيانات بطرق مختلفة
  • إنشاء واجهات برمجة التطبيقات (API)
  • تنسيق التطبيق باستخدام CSS Modules وTailwind CSS
  • تحسين أداء التطبيق
  • نشر التطبيق على الويب

استمر في استكشاف المزيد من ميزات Next.js واستفد من مجتمعه النشط للحصول على المساعدة والموارد.