مرحبًا بك في المدونة — كل ما تحتاجه عن Next.js App Router
جولة شاملة في Next.js 15 مع App Router: الـ layouts، الـ Server Components، جلب البيانات، والـ Metadata API. بقلم عزالدين عاطف.
ما الذي سنتعلمه؟
في هذا المقال سنستعرض Next.js 15 مع نظام App Router الجديد، ونفهم كيف تعمل:
- الـ Server Components و الـ Client Components
- نظام الـ layouts المتداخلة
- جلب البيانات مع
fetchعلى الخادم - الـ Metadata API لتحسين SEO
Server Components مقابل Client Components
الفرق الجوهري بسيط:
| الخاصية | Server Component | Client Component |
|---|---|---|
| يعمل على | الخادم فقط | المتصفح |
يستطيع استخدام useState | لا | نعم |
| يستطيع قراءة قاعدة البيانات | نعم | لا |
| حجم الـ JavaScript المرسل | صفر | حجم الملف كاملًا |
في Next.js كل مكوّن هو Server Component افتراضيًا. لتحويله إلى Client Component نضيف في أول السطر:
"use client";مثال عملي: صفحة المقالات
هذا مثال بسيط لصفحة تجلب مقالات من API وتعرضها:
// app/blog/page.tsx
import type { Post } from "@/types/post";
async function getPosts(): Promise<Post[]> {
const res = await fetch("https://api.example.com/posts", {
next: { revalidate: 3600 }, // إعادة التحقق كل ساعة
});
if (!res.ok) throw new Error("فشل جلب المقالات");
return res.json();
}
export default async function BlogPage() {
const posts = await getPosts();
return (
<ul className="space-y-4">
{posts.map((post) => (
<li key={post.id} className="p-4 border rounded-lg">
<h2 className="text-xl font-bold">{post.title}</h2>
<p className="text-neutral-600">{post.description}</p>
</li>
))}
</ul>
);
}لاحظ أن الدالة getPosts async مباشرة داخل المكوّن — هذا ممكن فقط في Server Components.
الـ Layout المتداخلة
نظام الـ layouts في App Router قوي جدًا. كل مجلد يمكن أن يحتوي على layout.tsx خاص به:
app/
├── layout.tsx ← Layout الجذر (Header + Footer)
├── blog/
│ ├── layout.tsx ← يضيف Sidebar للمقالات
│ └── [slug]/
│ └── page.tsx// app/blog/layout.tsx
export default function BlogLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="grid grid-cols-[1fr_250px] gap-8">
<main>{children}</main>
<aside>
{/* قائمة المقالات الجانبية */}
</aside>
</div>
);
}Metadata API
بدلًا من <Head> القديم، نستخدم الآن Metadata object:
// app/blog/[slug]/page.tsx
import type { Metadata } from "next";
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.description,
openGraph: {
title: post.title,
images: [post.coverImage],
},
};
}تثبيت المشروع من الصفر
# إنشاء مشروع جديد
npx create-next-app@latest my-blog \
--typescript \
--tailwind \
--app \
--src-dir
# الدخول للمجلد والبدء
cd my-blog
npm run devبعد التشغيل افتح http://localhost:3000 وستجد صفحة البداية.
نصيحة: استخدم loading.tsx بجانب كل page.tsx لإضافة Skeleton تلقائي أثناء جلب البيانات.
لا تستخدم "use client" بدون سبب. كلما قللت من Client Components كلما كان أداء تطبيقك أفضل.
الخلاصة
Next.js App Router يغير طريقة تفكيرنا في بناء تطبيقات React:
- ابدأ بـ Server Components وحوّل فقط ما يحتاج تفاعل المستخدم إلى Client
- استغل الـ layouts لتجنب تكرار الكود
- استخدم Metadata API للحصول على SEO ممتاز تلقائيًا
في المقال القادم سنتحدث عن Caching في Next.js وكيف تتحكم فيه بدقة.