طرق تحسين الأداء وتحسينه في تطبيقات React

نشرت: 2022-03-10
ملخص سريع ↬ منذ تقديم React ، غيرت الطريقة التي يبني بها مطورو الواجهة الأمامية تطبيقات الويب ، ويشتهر DOM الافتراضي الخاص به بتقديم المكونات بشكل فعال. في هذا البرنامج التعليمي ، سنناقش طرقًا مختلفة لتحسين الأداء في تطبيقات React ، وكذلك ميزات React التي يمكننا استخدامها لتحسين الأداء.

يُمكِّن React تطبيقات الويب من تحديث واجهات المستخدم الخاصة بها (UIs) بسرعة ، لكن هذا لا يعني أن تطبيق React الكبير أو المتوسط ​​الخاص بك سيعمل بكفاءة. سيعتمد أداؤها على كيفية استخدامك لـ React عند بنائها ، وعلى فهمك لكيفية عمل React والعملية التي من خلالها تعيش المكونات خلال مراحل مختلفة من دورة حياتها. تقدم React الكثير من تحسينات الأداء لتطبيق ويب ، ويمكنك تحقيق هذه التحسينات من خلال تقنيات وميزات وأدوات متنوعة.

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

من أين تبدأ تحسين الأداء في تطبيق التفاعل؟

لا يمكننا البدء في تحسين تطبيق ما دون معرفة متى وأين يجب التحسين بالضبط. قد تسأل ، "من أين نبدأ؟"

أثناء عملية التصيير الأولية ، تُنشئ React شجرة DOM من المكونات. لذلك ، عندما تتغير البيانات في شجرة DOM ، فإننا نريد من React أن تعيد تصيير المكونات التي تأثرت بالتغيير فقط ، متخطية المكونات الأخرى في الشجرة التي لم تتأثر.

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

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

المزيد بعد القفز! أكمل القراءة أدناه ↓

قياس الأداء

لا تبدأ أبدًا عملية تحسين تطبيق React الخاص بك بناءً على ما تشعر به. بدلاً من ذلك ، استخدم أدوات القياس المتاحة لتحليل أداء تطبيق React الخاص بك والحصول على تقرير مفصل عما قد يؤدي إلى إبطائه.

تحليل مكونات التفاعل باستخدام علامة تبويب أداء Chrome

وفقًا لوثائق React ، بينما لا تزال في وضع التطوير ، يمكنك استخدام علامة التبويب "Performance" في متصفح Chrome لتصور كيفية تثبيت مكونات React وتحديثها وإلغاء تحميلها. على سبيل المثال ، تُظهر الصورة أدناه علامة تبويب "الأداء" في Chrome وهي توصيف وتحلل مدونتي في وضع التطوير.

ملخص ملف تعريف الأداء
ملخص ملف تعريف الأداء (معاينة كبيرة)

لكي تفعل هذا، اتبع هذه الخطوات:

  1. قم بتعطيل جميع الامتدادات مؤقتًا ، خاصة أدوات مطور React ، لأنها يمكن أن تعبث بنتيجة التحليل. يمكنك بسهولة تعطيل الملحقات عن طريق تشغيل متصفحك في وضع التصفح المتخفي.
  2. تأكد من تشغيل التطبيق في وضع التطوير. وهذا يعني أن التطبيق يجب أن يعمل على مضيفك المحلي.
  3. افتح أدوات مطوري Chrome ، وانقر فوق علامة التبويب "الأداء" ، ثم انقر فوق الزر "تسجيل".
  4. قم بتنفيذ الإجراءات التي تريد تشكيلها. لا تسجل أكثر من 20 ثانية ، وإلا فقد يتعطل Chrome.
  5. أوقف التسجيل.
  6. سيتم تجميع أحداث React تحت عنوان "توقيت المستخدم".

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

رد فعل ملف التعريف أدوات المطور

وفقًا لوثائق React ، في react-dom 16.5+ وتفاعل react-native 0.57+ ، تتوفر إمكانات التنميط المحسّنة في وضع المطور باستخدام React Developer Tools Profiler. يستخدم ملف التعريف واجهة برمجة تطبيقات Profiler التجريبية الخاصة بـ React لجمع معلومات التوقيت حول كل مكون يتم عرضه ، من أجل تحديد اختناقات الأداء في تطبيق React.

ما عليك سوى تنزيل React Developer Tools لمتصفحك ، وبعد ذلك يمكنك استخدام أداة التعريف المرفقة معها. يمكن استخدام أداة التعريف فقط إما في وضع التطوير أو في إنشاء ملف تعريف الإنتاج لـ React v16.5 +. الصورة أدناه هي ملخص ملف التعريف لمدونتي في وضع التطوير باستخدام React Developer Tools Profiler:

