نظرة عملية على مُجمِّع رياكت (React Compiler) لتحسين الأداء

مقدمة: مشكلة الأداء في React

من أهم المشاكل التي تواجه التطبيقات المبنية باستخدام React هي المشاكل المتعلقة بالأداء. تعود معظم هذه المشاكل إلى الطريقة التي تعمل بها React أساسًا. تقوم React بجلب المكون (Component) الذي كتبناه وتراقب حالته (State) وخصائصه (Props). بمجرد أن تلاحظ تغييرًا في الحالة أو الخصائص، تعيد رسم هذا المكون، وهي عملية تُسمى “إعادة الرسم” (Re-render).

عملية إعادة الرسم هذه مكلفة من ناحية الأداء، لذلك يجب علينا قدر الإمكان تقليل عمليات إعادة الرسم، خصوصًا تلك التي لا داعي لها.

الأدوات الحالية لتحسين الأداء

للقيام بذلك أثناء الكتابة باستخدام React، نستخدم واجهات برمجة تطبيقات (APIs) تأتي مع المكتبة نفسها، مثل:

كلاهما (useMemo و useCallback) عبارة عن Hooks، وحتى أن هناك React.memo وهي واجهة برمجة تطبيقات موجودة داخل React يمكننا استخدامها للحد من عمليات إعادة الرسم غير الضرورية.

أحيانًا، بسبب سوء استخدام من المطور، قد ينسى أو يخطئ في تقدير أن أمرًا ما بسيط، فلا يرغب بوضعه داخل useMemo أو أي أداة أخرى، مما قد يؤدي إلى أن يقوم المكون بعمليات إعادة رسم دون داعٍ، وهو ما يؤدي إلى سوء أداء في التطبيق.

الحل: مُجمِّع رياكت (React Compiler)

لحل هذه المشكلة، أعلنت React منذ عام تقريبًا عن مُجمِّع (Compiler)، وفي ذلك الوقت كان عبارة عن مكتبة أطلقوا عليها اسم React Forget (على عكس React.memo). الفكرة هي أن المطور سينسى استخدام أدوات التحسين (Memoization)، وكل هذه الأمور ستحدث تلقائيًا أثناء وقت البناء (Build Time) عن طريق المجمّع. لاحقًا، غيروا الاسم إلى React Compiler، فأصبح البحث عنه أسهل.

حتى الآن، React Compiler ليس مستقرًا بعد، ولكن في هذا المقال، سنلقي نظرة عليه ونرى كيف يعمل، وسنقوم بتجربته أيضًا في أحد التطبيقات التي أعمل عليها حاليًا لنرى هل سيُحسن الأداء أم لا. لنبدأ.

نظرة على الوثائق الرسمية

داخل موقع react.dev، هذه هي الوثائق المتعلقة بـ React Compiler.

ملاحظة هامة: لا يزال React Compiler قيد الإنشاء وغير جاهز للاستخدام الإنتاجي. يمكنك استخدامه على مسؤوليتك. حاليًا، المنتجات داخل شركة Meta (Facebook سابقًا) تستخدم React Compiler، مثل Instagram، وقد صرحوا كيف حسّن المجمّع من أداء Instagram. لكنه لا يزال غير مستقر، فإذا استخدمته داخل تطبيق إنتاجي، فإنك ستستخدمه على مسؤوليتك.

تذكر الوثائق أن React Compiler لا يزال في مرحلة البيتا وهو مفتوح المصدر لتجربته وتزويدنا بالآراء والملاحظات.

يذكرون دائمًا أن React Compiler يعمل فقط إذا اتبعت قواعد كتابة React. فإذا كان تطبيقك غير صالح من الأساس، فلن يعمل المجمّع عليه. ولكن إذا كان لديك تطبيق React جاهز وشغال وأردت إضافة المجمّع إليه، سيعمل دون أن تقوم بأي شيء إضافي على قاعدة الكود الحالية.

سيعمل React Compiler بشكل أساسي مع React 19، ولكن هناك دعم للإصدارين 18 و 17 عن طريق مكتبة إضافية.

كيف يعمل React Compiler؟

بشكل بسيط، إذا كان تطبيقك يستخدم useMemo، useCallback، أو React.memo بشكل صحيح، فلن تحتاج إلى المجمّع. مهمته الوحيدة هي إضافة هذه الاستخدامات في الأماكن التي نسينا إضافتها فيها أو تكاسلنا عن ذلك. على سبيل المثال، عندما ترغب بإرسال دالة رد نداء (Callback) لأحد المكونات وتقوم بكتابتها مباشرة (inline) دون وضعها داخل useCallback، فإن هذا يؤثر على الأداء ويجعل المكون يعيد الرسم. سيصلح المجمّع كل هذه المشاكل. إذا كنت قد كتبت مشروعك بشكل صحيح من البداية، فقد لا تلاحظ فرقًا كبيرًا بعد إضافة React Compiler.

