لوحة التحكم للتحليلات الخاصة بعميلك تتجمد لمدة 340 ميلي ثانية في كل مرة يقوم فيها المستخدم بتبديل نطاق التاريخ على مخطط به 3000 نقطة بيانات. معالج React يعمل على مراجعة عقد VDOM، والـ hooks تندلع في تسلسلات متسلسلة، والحزمة الخاصة بك للتو تجاوزت 180 كيلو بايت مضغوطة. الفصل الماضي أعدنا بناء لوحة التحكم الإنتاجية هذه بالضبط—المصادقة، تحديثات WebSocket الفورية، نماذج معقدة متعددة الخطوات، وحدة الرسوم البيانية—في كل من SolidJS و React، وقمنا بتوثيق كل عملية تصيير، وتسجيل كل بايت من الحزمة، وتشغيل تدفقات المستخدم نفسها عبر كلا الإصدارين. فجوة الأداء كانت أوسع مما توقعنا، لكن ليس حيث تتوقع.

النتائج فاجأتنا. ليس لأن إطار عمل واحد "فاز"—بل لأن المقايضات كانت أكثر دقة بكثير مما يقترحه نقاش Twitter. بعض الأشياء توقعنا أن نراها. بعض الأشياء فاجأتنا تماماً. هذا ما تعلمناه فعلاً.

جدول المحتويات

بنينا نفس التطبيق في SolidJS و React: Signals مقابل Hooks

التطبيق الذي بنيناه

التطبيق عبارة عن لوحة تحكم تحليلات فورية لعميل تجارة إلكترونية. إليك ما يشمله:

  • تدفق المصادقة مع رموز JWT ومنطق التحديث
  • لوحة التحكم مع 6 لوحات عناصر واجهة مستخدم، تسحب البيانات من نقاط نهاية API مختلفة
  • خلاصة الطلبات الفورية باستخدام اتصالات WebSocket
  • الرسوم البيانية التفاعلية التي تصيير 5000+ نقطة بيانات (باستخدام مكتبة رسم بياني)
  • نماذج تصفية معقدة مع القوائم المنسدلة التابعة و منتقيات نطاق التاريخ
  • لوحة إعدادات المسؤول مع إدارة الحالة المتداخلة
  • تخطيط سريع الاستجابة مع ملاحة الشريط الجانبي

كلا الإصدارين يتصل بـ API الخلفية نفسها. كلاهما يستخدم TypeScript. كلاهما يستخدم Vite كأداة بناء. احتفظنا بالاعتماديات الخارجية متشابهة قدر الإمكان—نفس مكتبة الرسم البياني (Chart.js)، نفس عميل HTTP (ky)، نفس مجمع WebSocket.

إصدار React يستخدم React 19 مع hooks. إصدار SolidJS يستخدم Solid 1.9. لم نستخدم أي meta-frameworks (لا Next.js، لا SolidStart) لأننا أردنا عزل اختلافات الإطار دون التوجيه و SSR يخلط المقارنة.

Signals مقابل Hooks: تحول نموذج عقلي

هذا هو الكبير. وصراحة، استغرق الأمر حوالي أسبوع لفريقنا التوقف عن كتابة كود على شكل React في SolidJS.

كيفية عمل React Hooks

أنت تعرف هذا، لكن يستحق القول صراحة للمقارنة. نموذج React هو: عندما تتغير الحالة، دالة المكون تعيد التنفيذ. الدالة بأكملها. كل useState، كل useMemo، كل useCallback—كلها آليات للعمل حول حقيقة أن الدالة بأكملها تعيد التشغيل.