تفاعل أدوات المطور منشئ ملفات التعريف flamegraph
React Developer Tools Profiler flamegraph (معاينة كبيرة)

لتحقيق ذلك ، اتبع الخطوات التالية:

  1. قم بتنزيل أدوات المطورين React.
  2. تأكد من أن تطبيق React الخاص بك إما في وضع التطوير أو في بناء ملف تعريف الإنتاج لـ React v16.5 +.
  3. افتح علامة التبويب "أدوات المطور" في Chrome. ستتوفر علامة تبويب جديدة تسمى "منشئ ملفات التعريف" ، مقدمة من React Developer Tools.
  4. انقر فوق الزر "تسجيل" ، وقم بتنفيذ الإجراءات التي تريد تشكيلها. من الناحية المثالية ، توقف عن التسجيل بعد قيامك بالإجراءات التي تريد تشكيلها.
  5. سيظهر الرسم البياني (المعروف باسم flamegraph) مع كل معالجات الأحداث ومكونات تطبيق React الخاص بك.

ملاحظة : انظر الوثائق لمزيد من المعلومات.

Memoization مع React.memo()

تم إصدار React v16 بواجهة برمجة تطبيقات (API) إضافية ، مكون ذو رتبة أعلى يسمى React.memo() . وفقًا للوثائق ، يوجد هذا فقط كتحسين للأداء .

اسمها ، " memo " يأتي من memoization ، وهو في الأساس شكل من أشكال التحسين يستخدم بشكل أساسي لتسريع الكود عن طريق تخزين نتائج مكالمات الوظائف باهظة الثمن وإعادة النتيجة المخزنة كلما تم استدعاء نفس الوظيفة باهظة الثمن مرة أخرى.

Memoization هي تقنية لتنفيذ وظيفة مرة واحدة ، وعادة ما تكون وظيفة نقية ، ثم حفظ النتيجة في الذاكرة. إذا حاولنا تنفيذ هذه الوظيفة مرة أخرى ، باستخدام نفس الوسيطات السابقة ، فستعيد النتيجة المحفوظة مسبقًا من تنفيذ الوظيفة الأولى ، دون تنفيذ الوظيفة مرة أخرى.

عند تعيين الوصف أعلاه لنظام React البيئي ، فإن الوظائف المذكورة هي مكونات React والوسيطات عبارة عن دعائم.

السلوك الافتراضي للمكون المُعلن باستخدام React.memo() هو أنه يتم عرضه فقط إذا تغيرت الخاصيات في المكون. يقوم بإجراء مقارنة ضحلة للدعائم للتحقق من ذلك ، ولكن يتوفر خيار لتجاوز ذلك.

يعزز React.memo() أداء تطبيق React عن طريق تجنب إعادة عرض المكونات التي لم تتغير خصائصها أو عندما لا تكون هناك حاجة لإعادة العرض.

