طوال عقد كامل، كان جعل React سريعًا يعني رشّ useMemo وuseCallback وReact.memo يدويًا عبر المكوّنات. عملٌ ممل، سهل الخطأ، ويستحيل تطبيقه في المواضع الأشدّ حاجةً إليه. مترجم React 1.0 يقلب الوضع الافتراضي: المترجم يقرأ شيفرتك ويضيف التخزين المناسب نيابةً عنك، وقت البناء.
يشرح هذا الدليل ما يفعله مترجم React 1.0 فعليًا، وكيفية تثبيته في Vite وNext.js، وخيارات الإعداد المهمّة، وكيفية تبنّيه في مشروع قائم دون كسر أي شيء.
المشكلة التي لم يحلّها التخزين اليدوي قط
تعيد React رسم المكوّن كلما تغيّرت حالته أو خصائصه، وافتراضيًا تعيد رسم الشجرة الفرعية بأكملها تحته. لإيقاف العمل المهدور، يلجأ المطوّرون إلى ثلاث أدوات:
useMemoلتخزين قيمة محسوبة مكلفةuseCallbackلإبقاء مرجع الدالة ثابتًا بين عمليات الرسمReact.memoلتخطّي إعادة رسم مكوّن ابن عند ثبات خصائصه
النمط يعمل، لكن له تكاليف حقيقية. عليك صيانة مصفوفات الاعتماديات يدويًا، والاعتمادية المفقودة أو القديمة مصدر كلاسيكي للأخطاء. كما تُلوّث منطق العمل بضوضاء التحسين. والأسوأ أنك لا تستطيع التخزين بعد عبارة return شرطية — فقواعد الـ Hooks تمنع استدعاء useMemo بعد الخروج المبكر، وهو بالضبط حيث يقبع كثير من العمل المكلف.
يزيل مترجم React التخمين. يحلّل تدفّق البيانات وقابلية التغيير في كل مكوّن، ثم يُدرج التخزين تلقائيًا — حتى في مواضع يعجز عنها الإنسان، مثل ما بعد الخروج المبكر، وسلاسل الوصول الاختيارية، والوصول عبر فهارس المصفوفات.
ما الذي يأتي به مترجم React 1.0
إصدار 1.0، الذي استقرّ بعد سنوات من الاختبار الميداني داخل Meta، هو أول نسخة مستقرّة. أبرز الأرقام من طرحه الإنتاجي لدى Meta:
- التحميل الأولي والتنقّل بين الصفحات أسرع بنسبة تصل إلى 12 بالمئة
- تفاعلات محدّدة أسرع بما يصل إلى 2.5 ضعف
- استهلاك الذاكرة يبقى محايدًا
أبعد من السرعة الخام، يجلب 1.0 ثلاثة أمور تهمّ التبنّي. صار جزءًا من قوالب create-vite وcreate-next-app وcreate-expo-app، فتبدأ المشاريع الجديدة مُحسَّنة. وتأتي قواعد التدقيق ضمن eslint-plugin-react-hooks، مُرسِّخةً قواعد React وملتقطةً أخطاءً مثل استدعاء setState أثناء الرسم. وهناك مسار تجريبي عبر إضافة SWC لـ Next.js يُبقي البناء سريعًا دون خطّ Babel الكامل.
التثبيت في مشروع Vite
يعمل مترجم React كإضافة Babel. ثبّته كاعتمادية تطوير مثبّتة الإصدار بدقّة — تثبيت الإصدار موصى به حتى تكتمل تغطية اختباراتك، لأن إزالة التخزين أو تغييره قد يبدّل المُخرَج بصورة خفيّة.
pnpm add -D babel-plugin-react-compiler@latestمع @vitejs/plugin-react بإصدار 6 أو أحدث، وصّله عبر إعداد المترجم المسبق:
// vite.config.js
import { defineConfig } from 'vite';
import react, { reactCompilerPreset } from '@vitejs/plugin-react';
import babel from '@rolldown/plugin-babel';
export default defineConfig({
plugins: [
react(),
babel({
presets: [reactCompilerPreset()],
}),
],
});إذا أعددت Babel مباشرةً، يجب أن تعمل إضافة المترجم أولًا في قائمة الإضافات:
// babel.config.js
module.exports = {
plugins: [
'babel-plugin-react-compiler', // يجب أن تعمل أولًا
// ...إضافات أخرى
],
};التثبيت في Next.js
يغلّف Next.js المترجم بتحسين SWC مخصّص لا يطبّقه إلا على الملفات التي تحوي JSX أو Hooks، فيبقى البناء سريعًا. اعتبارًا من Next.js 16 صار الخيار راية إعداد على المستوى الأعلى. ثبّت إضافة Babel ثم فعّله:
npm install -D babel-plugin-react-compiler// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
reactCompiler: true,
};
export default nextConfig;هذا كامل الإعداد لتطبيق React 19. لا مصفوفات اعتماديات تلمسها، ولا مكوّنات تعيد كتابتها.
خيارات الإعداد المهمّة
معظم تطبيقات React 19 لا تحتاج أي إعداد. وعندما تحتاج تحكّمًا، تستحقّ أربعة خيارات وزنها.
compilationMode يقرّر أي الدوال يطالها المترجم. الافتراضي يستنتج المجموعة الصحيحة. اضبطه على 'annotation' للتبنّي بالاشتراك الاختياري، حيث لا تُترجَم سوى الدوال التي توسمها بتوجيه "use memo":
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
compilationMode: 'annotation',
}],
],
};target يخبر المترجم بإصدار React الذي يولّد له. الافتراضي '19'. لتطبيقات React 17 أو 18، اضبطه صراحةً وأضف حزمة وقت التشغيل:
['babel-plugin-react-compiler', {
target: '18', // أيضًا: pnpm add react-compiler-runtime
}]panicThreshold يتحكّم بما يحدث حين يصطدم المترجم بشيفرة لا يستطيع تحسينها بأمان. ضبطه على 'none' يتخطّى ذلك المكوّن بدل إفشال البناء — وهو الوضع الموصى به للإنتاج.
gating يتيح وضع المُخرَج المُترجَم خلف راية ميزة وقت التشغيل، فتطرح المترجم لنسبة من المستخدمين وتقارن قبل الالتزام.
التبنّي في مشروع قائم
المسار الآمن في تطبيق ناضج تدريجيّ. ابدأ بوضع 'annotation' كي لا يتغيّر شيء حتى تُشرك مكوّنًا عبر "use memo". تحقّق من السلوك ثم وسّع الشبكة.
يمكنك أيضًا استثناء أي مكوّن يسيء المترجم التعامل معه بإضافة توجيه الاستثناء أعلى جسمه:
function LegacyChart() {
"use no memo";
// يتخطّى المترجم هذا المكوّن
}أما استدعاءات useMemo وuseCallback القائمة لديك، فالإرشاد متحفّظ: اتركها في مكانها أولًا. إزالة التخزين اليدوي قد تغيّر المُخرَج المرسوم إن كانت الشيفرة الأصلية تعتمد على حدّ تخزين بعينه. ومتى عمل المترجم ونجحت اختباراتك، احذف الـ Hooks المكتوبة يدويًا تدريجيًا ودع المترجم يتولّى الأمر. للشيفرة الجديدة، اعتمد على المترجم افتراضيًا، ولا تلجأ إلى useMemo أو useCallback إلا كمنافذ هروب مقصودة.
الخطوة الأخرى غير القابلة للتفاوض هي أداة التدقيق. ثبّت أحدث eslint-plugin-react-hooks واستخدم إعداده الموصى به:
npm install -D eslint-plugin-react-hooks@latestالمترجم بجودة الشيفرة التي يحلّلها فحسب. قواعد التدقيق تفرض قواعد React التي يفترضها المترجم — مكوّنات نقيّة، ولا تغيير أثناء الرسم، وترتيب ثابت للـ Hooks — وتُظهر المخالفات قبل وصولها إلى البناء.
هل تُفعّله؟
إن كنت على React 19 وتبدأ مشروعًا جديدًا، فالجواب نعم — هو في القوالب أصلًا. ولتطبيق قائم، فميزان التكلفة والعائد قويّ: تسريع قابل للقياس، وشيفرة تحسين أقلّ تصونها، وصنفٌ كامل من أخطاء الاعتماديات القديمة يزول. والمخاطرة محدودة لأن التبنّي تدريجيّ وقابل للتراجع لكل مكوّن على حدة.
التحوّل الأكبر مفاهيميّ. ينتقل تخزين الأداء من انضباط يدويّ تحمله في كل مراجعة شيفرة إلى ضمان وقت بناء. وكما عبّر فريق React، فهذا الإصدار المستقرّ يُقصد به أن يكون «أساسًا وعصرًا جديدًا للعقد القادم وما بعده من React». ولفرق منطقة الشرق الأوسط وشمال إفريقيا التي تطلق تطبيقات React، يعني هذا تجارب أسرع على الأجهزة الأضعف والشبكات الأبطأ — بشيفرة أقلّ تُكتب وتُصان للوصول إلى ذلك.
ابدأ بوضع 'annotation' على ميزة واحدة، قِس، ثم وسّع. المترجم يتولّى الجزء الممل لتصرف انتباهك على المنتج.