// React: هذه الدالة بأكملها تعيد التشغيل عند كل تغيير حالة
function OrderFeed() {
  const [orders, setOrders] = useState([]);
  const [filter, setFilter] = useState('all');
  
  // يعيد الحساب في كل عملية تصيير إلا إذا قمنا بـ memoize
  const filteredOrders = useMemo(() => 
    orders.filter(o => filter === 'all' || o.status === filter),
    [orders, filter]
  );

  // يتم إعادة إنشاء هذا ref مفاهيمياً في كل عملية تصيير
  const handleNewOrder = useCallback((order) => {
    setOrders(prev => [order, ...prev]);
  }, []);

  useEffect(() => {
    const ws = connectWebSocket(handleNewOrder);
    return () => ws.close();
  }, [handleNewOrder]);

  return <OrderList orders={filteredOrders} />;
}

كيفية عمل Solid Signals

نموذج Solid مختلف بشكل أساسي. دالة المكون تعمل مرة واحدة. بعد ذلك، فقط التعبيرات المحددة التي تقرأ إشارة تعيد التنفيذ عند تغيير تلك الإشارة. لا توجد virtual DOM diff. لا توجد مصالحة. الرسم البياني التفاعلي يتتبع بالضبط أي عقد DOM تعتمد على أي إشارات.

// Solid: هذه الدالة تعمل مرة واحدة فقط
function OrderFeed() {
  const [orders, setOrders] = createSignal([]);
  const [filter, setFilter] = createSignal('all');
  
  // يتم تتبع هذا تلقائياً—لا حاجة لصفيف التبعية
  const filteredOrders = createMemo(() => 
    orders().filter(o => filter() === 'all' || o.status === filter())
  );

  // لا حاجة لـ useCallback—هذا الإغلاق مستقر
  const handleNewOrder = (order) => {
    setOrders(prev => [order, ...prev]);
  };

  // onMount بدلاً من useEffect مع deps فارغة
  onMount(() => {
    const ws = connectWebSocket(handleNewOrder);
    onCleanup(() => ws.close());
  });

  return <OrderList orders={filteredOrders()} />;
}

ماذا يعني هذا عملياً

إصدار Solid لا يحتوي على صفائف التبعية. لا useCallback. لا useMemo للحالة المشتقة (على الرغم من أن createMemo موجود للحسابات المكلفة—الفرق هو أنها اختيارية للأداء، وليست مطلوبة للصحة).

إليك ما عضنا أثناء التطوير:

  1. فصل props يقتل التفاعل في Solid. كان لدينا مطور صغير يفصل props في مكون Solid وأمضينا 45 دقيقة في تصحيح الأخطاء لماذا لم تنتشر التحديثات. في React، فصل props أمر جيد لأن الدالة بأكملها تعيد التشغيل. في Solid، تحتاج إلى الوصول إلى props.value داخل JSX أو نطاق مقفول.

  2. العودة المبكرة محفوفة بالمخاطر في Solid. لا يمكنك فعل if (!data()) return <Loading /> في أعلى مكون Solid بالطريقة التي قد تفعلها في React. دالة المكون تعمل مرة واحدة فقط، لذلك هذا الشرط لن يعيد التقييم أبداً. تحتاج إلى <Show when={data()}> بدلاً من ذلك.

  3. لا توجد أخطاء stale closure. كانت هذه الفائزة الكبيرة. في إصدار React الخاص بنا، كان لدينا ثلاثة أخطاء stale closure منفصلة في الأسبوع الأول المتعلقة بمعالجات WebSocket التي تلتقط الحالة القديمة. إصدار Solid كان لديه صفر، لأن الإشارات يتم قراءتها دائماً في وقت الوصول، وليس في closure.

مقارنة حجم الحزمة

قمنا بقياس كلا الإصدارات الإنتاجية مع نفس إعداد Vite، ضغط gzip، واستراتيجية تقسيم الكود.

مقياس React 19 SolidJS 1.9 الفرق
runtime الإطار 44.2 KB (gzip) 7.1 KB (gzip) -84%
الحزمة الأولية الكلية 127.8 KB 89.3 KB -30%
التطبيق الكلي (جميع الأجزاء) 312.4 KB 274.1 KB -12%
الجزء الأول (مسار حرج) 68.4 KB 41.2 KB -40%
عدد الأجزاء 14 14 نفس

