الرجوع لكل المقالات
uncategorized

⚛️ React Server Components vs Qwik: الحقيقة العالية في العالم الواقعي عبر منصات متعددة

4 دقايق قراءة
4 مشاهدة

الحرب بين الأطر التي لا يتحدث عنها أحد

كل فترة، مجتمع الـ frontend بيحصل على أطر جديدة وبيقولوا إنها هتخلف عن React. لقد شفناه مع Svelte، ثم Solid، والآن Qwik هو المنافس اللي بيعمل ده. لكن القصة الحقيقية أكتر تعقيد منقول "X أحسن من Y". لما أني قضي السنة الماضية في بناء تطبيقات إنتاجية باستخدام React Server Components (RSC) في Next.js و Qwik City، هقلك على الأشياء اللي بتحصل لما بتبعت منتجات حقيقية.

ما اللي RSC بيعمله صح

React Server Components بتحول العمل. بدل ما ترسل حزمة من JavaScript للعميل وتطلب من المتصفح أن يرسم كل شيء، أنتا بترسم على السيرفر وترسل HTML. ده بيبدو بسيط، لكن الأثر بيبقى كبير:

// RSC — ده المكون مش هيروح للعميل
import { db } from '@/db';
import { posts } from '@/db/schema';
export async function BlogList() {
  const allPosts = await db.select().from(posts);
  return (
    <ul>
      {allPosts.map(post => (
        <li key={post.id}>{post.title_en}</li>
      ))}
    </ul>
  );
}

المكون BlogList ده بيشتغل كله على السيرفر. مفيش JavaScript بيتسلم للعميل. لا useEffect، لا حالات تحميل، لا مكالمات API من المتصفح. استعلام قاعدة البيانات بيحصل على السيرفر، وال HTML الناتج بتوصل للمستخدم فقط. لموقع پورتفوليو الخاص بي، ده خيار واضح. الصفحات بتتحمل بسرعة لأن مفيش JavaScript كتير للصفحات اللي فيها محتوى. الحزمة بتضل رشيقة.

حيث RSC بتفشل

الآن للحقيقة الصعبة: RSC بتلمع للصفحات اللي فيها محتوى كتير، لكن بتعاني مع واجهات المستخدم التفاعلية جدا. لما تحتاج تحديثات في الوقت الحقيقي، أو طفرات متفائلة، أو حالة عميل معقدة، أنتا عائد تتنشر "use client" في كل مكان.

"use client";
import { useState } from "react";
export function CommentForm({ postId }: { postId: string }) {
  const [text, setText] = useState("");
  const [submitting, setSubmitting] = useState(false);
  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setSubmitting(true);
    await fetch(`/api/posts/${postId}/comments`, {
      method: "POST",
      body: JSON.stringify({ text }),
    });
    setSubmitting(false);
    setText("");
  }
  return (
    <form onSubmit={handleSubmit}>
      <textarea value={text} onChange={(e) => setText(e.target.value)} />
      <button disabled={submitting}>
        {submitting ? "Submitting..." : "Submit"}
      </button>
    </form>
  );
}

لما تضيف "use client"، المكون ده وكل شيء تحته بيتسلم كجافاسكريبت. مش ممكن تعمل tree-shake عند حدود السيرفر — ده تبديل كل شيء أو لا شيء. ده بيخلق انقسام مزعج في قاعدة بياناتك حيث المكونات الذكية على السيرفر والمكونات الغبية على العميل منفصلين بحدود صلبة.

رهان Qwik على الاستئناف

Qwik بت_approach_ المشكلة من زاوية مختلفة تمامًا. بدل ما يكون السيرفر ضد الكلينت، Qwik بيتكلم عن الاستئناف ضد الهيدريشن. الفكرة الأساسية هي إن الإطار يجب يتحمل فقط تحميل وتنفيذ الـ JavaScript اللي محتاجة للتفاعل المحدد اللي بيقوم بيه المستخدم. لا هيدريشن. لا إعادة تشغيل كل منطق الكومبوننت على تحميل الصفحة. بس serialize حالة التطبيق إلى HTML، ثم تحميل معالجات الأحداث بشكل كسول ตาม ما بيتفاعل المستخدم.

// Qwik — يقوم بتقسيم الكود على مستوى معالج الأحداث
import { component$, useSignal, $ } from "@builder.io/qwik";
export const Counter = component$(() => {
  const count = useSignal(0);
  return (
    <button onClick$={() => count.value++}>
      Count: {count.value}
    </button>
  );
});

معالج onClick$ اللي فوق هو شريحة منفصلة. بيتحمل فقط لما المستخدم يضغط على الزر. لو هو ما ضغطش، الكود ده هيحملش.

الواقع العابر للمنصات

لقد قمت بتشغيل كلا الإطارين على نفس الأجهزة (VPS Dokploy مع PostgreSQL) وهنا ما وجدته: | المقياس | Next.js (RSC) | Qwik City | |--------|--------------|-----------| | تحميل JavaScript الأول (صفحة المحتوى) | ~85 KB | ~45 KB | | تحميل JavaScript الأول (صفحة التفاعل) | ~145 KB | ~60 KB | | TTI | 1.2s | 0.9s | | وقت البناء (50 صفحة) | 18s | 32s | | DX لمواقع المحتوى الثقيل | ممتاز | جيد | | DX لمواقع التطبيقات | جيد | ممتاز | الأرقام بتحكي قصة، ولكن فرق DX مهم أكثر في الممارسة. نموذج RSC للتفكير في "السيرفر ضد الكلينت" أسهل في التفكير عنه لمعظم الفرق. الاستئناف في Qwik أكثر أداءً ولكن له منحنى تعلم أعمق.

الخلاصة

إذا كنت تبني موقع محتوى أو مدونة أو محفظة (مثل هذه) — استمر مع Next.js و RSC. النظام البيئي والأدوات وقصة النشر غير متوازیة. لموقعي، التبادل واضح: RSC يعطيني تحميل صفحات سريع مع تعقيد أقل. إذا كنت تبني تطبيق ويب تفاعلي حيث يهم الأداء على الأجهزة البطيئة — Qwik يستحق النظر الجدي. نموذج الاستئناف فعلاً أفضل لتحسينات JavaScript الثقيلة. الفائز الحقيقي؟ كلا الإطارين بيحسنوا الويب عن طريق تقليل ضرائب JavaScript. اختر الإطار اللي يطابق طبيعة تطبيقك.