Next.js 16 vs Remix
Next.js 16 (بـ Turbopack كافتراضي وPartial Prerendering) مقابل Remix (من Shopify، قائم على معايير الويب) — مقارنة بين أطر عمل React الفوقية (meta-frameworks) لعام 2026.
طبقة React مُقدَّمة الرندر في الخادم، بجافاسكريبت صفري افتراضيًا
أسلوب استخدام React الكلاسيكي والناضج، المُرسَّم في المتصفح
في الصفحات كثيفة المحتوى والحرجة لتحسين محركات البحث (SEO)، يمنح RSC مكسبًا قابلًا للقياس: في مثال react.dev، لا تصل مكتبة بحجم 75K مضغوط (gzip) إلى العميل إطلاقًا. أما في اللوحات الداخلية كثيفة التفاعل (dashboard، admin)، فإن النهج القائم على العميل (client-first) أبسط ويقدّم سطح أخطاء أصغر. التحذير الحرج حقيقي: تمرير كائن (object) كاملًا كـ prop من الخادم إلى العميل يكتب جميع حقول ذلك الكائن في حمولة الرحلة (flight payload)؛ فإذا رسمتَ الحد الفاصل بشكل خاطئ، يتلاشى المكسب بصمت. اتخذ القرار بالقياس، لا بالموضة.
| الفئة | React Server Components | Client-side React (SPA) |
|---|---|---|
| الأداء | 8/10 | 6/10 |
| سهولة التعلّم | 4/10 | 8/10 |
| النظام البيئي | 7/10 | 9/10 |
| المجتمع | 7/10 | 9/10 |
| سوق العمل | 7/10 | 8/10 |
| الاستدامة المستقبلية | 9/10 | 7/10 |
// Next.js App Router — مكوّن خادم (Server Component، الافتراضي)
// app/posts/[slug]/page.tsx
import { db } from '@/lib/db';
import LikeButton from './like-button'; // مكوّن عميل (Client Component، في ملف منفصل 'use client')
interface PageProps {
params: Promise<{ slug: string }>;
}
export default async function PostPage({ params }: PageProps) {
const { slug } = await params;
// await مباشر في جانب الخادم — لا يوجد waterfall بين العميل والخادم،
// مكتبات ثقيلة مثل marked/sanitize-html لا تدخل إلى حزمة العميل إطلاقًا
const post = await db.post.findUnique({ where: { slug } });
if (!post) return <div>غير موجود</div>;
return (
<article>
<h1>{post.title}</h1>
{/* فقط الخصائص (props) القابلة للتسلسل تمرّ إلى مكوّن العميل */}
<div dangerouslySetInnerHTML={{ __html: post.renderedHtml }} />
<LikeButton postId={post.id} initialCount={post.likeCount} />
</article>
);
}
// app/posts/[slug]/like-button.tsx
'use client';
import { useState, useTransition } from 'react';
export default function LikeButton({ postId, initialCount }: { postId: string; initialCount: number }) {
const [count, setCount] = useState(initialCount);
const [isPending, startTransition] = useTransition();
return (
<button
disabled={isPending}
onClick={() => startTransition(async () => {
setCount((c) => c + 1);
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
})}
>
إعجاب ({count})
</button>
);
}// Vite + React — تطبيق SPA من جانب العميل
// src/pages/PostPage.tsx
import { useEffect, useState } from 'react';
import { useParams } from 'react-router';
interface Post {
id: string;
title: string;
renderedHtml: string;
likeCount: number;
}
export default function PostPage() {
const { slug } = useParams();
const [post, setPost] = useState<Post | null>(null);
const [isLiking, setIsLiking] = useState(false);
useEffect(() => {
// كل جلب البيانات في العميل — خطر waterfall يبدأ هنا
let cancelled = false;
fetch(`/api/posts/${slug}`)
.then((res) => res.json())
.then((data) => { if (!cancelled) setPost(data); });
return () => { cancelled = true; };
}, [slug]);
if (!post) return <div>جارٍ التحميل...</div>; // لا تظهر هذه الشاشة إطلاقًا قبل تشغيل جافاسكريبت
async function handleLike() {
setIsLiking(true);
setPost((p) => (p ? { ...p, likeCount: p.likeCount + 1 } : p));
await fetch(`/api/posts/${post!.id}/like`, { method: 'POST' });
setIsLiking(false);
}
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.renderedHtml }} />
<button disabled={isLiking} onClick={handleLike}>
إعجاب ({post.likeCount})
</button>
</article>
);
}
// vite.config.ts — تقسيم الكود يُفوَّض إلى Rollup
export default {
build: {
rollupOptions: {
output: { manualChunks: { vendor: ['react', 'react-dom', 'react-router'] } },
},
},
};في الصفحات كثيفة المحتوى والحرجة لتحسين محركات البحث (SEO)، يمنح RSC مكسبًا قابلًا للقياس: في مثال react.dev، لا تصل مكتبة بحجم 75K مضغوط (gzip) إلى العميل إطلاقًا. أما في اللوحات الداخلية كثيفة التفاعل (dashboard، admin)، فإن النهج القائم على العميل (client-first) أبسط ويقدّم سطح أخطاء أصغر. التحذير الحرج حقيقي: تمرير كائن (object) كاملًا كـ prop من الخادم إلى العميل يكتب جميع حقول ذلك الكائن في حمولة الرحلة (flight payload)؛ فإذا رسمتَ الحد الفاصل بشكل خاطئ، يتلاشى المكسب بصمت. اتخذ القرار بالقياس، لا بالموضة.
احصل على استشارة مجانيةفي الأسطح كثيفة المحتوى والحرجة لـ SEO، حيث يهم التحميل الأولي (LCP/TTI) — مثل المدونة وصفحة المنتج وصفحة المقارنة — يوفّر RSC مكسبًا قابلًا للقياس: جلب البيانات في جانب الخادم وجافاسكريبت أقل في جانب العميل. وفقًا لبيانات Next.js 16.3 نفسها، فإن الانتقال إلى تدفقات (streams) Node.js الأصلية في العرض من جانب الخادم يتيح معالجة 22% طلبات إضافية تحت الحمل. أما في اللوحات الداخلية كثيفة التفاعل (dashboard، admin)، فإن النهج القائم على العميل يوفّر عادةً تجربة تطوير أبسط.