الكود أدناه هو بناء الجملة الأساسي لـ React.memo() :

 const MemoizedComponent = React.memo((props) => { // Component code goes in here })

متى تستخدم React.memo()

  • مكون وظيفي خالص
    يمكنك استخدام React.memo() إذا كان المكون الخاص بك وظيفيًا ، وتم إعطاؤه نفس الخاصيات ، وعرض نفس الإخراج دائمًا. يمكنك أيضًا استخدام React.memo() على مكونات غير وظيفية خالصة مع خطافات React.
  • يتم عرض المكون في كثير من الأحيان
    يمكنك استخدام React.memo() لالتفاف مكون يتم عرضه كثيرًا.
  • يعيد المكون تصيير نفس الدعائم
    استخدم React.memo() لالتفاف مكون يتم توفيره عادةً بنفس الخاصيات أثناء إعادة التصيير.
  • متوسطة إلى عالية العناصر
    استخدمه لمكون يحتوي على عدد متوسط ​​إلى مرتفع من عناصر واجهة المستخدم للتحقق من المساواة.

ملاحظة : كن حذرًا عند حفظ المكونات التي تستخدم الدعائم كردود نداء. تأكد من استخدام نفس مثيل وظيفة رد الاتصال بين عمليات العرض. هذا لأن المكون الرئيسي يمكن أن يوفر مثيلات مختلفة لوظيفة رد الاتصال في كل تصيير ، مما سيؤدي إلى تعطل عملية التذكر. لإصلاح ذلك ، تأكد من أن المكون المذكر يتلقى دائمًا نفس مثيل رد الاتصال.

دعونا نرى كيف يمكننا استخدام الذاكرة في المواقف الواقعية. المكون الوظيفي أدناه ، المسمى "صورة" ، يستخدم React.memo() لمنع إعادة العرض.

 export function Photo({ title, views }) { return ( <div> <div>Photo title: {title}</div> <div>Location: {location}</div> </div> ); } // memoize the component export const MemoizedPhoto = React.memo(Photo);

يتكون الرمز أعلاه من مكون وظيفي يعرض div يحتوي على عنوان الصورة وموقع الموضوع في الصورة. نحن أيضًا نحفظ المكون من خلال إنشاء وظيفة جديدة MemoizedPhoto . ستؤدي ميزة Memoating مكون الصورة إلى منع المكون من إعادة العرض طالما أن العناصر title location هي نفسها في عمليات التصيير اللاحقة.

 // On first render, React calls MemoizedPhoto function. <MemoizedPhoto title="Effiel Tower" location="Paris" /> // On next render, React does not call MemoizedPhoto function, // preventing rendering <MemoizedPhoto title="Effiel Tower" location="Paris" />

هنا ، تستدعي React الوظيفة المذكرة مرة واحدة فقط. لن يتم عرض المكون في المكالمة التالية طالما ظلت الخاصيات كما هي.

التجميع والتصغير

في تطبيقات React أحادية الصفحة ، يمكننا تجميع وتصغير جميع أكواد JavaScript في ملف واحد. هذا جيد ، طالما أن طلبنا صغير نسبيًا.

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

في مثل هذه الحالة ، يمكننا استخدام شكل من أشكال تجميع الأصول مثل Webpack ، ثم الاستفادة من وظيفة تقسيم الكود لتقسيم تطبيقنا إلى ملفات متعددة.

يُقترح تقسيم الشفرة في وثائق Webpack كوسيلة لتحسين وقت تحميل التطبيق. يُقترح أيضًا في وثائق React للتحميل البطيء (خدمة فقط الأشياء التي يحتاجها المستخدم حاليًا) ، والتي يمكن أن تحسن الأداء بشكل كبير.

يقترح Webpack ثلاث طرق عامة لتقسيم الشفرة:

  • نقاط الدخول
    يدويا تقسيم التعليمات البرمجية باستخدام تكوين الإدخال.
  • منع الازدواجية
    استخدم SplitChunksPlugin تكرار القطع وتقسيمها.
  • الواردات الديناميكية
    انقسام الكود عبر استدعاءات الوظائف المضمنة داخل الوحدات.

فوائد تقسيم الكود

  • يساعد تقسيم الكود في موارد ذاكرة التخزين المؤقت للمتصفح ومع التعليمات البرمجية التي لا تتغير كثيرًا.
  • كما أنه يساعد المتصفح على تنزيل الموارد بالتوازي ، مما يقلل من وقت التحميل الإجمالي للتطبيق.
  • إنها تمكننا من تقسيم الكود إلى أجزاء يتم تحميلها عند الطلب أو حسب الحاجة بواسطة التطبيق.
  • إنها تحافظ على التنزيل الأولي للموارد عند العرض الأول صغيرًا نسبيًا ، وبالتالي تقليل وقت تحميل التطبيق.
عملية التجميع والتصغير
عملية التجميع والتصغير (معاينة كبيرة)

هياكل البيانات غير القابلة للتغيير

تتحدث وثائق React عن قوة عدم تغيير البيانات. أي بيانات لا يمكن تغييرها غير قابلة للتغيير. الثبات هو مفهوم يجب على مبرمجي React فهمه.

لا يمكن تغيير قيمة أو كائن غير قابل للتغيير. لذلك ، عندما يكون هناك تحديث ، يتم إنشاء قيمة جديدة في الذاكرة ، مع ترك القيمة القديمة كما هي.

يمكننا استخدام هياكل البيانات غير القابلة للتغيير و React.PureComponent للتحقق تلقائيًا من حدوث تغيير معقد في الحالة. على سبيل المثال ، إذا كانت الحالة في التطبيق الخاص بك غير قابلة للتغيير ، يمكنك في الواقع حفظ جميع كائنات الحالة في متجر واحد باستخدام مكتبة لإدارة الحالة مثل Redux ، مما يتيح لك تنفيذ وظائف التراجع والإعادة بسهولة.

لا تنس أنه لا يمكننا تغيير البيانات غير القابلة للتغيير بمجرد إنشائها.

فوائد هياكل البيانات غير القابلة للتغيير

  • ليس لديهم آثار جانبية.
  • من السهل إنشاء واختبار واستخدام كائنات البيانات غير القابلة للتغيير.
  • إنها تساعدنا في كتابة منطق يمكن استخدامه للتحقق بسرعة من التحديثات في الحالة ، دون الحاجة إلى التحقق من البيانات مرارًا وتكرارًا.
  • إنها تساعد على منع الاقتران الزمني (نوع من الاقتران يعتمد فيه الكود على ترتيب التنفيذ).

تساعد المكتبات التالية في توفير مجموعة من هياكل البيانات غير القابلة للتغيير:

  • مساعد الثبات
    تحويل نسخة من البيانات دون تغيير المصدر.
  • غير قابل للتغيير
    تزيد مجموعات البيانات الثابتة غير القابلة للتغيير لجافا سكريبت الكفاءة والبساطة.
  • سلس غير قابل للتغيير
    تصبح هياكل البيانات غير القابلة للتغيير لجافا سكريبت متوافقة مع مصفوفات وكائنات جافا سكريبت العادية.
  • رد فعل نسخ وكتابة
    هذا يعطي حالة ثابتة مع واجهة برمجة تطبيقات قابلة للتغيير.

طرق أخرى لتحسين الأداء

استخدم بناء الإنتاج قبل النشر

تقترح وثائق React استخدام بنية الإنتاج المصغرة عند نشر تطبيقك.

تحذير "إصدار الإنتاج" الخاص بـ React Developer Tools
تحذير "إصدار الإنتاج" الخاص بأدوات React Developer (معاينة كبيرة)

تجنب الوظائف المجهولة

نظرًا لأنه لا يتم تعيين معرِّف للوظائف المجهولة (عبر const/let/var ) ، فإنها لا تكون ثابتة عندما يتم عرض أحد المكونات مرة أخرى حتمًا. يؤدي هذا إلى تخصيص JavaScript لذاكرة جديدة في كل مرة يتم فيها إعادة عرض هذا المكون ، بدلاً من تخصيص جزء واحد من الذاكرة مرة واحدة فقط ، كما هو الحال عند استخدام الوظائف المسماة.

 import React from 'react'; // Don't do this. class Dont extends Component { render() { return ( <button onClick={() => console.log('Do not do this')}> Don't </button> ); } } // The better way class Do extends Component { handleClick = () => { console.log('This is OK'); } render() { return ( <button onClick={this.handleClick}> Do </button> ); } }

يوضح الكود أعلاه طريقتين مختلفتين لجعل الزر ينفذ إجراءً عند النقر. تستخدم كتلة التعليمات البرمجية الأولى وظيفة مجهولة في خاصية onClick() ، وهذا من شأنه أن يؤثر على الأداء. تستخدم كتلة التعليمات البرمجية الثانية وظيفة مسماة في وظيفة onClick() ، وهي الطريقة الصحيحة في هذا السيناريو.

غالبًا ما تكون مكونات التركيب والفك مكلفة

لا يُنصح باستخدام الشروط الشرطية أو الأوتار لإخفاء أحد المكونات (أي لإلغاء تثبيته) ، لأن المكون الذي تم جعله يختفي سيؤدي إلى إعادة رسم المتصفح وتدفقه. هذه عملية مكلفة لأنه سيتعين إعادة حساب المواضع والأشكال الهندسية لعناصر HTML في المستند. بدلاً من ذلك ، يمكننا استخدام خصائص opacity visibility لـ CSS لإخفاء المكون. بهذه الطريقة ، سيظل المكون موجودًا في DOM ولكنه غير مرئي ، دون أي تكلفة على الأداء.

افتراضية القوائم الطويلة

تقترح الوثائق أنه إذا كنت تعرض قائمة تحتوي على كمية كبيرة من البيانات ، فيجب عليك عرض جزء صغير من البيانات في القائمة في وقت واحد ضمن إطار العرض المرئي. بعد ذلك ، يمكنك تقديم المزيد من البيانات أثناء التمرير في القائمة ؛ ومن ثم ، لا يتم عرض البيانات إلا عندما تكون في منفذ العرض. هذه العملية تسمى "النوافذ". في النافذة ، يتم عرض مجموعة فرعية صغيرة من الصفوف في أي وقت. هناك مكتبات شائعة للقيام بذلك ، ويحتفظ برايان فون باثنتين منها:

  • رد الفعل نافذة
  • رد الفعل الافتراضي

خاتمة

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

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

المراجع والمصادر ذات الصلة

  • "تحسين الأداء" ، React Docs
  • "استخدم React.memo بحكمة" ، ديمتري بافلوتين
  • "تقنيات تحسين الأداء في التفاعل" ، نيتيش ياداف
  • "الثبات في التفاعل: لا يوجد شيء خاطئ مع الأشياء المتغيرة" ، إستيبان هيريرا
  • "10 طرق لتحسين أداء تطبيق React الخاص بك" ، Chidume Nnamdi
  • "5 نصائح لتحسين أداء تطبيقات React الخاصة بك" ، William Le