runtime Solid أصغر بشكل هائل. هذا ليس خبر—Ryan Carniato تحدث عن هذا على نطاق واسع. لكن ما فاجأنا كان أن فرق التطبيق الإجمالي ضاق بشكل كبير بمجرد إضافة كود التطبيق الحقيقي والمكتبات الخارجية والأصول.

runtime الإطار يهم أكثر شيء للحمل الأولي. وعند 7.1 KB مضغوطة، Solid تختفي في الأساس في الضوضاء. تصنيف React البالغ 44 كيلو بايت ملحوظ، خاصة على اتصالات الهاتف المحمول.

Tree Shaking

Solid يقوم بـ tree shake بشكل أفضل من React. الـ primitives غير المستخدمة من Solid يتم حذفها بالكامل. مع React، معالج المصالحة و fiber architecture تُشحن سواء استخدمت كل الميزات أم لا. أكدنا هذا بناء صفحة بسيطة في كلا الإصدارين—أرضية Solid أقل.

بنينا نفس التطبيق في SolidJS و React: Signals مقابل Hooks - العمارة

معايير أداء التصيير

قمنا بتشغيل معايير منظمة باستخدام Chrome DevTools performance profiles و Lighthouse و tooling قياس مخصص. جميع الاختبارات على MacBook Pro M2 مع CPU throttling مضبوطة على 4x slowdown لمحاكاة الأجهزة متوسطة المدى.

تصيير المخطط (5000 نقطة بيانات)

مقياس React 19 SolidJS 1.9
التصيير الأولي 142ms 89ms
إعادة التصيير عند تغيير المرشح 67ms 23ms
الذاكرة أثناء التصيير 18.4 MB 11.2 MB
عقد DOM التي تم إنشاؤها 5,847 5,812

كان Solid متسقاً أسرع في إعادة التصيير لأنه لا يختلف عن شجرة virtual DOM. عندما تتغير إشارة مرشح، فقط التعبيرات التي تقرأ تلك الإشارة تحدث. تحسينات مجمع React 19 ساعدت—نفس الاختبار على React 18 كان 95ms لإعادة التصيير—لكن Solid كانت لا تزال لديها ميزة واضحة.

خلاصة الطلبات الفورية (100 تحديث/ثانية)

هنا حيث أصبحت الأمور مثيرة جداً للاهتمام. دفعنا 100 رسالة WebSocket في الثانية إلى خلاصة الطلبات.

مقياس React 19 SolidJS 1.9
انقطاع الإطار (لكل 10 ثانية) 12 2
متوسط وقت الطلاء 8.3ms 3.1ms
أقصى وقت طلاء 34ms 11ms
استخدام CPU (متوسط) 24% 9%

Solid سحقت هذا المعيار تماماً. التحديثات عالية التردد هي حيث يدفع التفاعل الدقيق أكبر عائد. كان React يجمع التحديثات (وهو أمر جيد)، لكن لا تزال تختلف أكثر DOM من الضروري في كل دفعة.

يجب أن نلاحظ: React 19's useTransition والتجميع التلقائي جعل هذا أفضل بكثير مما كانت React 18 ستكون. وللعديد من التطبيقات الحقيقية، لا تدفع 100 تحديث في الثانية. عند 10 تحديثات/ثانية، كلا الإطارين كانا سلسين.

نموذج معقد مع 40 حقل

مقياس React 19 SolidJS 1.9
تأخير الإدخال عند الكتابة 2-4ms <1ms
تصيير إرسال النموذج 28ms 12ms
re-renders مكون في كل keystroke 3-8 1

في React، الكتابة في حقل واحد ستؤدي إلى re-render مكونات الوالد ما لم نقوم بـ memoize كل شيء بعناية. في Solid، الكتابة في حقل يحدّث فقط عقدة نص DOM لهذا الحقل. لا شيء آخر يعاد تنفيذ.

تجربة المطور والنظام البيئي