ملاحظة هامة: يعمل React Compiler فقط إذا كان تطبيقك يتبع قواعد React بشكل صحيح. أي مكون يحتوي على مشاكل في القواعد الرئيسية لـ React (مثل استخدام خاطئ للـ Hooks) لن يعمل المجمّع داخله، ولكنه سيتابع عمله في المكونات الأخرى.

تأتي مع المجمّع إضافة لـ ESLint (eslint-plugin-react-compiler) ستظهر لك الأخطاء في الكود التي قد تعطل عمل المجمّع. لا داعي لحل كل هذه الأخطاء فورًا، ولكن لاحظ أن أي مكون به خطأ لن يتم تجميعه.

البدء باستخدام React Compiler

لتثبيت المجمّع، ستحتاج إلى الحزم التالية:

المجمّع هو إضافة لـ Babel، فإذا كان مشروعك يحتوي على Babel بالفعل، ستقوم فقط بجلب الإضافة وإضافتها.

مع React 17 و 18

يعمل المجمّع بشكل رئيسي مع React 19، ولكن إذا كان لديك كود يستخدم الإصدار 18 أو 17، يمكنك استخدامه عن طريق إضافة مكتبة react-compiler-runtime:

npm install react-compiler-runtime

ثم يجب تحديد هذا الهدف في إعدادات Babel.

إعدادات Babel

هذه هي طريقة إضافة React Compiler إلى ملف إعدادات Babel:

// babel.config.js
module.exports = {
  plugins: [
    ["babel-plugin-react-compiler", {}], // options object is optional
  ],
};

إعدادات Vite

إذا كنت تستخدم Vite، يمكنك تثبيت إضافة Babel وتهيئتها بهذا الشكل:

// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          ["babel-plugin-react-compiler", {}],
        ],
      },
    }),
  ],
});

إعدادات Next.js

أنا أستخدم Next.js، وسأقوم بعمل عرض توضيحي على تطبيق يستخدمه. في Next.js 15، تمت إضافة دعم تجريبي لـ React Compiler.

تجربة عملية على تطبيق Next.js

هذا هو التطبيق الذي سأجرب عليه React Compiler. هو عبارة عن أداة لبناء تدفقات العمل في المتصفح. سأقوم بتجربته قبل وبعد تفعيل المجمّع لأرى كيف سيتحسن الأداء.

قياس الأداء قبل التفعيل

لكي نقيس عمليات إعادة الرسم، هناك عدة أدوات، أهمها React DevTools. وهناك أداة ظهرت حديثًا اسمها React Scan، وهي أسهل في التشغيل وتحتوي على ميزات أكثر، لذلك سأستخدمها في هذا المقال.

لإضافة React Scan إلى المشروع، نأخذ هذا السكريبت ونضيفه داخل وسم <head> في ملف layout.tsx:

<script src="https://cdn.jsdelivr.net/npm/react-scan@latest/dist/react-scan.min.js"></script>

بعد إضافته، يُظهر التطبيق مربعات بنفسجية حول المكونات التي يتم إعادة رسمها. عند إضافة خطوات جديدة أو توسيعها، نلاحظ حدوث عمليات إعادة رسم. بعضها إجباري، وبعضها غير ضروري ويجب إيقافه.

تفعيل React Compiler في Next.js

  1. تثبيت المكتبة: أولاً، نقوم بتثبيت مكتبة المجمّع.

    npm install babel-plugin-react-compiler
    
  2. تحديث إعدادات Next.js: بعد ذلك، نذهب إلى ملف next.config.mjs ونقوم بتفعيل React Compiler بهذا الشكل:

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      experimental: {
        reactCompiler: true,
      },
    };
    
    export default nextConfig;
    

أنا أستخدم React 19 في هذا التطبيق، لذلك يمكنني استخدام React Compiler دون الحاجة لإضافة حزمة runtime.

النتائج بعد التفعيل

بعد حفظ التغييرات وإعادة تشغيل التطبيق، نلاحظ أن الأداء تحسن وعدد عمليات إعادة الرسم قل بشكل ملحوظ.

خلاصة

إضافة React Compiler على تطبيق Next.js سيكون سهلاً جداً، خصوصًا إذا كان التطبيق حديثًا ويستخدم React 19. وحتى لو كنت تستخدم الإصدار 17 أو 18، فالأمر سهل أيضًا، حيث ستحتاج فقط إلى إضافة runtime الخاص بالمجمّع.

شارك المقال

أحدث المقالات

CONNECTED
ONLINE: ...
SECURE
00:00:00