الأداء ليست كل شيء. عليك أن تبني الشيء فعلياً وتصحح أخطاءه وتوظف له والحفاظ عليه.

حجم النظام البيئي (من أوائل 2026)

العامل React SolidJS
npm التنزيلات الأسبوعية ~28M ~85K
نجوم GitHub 233K+ 33K+
أسئلة Stack Overflow 470K+ ~2K
مكتبات مكونات واجهة المستخدم 50+ خيارات ناضجة 5-8 خيارات
منشورات الوظائف (LinkedIn US) ~45,000 ~200
Meta-framework Next.js (ناضج) SolidStart (beta)

هذا هو الفيل في الغرفة. النظام البيئي React أكبر بأوامر من الحجم. عندما احتجنا إلى منتقي نطاق التاريخ لـ Solid، كان عليا إما نقل واحد من React أو كتابة واحدة بنفسنا. في React، كان لدينا 15 خياراً للاختيار من بينها.

استخدمنا Kobalte لـ primitives واجهة المستخدم التي يمكن الوصول إليها في Solid، وهي جيدة فعلاً. لكنها ليست Radix UI من حيث تغطية المكونات.

تصحيح الأخطاء

React DevTools ناضج وصيانته جيدة وشيء يعرفه كل مطور frontend. Solid لديها extension DevTools الخاصة بها، وهي لائقة—يمكنك فحص رسم الإشارة البياني، وهو فعلاً أكثر فائدة لتتبع أخطاء التفاعل من عرض شجرة مكونات React. لكنها أقل تلميعاً.

دعم TypeScript

كلاهما ممتاز. دعم Solid's TypeScript أفضل قليلاً لـ JSX لأن المجمع يتعامل مع المزيد في وقت البناء. كان لدينا ألعاب نوع أقل في codebase Solid.

مقايضات الإنتاج التي تهم فعلاً

بعد بناء كلا الإصدارين ونشر إصدار Solid إلى staging (اختار العميل في النهاية React للإنتاج—المزيد حول هذا أدناه)، إليك المقايضات التي أهمت فعلاً:

التوظيف

عميلنا لديه فريق من 8 مطورين frontend. الكل يعرفون React. لا أحد استخدم Solid. تقدير وقت التدريب: 2-3 أسابيع للإنتاجية، 2-3 أشهر للإتقان. هذه تكلفة حقيقية. هذا هو العامل الأكبر في معظم قرارات الإنتاج، وهذا هو السبب في أننا عادة ما نوصي بـ React أو frameworks مثل Next.js للفرق التي تحتاج إلى التوظيف بشكل متكرر.

توافق المكتبة الخارجية

كان علينا كتابة wrappers مخصصة لثلاث مكتبات كان لديها تكاملات خاصة بـ React. أضاف هذا تقريباً 20 ساعة من وقت التطوير. في مشروع React، تلك الساعات لا توجد.

تصيير الخادم

SolidStart واعد لكنه كان لا يزال في beta أثناء مشروعنا. Next.js تم اختباره في المعركة. بالنسبة للمشاريع حيث نحتاج إلى SSR من الدرجة الإنتاجية مع كل الملفات، لا نزال نصل إلى تطوير Next.js أو Astro حسب نموذج المحتوى.

الأداء حيث يهم

إليك الحقيقة الصريحة: لـ dashboard معين، كلا الإطارين أديا بشكل جيد لاحتياجات الإنتاج. إصدار Solid كان بقياس أسرع، لكن إصدار React لم يكن أبداً بطيء. المستخدمون لن يلاحظوا الفرق في معظم التفاعلات.

الاستثناء كان خلاصة فورية عند ترددات تحديث عالية. إذا كان لدى تطبيقك حالة استخدام مثل تلك، فإن ميزة أداء Solid معنى، وليست مجرد مفاخرة بالمعايير.

متى تختار SolidJS بدلاً من React

بعد هذه التجربة، إليك النموذج الصريح الخاص بنا للقرار:

اختر SolidJS عندما:

  • يحتوي تطبيقك على تحديثات تفاعلية عالية التردد (لوحات تحكم، منصات تداول، تعاون فوري)
  • حجم الحزمة أمر حرج (widgets embedded، micro-frontends، الأول للجوال)
  • فريقك صغير ومستعد للاستثمار في منحنى التعلم
  • تريد تفاعل دقيق دون القتال مع الإطار
  • تبني شيء جديد ولا تحتاج إلى نظام بيئي ضخم للمكونات

اختر React عندما:

  • فريقك يعرف بالفعل React (هذا وحده عادة ما يكون حاسماً)
  • تحتاج إلى meta-framework ناضج (Next.js, Remix)
  • توفر مكتبة خارجية مهمة
  • أنت تستأجر وتحتاج إلى مجموعة موهبة كبيرة
  • متطلبات أداء تطبيقك نموذجية (ليست متطرفة)

للـ headless CMS development الخاص بنا، React لا يزال يهيمن لأن تكاملات CMS (Sanity, Contentful, Storyblok) لديها SDKs من الدرجة الأولى React. دعم Solid موجود لكنه في الغالب مدعوم من المجتمع.

مقارنة الكود: أنماط حقيقية

لننظر إلى بعض الأنماط الحقيقية من المشروع جنباً إلى جنب.

جلب البيانات مع حالات التحميل

React:

function Dashboard() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchDashboardData()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <Skeleton />;
  if (error) return <ErrorBanner error={error} />;
  return <DashboardGrid data={data} />;
}

SolidJS:

function Dashboard() {
  const [data] = createResource(fetchDashboardData);

  return (
    <Suspense fallback={<Skeleton />}>
      <ErrorBoundary fallback={(err) => <ErrorBanner error={err} />}>
        <DashboardGrid data={data()} />
      </ErrorBoundary>
    </Suspense>
  );
}

createResource Solid مع Suspense رشيق حقاً. React لديها Suspense أيضاً (وقد تحسن)، لكن نسخة Solid شعرت بأنها أكثر طبيعية للعمل معها. أقل boilerplate، عدد أقل من متغيرات الحالة للإدارة.

التصيير الشرطي

React:

{user ? (
  <Profile user={user} />
) : (
  <LoginPrompt />
)}

SolidJS:

<Show when={user()} fallback={<LoginPrompt />}>
  {(u) => <Profile user={u()} />}
</Show>

mكون <Show> من Solid موجود لأن ternaries لا تعمل بنفس الطريقة عندما تعمل دالة المكون مرة واحدة فقط. استغرق الأمر التعود عليه، لكن نمط الـ callback يعطيك reference مضيقة وغير فارغة وهي لطيفة لـ TypeScript.

تصيير القائمة

React:

{orders.map(order => (
  <OrderRow key={order.id} order={order} />
))}

SolidJS:

<For each={orders()}>
  {(order) => <OrderRow order={order} />}
</For>

<For> من Solid لا تحتاج مفاتيح لأنها تتبع عناصر المصفوفة بواسطة reference. عندما ينتقل عنصر في المصفوفة، Solid تنقل عقدة DOM الفعلية. React ستقوم بـ unmount و remount. هذا هو السبب في أن أداء قائمة Solid جيدة جداً.

الأسئلة الشائعة

هل SolidJS جاهزة للإنتاج في 2026؟ نعم. Solid 1.x ثابتة لأكثر من سنتين. شركات مثل Cloudflare و Samsung استخدمتها في الإنتاج. مكتبة النواة ناضجة وتم اختبارها بشكل جيد. النظام البيئي حولها (SolidStart، مكتبات المكونات) أصغر من React's ولكن ينمو بشكل مطرد. السؤال ليس ما إذا كانت Solid جاهزة—إنه ما إذا كان فريقك ومتطلبات المشروع تتوافق مع حجم النظام البيئي الخاص بها.

هل يمكنني الترحيل من React إلى SolidJS بشكل تدريجي؟ ليس بسهولة. رغم تشابه JSX، نماذج runtime مختلفة بشكل أساسي. لا يمكنك embed مكونات Solid داخل تطبيق React (أو العكس) دون iframe أو حدود web component. الترحيل سيكون بشكل أساسي إعادة كتابة. إذا كنت تفكر فيها، ابدأ بميزة معزولة جديدة أو micro-frontend بدلاً من محاولة تحويل كود React موجود.

هل SolidJS تدعم تصيير الخادم؟ نعم. SolidStart توفر SSR، streaming، ووظائف server. إنها وظيفية وتتحسن بسرعة، لكن في أوائل 2026، لا تزال أقل نضجاً من Next.js أو Remix. لمشاريع SSR-heavy، قد نوصي بتقييم Next.js أو Astro حسب احتياجات المحتوى.

كيف يقارن مجمع React 19 بنهج Solid؟ مجمع React 19 (سابقاً React Forget) يقوم بـ auto-memoizes مكونات لتقليل re-renders غير الضروري. تحسن كبير. لكنها لا تزال تعمل ضمن نموذج React لإعادة تشغيل دوال المكون و diffing virtual DOM. Solid يتخطى كلا الخطوتين تماماً. يجعل المجمع React أسرع، لكنه لا يغير العمارة الأساسية. في معايرنا، React 19 مع المجمع كان حوالي 30% أسرع من React 18، لكن لا يزال أبطأ من Solid في سيناريوهات update-heavy.

ماذا عن Preact Signals كحل وسط؟ Preact Signals (و @preact/signals-react adapter) يجلب reactivity تشبه الإشارات إلى النظام البيئي React. نهج مثير للاهتمام، لكنه يقاتل ضد نموذج React الأساسي بدلاً من العمل معه. اختبرنا القليل بسرعة ووجدنا حالات حدود مع Suspense وميزات متزامنة. إذا كنت تريد signals، Solid تعطيك التجربة الكاملة دون عدم التطابق.

هل من الصعب تعلم SolidJS من React؟ إذا كنت تعرف React بالفعل، API Solid ستبدو مألوفة—JSX مشابه، أنماط مشابهة. الجزء الصعب هو unlearn نموذج React. ستصل إلى useEffect patterns التي لا توجد. ستفصل props وتكسر reactivity. ستحاول early returns وتتساءل لماذا لا تعمل. يميت حوالي 1-2 أسبوع لمطور React متمرس ليصبح منتجاً في Solid، وشهر أو شهرين آخرين للتوقف عن كتابة Solid بنكهة React.

أي الإطار لديه دعم TypeScript أفضل؟ كلاهما لديهما دعم TypeScript ممتاز. Solid لديه ميزة طفيفة لأن المجمع يمكن أن يوفر أنواع أضيق في أنماط معينة (مثل callback في <Show>)، وأنت لا تحتاج إلى نفس حجم parameters نوع عام التي React hooks معقدة في الوقت قد تتطلب. لكنصراحة، كلاهما رائع. لا ينبغي أن يكون هذا عامل حاسم.

هل يجب أن أستخدم SolidJS للمشروع التالي؟ يعتمد على القيود الخاصة بك. إذا كنت فريقاً صغيراً تبني شيئاً حساس للأداء وأنت مستعد للاستثمار في منحنى التعلم وحل مشكلة النظام البيئي الأصغر، Solid اختيار ممتاز حقاً. إذا كنت تحتاج إلى تعيين مطورين React، واستخدام مكتبات مكونات محددة، أو تحتاج إلى meta-framework مُختبرة للإنتاج، React أرهان أكثر أماناً. لا توجد إجابة شاملة—فقط الإجابة الصحيحة للوضع المحدد الخاص بك. إذا كنت تريد الحديث عن القرار لمشروعك، تواصل معنا ويمكننا مساعدتك في تقييم المقايضات.