Material-ui: تحسين أداء Material-UI

تم إنشاؤها على ٢٣ مارس ٢٠١٨  ·  93تعليقات  ·  مصدر: mui-org/material-ui

أولاً ، شكرًا جزيلاً لك على مكتبة المكونات الرائعة هذه! انه لشيء رائع!

لقد أضفت درجًا في تطبيقي الجديد. في الغالب ، قمت بطباعة مثال درج. فقط من أجل PoC أنا تضاعفت

        <Divider />
        <List>{mailFolderListItems}</List>

الجزء.

بعد ذلك ، يبدو الأمر بطيئًا للغاية ، خاصة على الجهاز المحمول (nexus 4 ، cordova with crosswalk 20). أستخدم وضع dev ، لكن وضع prod لا يسرع كثيرًا.

من خلال أدوات تطوير التفاعل ، لاحظت أن المكونات الموجودة في mailFolderListItems يتم عرضها على كل نقرة على رابط في جهاز التوجيه التفاعلي أو حتى فتح القائمة. يستغرق الأمر ما يصل إلى 50-60 مللي ثانية لإعادة عرض ONE {mailFolderListItems} . أنا أستعمل

const modalProps = {
    keepMounted: true, // Better open performance on mobile.
};

للتخلص من عدم اليقين مع مكونات التطبيق الأخرى ، قمت بتحويل mailFolderListItems إلى مكون وقمت بتعطيل العرض:

class MailFolderListItems extends React.Component<{}, {}> {

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <List>
                <Link to={Routes.Startpage.path}>
                    <ListItem>
                        <ListItemIcon>
                            <InboxIcon />
                        </ListItemIcon>
[...]


                <Divider />
                <MailFolderListItems />

بعد ذلك يبدو هذا الجزء على ما يرام.

لقد وجدت https://github.com/mui-org/material-ui/issues/5628 . أقترح إعادة النظر فيه . يعد تحسين shouldComponentUpdate خطوة أساسية وأهم للحصول على الأداء. PureComponent هو الاختصار الأكثر شيوعًا.

علاوة على ذلك ، لاحظت أنه يتم إنفاق الكثير من الوقت (1-2 مللي ثانية وأكثر لكل مكون من مكونات واجهة المستخدم المادية) في WithStyles .

  • [x] لقد بحثت في قضايا هذا المستودع وأعتقد أن هذه ليست نسخة مكررة.

سلوك متوقع

أتوقع الحصول على معظم أداء التفاعل المحتمل لهذه المكتبة الرائعة.

السلوك الحالي

يصبح التطبيق أبطأ مع كل مكون من مكونات واجهة المستخدم المادية.

خطوات إعادة الإنتاج (للحشرات)

لا أقدم إعادة إنتاج المثال حتى الآن ، لأنني قمت فقط بنسخ نسخة من صفحة العرض التوضيحي للمكون ، ولكن إذا لزم الأمر ، يمكنني تقديم عرض الكود وعلبة العرض. بالنسبة للمتصفح ، يكون ذلك ملحوظًا ، إذا تباطأ المتصفح حسب العامل> = 5x في إعداد الأداء.

بيئتك

| التقنية | الإصدار |
| -------------- | --------- |
| واجهة المستخدم المادية | 1.0.0 بيتا 38 |
| أيقونات واجهة المستخدم المادية | 1.0.0 بيتا 36 |
| رد فعل | 16.2.0 |
| متصفح | كوردوفا معبر 20 (يساوي أندرويد كروم 50) |

discussion performance

التعليق الأكثر فائدة

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

فقط لأجلك أقوم بتقليصه إلى 10 أزرار. 10! انها تعني أي 10 مكونات (أسوأ من ذلك: حاويات) من تباطؤ مادي-واجهة المستخدم أسفل التطبيق بأكمله حتى التطبيق غير صالح للاستخدام! تم اختباره على جهاز حقيقي مع Crosswalk 21 / chrome 51 بدون أي دواسة الوقود:

الزر العادي:
image

PureButton:
image

هذا لا يزال تحسن 8x! انه ضخم! هل يمكنك تخيل مدى أهمية هذا على الجهاز المحمول؟

بدلاً من 100 زر ، ستجد 10 أزرار على الأكثر في الصفحة. ومع ذلك ، ستجد 10 شبكات ، 10 X ، إلخ.

لقد استخدمت Button لأنه أحد أبسط المكونات! فإنه يدل على أن واجهة المستخدم، يتم تقسيم المواد من جهة نظر الأداء. الآن ، تخيل مكونات حاوية مثل AppBar ، Toolbar ، List ، Drawer! هذا أسوأ! تحصل بسرعة كبيرة على 20 مكونًا / حاوية في كل صفحة. ولأنك لا تنتهي صلاحية أي بطء على سطح المكتب / جهاز Mac القوي ، فهذا لا يعني أن واجهة المستخدم المادية ليست بطيئة بشكل لا يصدق.

رد فعل-intl ، فإن الاختيار بين الدعائم السابقة والجديدة سيكون دائمًا خاطئًا. سوف تضيع دورات وحدة المعالجة المركزية. لذا x13 -> x0.8

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

راجع للشغل: WithStyles تستهلك ما يصل إلى 2،27 مللي ثانية للزر الموجود على الجهاز المحمول. 8 مكونات وأنت أقل من 60 إطارًا في الثانية.

ال 93 كومينتر

أتوقع الحصول على معظم أداء التفاعل المحتمل لهذه المكتبة الرائعة.

سيكون أداء Bessonov @ إصدارًا بؤريًا بعد الإصدار 1. لقد حاولنا الحفاظ على جوهر المكتبة بأسرع ما يمكن. يجب أن تكون جيدة بما يكفي لأكثر من 90٪ من الحالات. على الأقل ، إنها تجربتي في استخدام المكتبة حتى الآن. لم تقدم أي مرجع خارجي ، بصرف النظر عن إثارة انتباهنا حول حقيقة أن الأداء مهم ، لا يمكننا جعل هذه المشكلة قابلة للتنفيذ. إذا كنت قادرًا على تحديد قيود جذر الأداء لـ Material-UI التي يمكننا التحقيق فيها (باستخدام رموز الاستنساخ وصندوق أو مستودع) ، فيرجى رفعه. حتى ذلك الحين ، أغلق المشكلة.

oliviertassinari أشكركم على ردكم السريع! أنا سعيد جدًا لسماع ذلك ، سيكون التركيز على الأداء بعد الإصدار.

يجب أن تكون جيدة بما يكفي لأكثر من 90٪ من الحالات. على الأقل ، إنها تجربتي في استخدام المكتبة حتى الآن.

على سطح المكتب - نعم ، هو كذلك. لكنها بطيئة حقًا على الجوّال. Just Drawer وبعض الأزرار تجعل التطبيق بطيئًا. إنه لا يستجيب ويستهلك المزيد من الطاقة حسب الحاجة.

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

لقد قدمت إشارة إلى المشكلة التي أثيرت بالفعل ومرجعًا للرد على الوثائق.

إذا كنت قادرًا على تحديد قيود جذر الأداء لـ Material-UI التي يمكننا التحقيق فيها (باستخدام رموز الاستنساخ وصندوق أو مستودع)

كما قلت ، يمكنني فعل ذلك. هنا مقارنة مكون نقي وغير نقي. خطوات التكاثر هي:

  1. استخدم الكروم وانتقل إلى https://codesandbox.io/s/r1ov818nwm
  2. انقر فوق "فتح في نافذة جديدة" في نافذة المعاينة
  3. افتح أدوات التطوير وانتقل إلى علامة التبويب "الأداء"
  4. خنق وحدة المعالجة المركزية الخاصة بك بما لا يقل عن 5x (اعتمادًا على جهاز الكمبيوتر الخاص بك - قد يكون 10x) لتعكس الجهاز المحمول
  5. انقر على برجر وشاهد كيف يتأخر.

و الأن:

  1. انتقل إلى index.js
  2. تغيير pure إلى true
  3. يحفظ
  4. كرر الخطوات المذكورة أعلاه
  5. استمتع بها!

هذا المثال غير واقعي قليلاً لأنني قمت بإدراج الكثير من عناصر القائمة. ولكن كما قلت ، على الجوّال ، يتم بسرعة كبيرة الإشارة إلى حيث "تشعر" بكل فعل.

هذه هي مشكلتي مع WithStyles . إنه على سطح المكتب مع التحكم في وحدة المعالجة المركزية. أود نشر لقطات شاشة من جهاز حقيقي يوم الاثنين.

الوقت مقابل WithStyles(ListItem) :
image

الوقت مقابل ListItem :
image

الفرق هو 1.26 مللي ثانية فقط لمكون ListItem . مع 13 مكونًا مثل هذا ، لا يمكنك تصيير 60 إطارًا في الثانية بعد الآن. لكنني لاحظت على سطح المكتب أن هذه المدة ليست هنا دائمًا.

هنا مقارنة مكون نقي وغير نقي

بالمناسبة ، لا أقول أن PureComponent هو الحل لجميع مشكلات الأداء. أقول فقط ، يمكن أن يكون أحد المساعدين جعل واجهة المستخدم المادية قابلة للاستخدام على الهاتف المحمول.

الفرق هو 1.26 مللي ثانية فقط لمكون عنصر القائمة.

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

حسنًا ، هذا جزء واحد فقط. ما رأيك في الجزء الأكثر أهمية - تحسين shouldComponentUpdate ؟

تحرير: أريد تقسيم هذه المسألة إلى جزأين. هذا الجزء هو حول shouldComponentUpdate والجزء الآخر WithStyles ، إذا كان بإمكاني إظهار المزيد من المعلومات. هل هذا مناسب لك؟

التحسين shouldComponentUpdate

Bessonov نحن لا ننفذ مثل هذا المنطق عن قصد على جانب Material-UI لسببين:

  1. تقبل معظم مكوناتنا عناصر التفاعل ، وهو تغيير مرجعي لعنصر التفاعل في كل تصيير ، مما يجعل المنطق يهدر دورات وحدة المعالجة المركزية بشكل منهجي .
  2. كلما اقترب المنطق shouldComponentUpdate من جذر شجرة React ، زادت فعاليتها. أعني ، كلما زاد تقليم الشجرة ، كان ذلك أفضل. مكونات واجهة المستخدم المادية منخفضة المستوى. هناك فرصة منخفضة للرافعة المالية .

الفرصة الوحيدة التي وجدناها هي مع الرموز. دعنا نعرف ما إذا كان يمكنك التعرف على جديدة.

الجزء الآخر لـ WithStyles

+ 90٪ من الوقت الذي تقضيه في WithStyles يتم إنفاقه فعليًا في JSS ، هناك القليل جدًا الذي يمكننا القيام به حيال ذلك على جانب Material-UI.
على الأقل ، كنت أحدد فرصة التخزين المؤقت للعرض من جانب الخادم مؤخرًا لتحسين الأداء بشكل كبير في العرض المتكرر. لكنها من جانب الخادم فقط.

تقبل معظم مكوناتنا عناصر التفاعل ، وهو تغيير مرجعي لعنصر التفاعل في كل تصيير ، مما يجعل المنطق يهدر دورات وحدة المعالجة المركزية بشكل منهجي.

هذا يعتمد على الاستخدام ويمكن تحسينه. لا أقوم بتقييم نفسي ، لكنني متأكد من أن الاستخدام الصحيح للمكونات وتحسين shouldComponentUpdate (مع المقارنة السطحية) أقل تكلفة من المكون غير المحسن ، خاصة بالنسبة للهياكل غير القابلة للتغيير (و immutable.js ليس مطلوبًا بالمناسبة). تذكرة ذات صلة: https://github.com/mui-org/material-ui/issues/4305

على سبيل المثال في https://github.com/mui-org/material-ui/blob/v1-beta/docs/src/pages/demos/drawers/PermanentDrawer.js#L68 يؤدي هذا إلى كائنات جديدة ويجني PureComponent بلا معنى:

        classes={{
          paper: classes.drawerPaper,
        }}

لأنه يعود في كل مرة كائن جديد. لكن لا:

const drawerClasses = {
    paper: classes.drawerPaper,
};
[...]
        classes={drawerClasses}

نفس الشيء بالنسبة للمكونات.

كلما اقترب منطق shouldComponentUpdate من جذر شجرة React ، زادت فعاليتها. أعني ، كلما زاد تقليم الشجرة ، كان ذلك أفضل.

نعم هذا صحيح.

مكونات واجهة المستخدم المادية منخفضة المستوى. هناك فرصة منخفضة للرافعة المالية.

هذا صحيح جزئيًا. كما ترون في https://codesandbox.io/s/r1ov818nwm أنا فقط أقوم بلف List PureComponent . لا شيء آخر وهو يعمل على تسريع الدرج بعامل مهم. أود أن أدعي أن هذا صحيح لكل مكون ، على الأقل يستخدم {this.props.children} . لقد قمت بإنشاء عرض توضيحي آخر: https://codesandbox.io/s/my7rmo2m4y

لا يوجد سوى 101 زرًا (نقي = خطأ) وأزرار ملفوفة في PureComponent (نقي = صحيح ، انظر من أين يتم استيراد الزر). نفس نتيجة اللعبة ، إذا قمت بالنقر فوق الزر "انقر" -:

زر عادي:
image

زر ملفوف (مع النفقات العامة وما إلى ذلك):
image

كما ترى ، هناك 637 مللي ثانية مقابل 47 مللي ثانية للأزرار العادية فقط! هل ما زلت تعتقد أن تحسين shouldComponentUpdate (أو PureComponent ) لا يستحق كل هذا العناء؟ :)

تحرير: إصلاح الصياغة في البداية

oliviertassinarioreqizer لقد لاحظت الشيء المثير للاهتمام. يبدو أنه يمتد إلى PureComponent ويؤدي بشكل أفضل مثل Component مع

  shouldComponentUpdate() {
    return false;
  }

image

تحرير: أعتقد أن هذا هو أحد التحسين الداخلي للتفاعل.

كما ترى ، هناك 637 مللي ثانية مقابل 47 مللي ثانية للأزرار العادية فقط! هل ما زلت تعتقد أن التحسين shouldComponentUpdate (أو PureComponent فقط) لا يستحق كل هذا العناء؟ :)

Bessonov إنه يوضح إمكانات المنطق الخالص. نعم ، يمكن أن يكون مفيدًا جدًا! إنه تحسين x13. لكنني لا أعتقد أنه قريب من ظروف الحياة الواقعية:

  • بدلاً من 100 زر ، ستجد 10 أزرار على الأكثر في الصفحة. ومع ذلك ، ستجد 10 شبكات ، 10 X ، إلخ.
  • بدلاً من الخصائص البسيطة المقدمة لعناصر المستوى الأدنى ، ستستخدم شيئًا مثل رد فعل intl ، وسيظل الاختيار بين الدعائم السابقة والجديدة خاطئًا دائمًا. سوف تضيع دورات وحدة المعالجة المركزية . لذا x13 -> x0.8 أو نحو ذلك

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

فقط لأجلك أقوم بتقليصه إلى 10 أزرار. 10! انها تعني أي 10 مكونات (أسوأ من ذلك: حاويات) من تباطؤ مادي-واجهة المستخدم أسفل التطبيق بأكمله حتى التطبيق غير صالح للاستخدام! تم اختباره على جهاز حقيقي مع Crosswalk 21 / chrome 51 بدون أي دواسة الوقود:

الزر العادي:
image

PureButton:
image

هذا لا يزال تحسن 8x! انه ضخم! هل يمكنك تخيل مدى أهمية هذا على الجهاز المحمول؟

بدلاً من 100 زر ، ستجد 10 أزرار على الأكثر في الصفحة. ومع ذلك ، ستجد 10 شبكات ، 10 X ، إلخ.

لقد استخدمت Button لأنه أحد أبسط المكونات! فإنه يدل على أن واجهة المستخدم، يتم تقسيم المواد من جهة نظر الأداء. الآن ، تخيل مكونات حاوية مثل AppBar ، Toolbar ، List ، Drawer! هذا أسوأ! تحصل بسرعة كبيرة على 20 مكونًا / حاوية في كل صفحة. ولأنك لا تنتهي صلاحية أي بطء على سطح المكتب / جهاز Mac القوي ، فهذا لا يعني أن واجهة المستخدم المادية ليست بطيئة بشكل لا يصدق.

رد فعل-intl ، فإن الاختيار بين الدعائم السابقة والجديدة سيكون دائمًا خاطئًا. سوف تضيع دورات وحدة المعالجة المركزية. لذا x13 -> x0.8

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

راجع للشغل: WithStyles تستهلك ما يصل إلى 2،27 مللي ثانية للزر الموجود على الجهاز المحمول. 8 مكونات وأنت أقل من 60 إطارًا في الثانية.

لماذا تستخدم افتراضاتك الشخصية كحجج ولا حقائق؟

ما الذي يجعلك تعتقد أنه افتراض شخصي؟ كنت أحاول أداء التفكير النقدي. من الناحية المفاهيمية ، فإن اجتياز الدعامة الإضافي سيؤدي إلى إبطاء الإصدار النقي مقارنة بالإصدار غير النقي ، وعليه تقليم شيء يستحق العناء. نفس السبب مثل # 5628 أو https://github.com/react-bootstrap/react-bootstrap/issues/633#issuecomment -234749417 أو https://github.com/reactstrap/reactstrap/pull/771#issuecomment -375765577

مع نقي:
capture d ecran 2018-03-27 a 11 43 41

بدون نقي:
capture d ecran 2018-03-27 a 11 44 15

الاستنساخ هو التالي.

oliviertassinari هل أنت متأكد من أن Codeandbox يجعل كل شيء مناسبًا للاختبار؟ لأن نتائجي مختلفة جدًا:

بدون نقاء (حتى بدون دواسة الوقود يكون بطيئًا):
image

نقي (بعد التغيير إلى صحيح وحفظ أحصل على عنوان url جديد لـ codeandbox):
image

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

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

قد يكون عليك التفكير في تقديم نسخة نقية وغير نقية من المكونات. أفعل ذلك الآن لكي يحصل تطبيقي على بعض الأداء القابل للاستخدام حتى على سطح المكتب.

Bessonov لم يتم حفظ الرموز والصندوق بشكل صحيح. آسف. كان يفتقد الفرق التالية. لقد قمت بتحديث الرابط:

<Button>
+ <i>
    Button
+ </i>
</Button>

لا أفهم لماذا يجب أن تؤدي إلى نتائج مختلفة؟ أحصل على مخطط أفضل ، لكن الإصدار غير النقي أبطأ بشكل ملحوظ.

تحرير: حسنًا ، فهمت. حاول معرفة ما يحدث ...

حسنًا ، فهمت الآن. فقط نفس "الكائن الجديد في كل عرض" - أي شيء. لم ألاحظ ذلك من قبل. في بعض الحالات ، يمكن تحسينه باستخدام الثوابت من خلال ملحق بابل الإضافي تلقائيًا.

حسنًا ، فأنت تعلم ذلك بالفعل! : D على الرغم من عدم وجود فائدة كبيرة من تلقاء نفسها (لقد أظهرت حوالي 7٪) ، إلا أنها لا تزال مربحة في الختام مع المكونات النقية لتجنب بعض العيوب التي ذكرتها أعلاه. لقد اختبرته الآن مع Pure Wrapper + babel plugin + Production build وهو سريع مثير للإعجاب على نفس الجهاز المحمول!

كما قلت ، أعتقد أنه من الأفضل تقديم كلاهما - مكونات غير نقية للمرونة ومكونات نقية (الأغلفة كافية لإبقائها بسيطة وقابلة للصيانة) للأداء. لكن بالنسبة لي ، يمكنني التعايش مع مكونات نقية فقط ، لأن تحسين الأداء الكلي أكبر بكثير من عيوب الأداء. أو أفضل: لا يمكنني استخدام واجهة المستخدم المادية بدون مكونات نقية.

حسنًا ، في الوقت الحالي أنتظر المزيد من المدخلات حول هذا الموضوع وإنشاء أغلفة خاصة في تطبيقي)

شكرا على الرؤى!

لم أسمع أبدًا عن العناصر الثابتة للتحويل والتفاعل والتي يتم استخدامها بالفعل وتكون مفيدة حقًا. لا بأس من التحسين الجزئي العشوائي ، لكن في الممارسة العملية نادرًا ما تكتب رمزًا بسيطًا بما يكفي للحصول على الكثير منه. على الرغم من أنني أفترض أنه لن يكون تحسينًا سيئًا لجميع مكونات رمز نمط SVG مثل <Add /> .

ألقِ نظرة على هذا المثال (انقر على الإضافات في الجانب ، وابحث عن "رد فعل ثابت" وانقر على مربع الاختيار الموجود على "عناصر تحويل - تفاعل - ثابت") وستلاحظ أنه بالكاد تم تحسين أي شيء:

  • تم نقل الثابت InputAdornment إلى الأعلى ، رائع.
  • لكن زر الإرسال البسيط البسيط لم يعد محسنًا لحظة وضع معالج الحدث عليه.
  • وبينما يتم رفع InputAdornment نفسه الآن ، لا يزال InputProps={{startAdornment: ...}} مضمنًا ويخلق كائنًا جديدًا في كل عرض مما يجعل PureComponent مستحيلًا.
  • وبالمثل فإن classes={{label: classes.runButtonLabel}} يجعل من المستحيل على PureComponent تحسين زر التشغيل.

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

  • تعتبر عناصر *Props مثل InputProps نمطًا أساسيًا لكيفية عمل MUI. إنها ليست مجرد طريقة متقدمة لتعديل الأجزاء الداخلية من MUI عندما تحتاج إليها ، بل هي طريقة تستخدم بانتظام في حالات الاستخدام البسيطة. غالبًا ما يجعل هذا النمط أي مكون طرفية يمكن تحسينه بشكل طبيعي في الوضع النقي ، غير قابل للتحسين.
  • وبالمثل ، فإن نمط classes={{...}} لا يعمل أيضًا مع PureComponent وهو طريقة لإضافة أي تصميم للأشياء في MUI. (والقول بأن استخدام classes={classes} ليس عمليًا بأي حال من الأحوال لأن المستهلك الواقعي من المحتمل أن يكون له اسم فئة مختلف عن الفئة الداخلية للمكون ومن المحتمل أن يتضمن classes أيضًا فئات تهدف إلى تصميم عناصر أخرى في نفس المكون المستهلك)
  • يتم استخدام الأطفال كثيرًا ، فبدلاً من وجود مكون واحد ، غالبًا ما يستخدم النمط الشائع 2-3 ويمكن تحسين واحد منهم فقط إذا كان بإمكان أي منهم.

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

نحن فقط نسمح بتمكين الوضع الخالص ، يتعين على المستهلكين حفظ الكائنات أو رفعها يدويًا للحصول على التحسينات بالفعل

  1. إحدى الطرق التي يمكن أن أفكر بها للقيام بذلك قد تكون أقل من shallowMemoize والتي تستخدم this المحلي و key (لذا يمكنك استخدامها على أجزاء مختلفة من البيانات) يحفظ البيانات طالما أنها سطحية متساوية
  2. آخر يمكنني التفكير فيه هو استخدام شيء مثل إعادة التحديد لإنشاء محددات ستحفظ البيانات.
  3. هناك طريقة أخرى لعمل shallowMemoize في 1. وهي تمريرها إلى render() مع مصمم. بهذه الطريقة يمكننا تمرير عرض جديد لكل عرض وبدلاً من الحاجة إلى key يمكننا فقط التحقق مما إذا كان يجب إعادة استخدام أي من الكائنات المحفوظة في الذاكرة من العرض الأخير ، ثم تجاهل جميع القيم القديمة.

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

import {createSelector} from 'reselect';

class FormPage extends PureComponent {
  state = { example: '' };

  change = e => this.setState({example: e.target.value});
  submit = () => {
    console.log('Submit: ', this.state.example);
  };

  runButtonClasses = createSelector(
    props => props.classes.runButtonLabel,
    runButtonLabel => ({runButtonLabel}));

  render() {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={this.shallowMemoize('a', {
            // This example assumes use of transform-react-constant-elements to make this object always the same
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={this.runButtonClasses(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }
}
// ...
  <strong i="6">@withShallowMemoize</strong>
  render(memo) {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={memo({
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={memo(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }

بدلاً من محاولة تحسين InputProps ، والفئات ، وما إلى ذلك ... نشجع الأشخاص على صنع مكونات دقيقة لجميع أغلفة استخدامهم

إذا كانت هذه هي الطريقة الموصى بها لاستخدام MUI ، فقد لا نحتاج حتى إلى وضع خالص. كما ترى ، بمجرد أن تبدأ في صنع مكونات مساعدة صغيرة لحالات الاستخدام الشائعة ، يمكن أن تكون هذه المكونات نفسها مكونات نقية بسهولة. في المثال WeightTextField الآن لن يتم إعادة عرضه أبدًا طالما أن value لا يزال هو نفسه ، متخطيًا تمامًا مع الأنماط ، أي عمل لحفظ الذاكرة ضروري لـ InputProps ، أو إعداد InputAdornment. وعندما يتغير value ، يتعين علينا إعادة تقديم TextField على أي حال حتى لا يهم InputProps={{...}} غير الخالص.

أنا بخير مع هذا المسار. أنا أحب المكونات الدقيقة من الناحية النظرية ؛ على الرغم من أنني أكره كل بناء جملة / نمط صالح حاليًا لكتابتها والتي يمكنني التفكير فيها. لا أريد MyComponent = enhance(MyComponent) ، أريد تزيينها ، لكن لا يمكنك تزيين أي من الطرق القصيرة لكتابة مكون صغير. أنا أيضًا لا أحب تحويل import {TextField} from 'material-ui'; إلى import WeightTextField from '../../../ui/WeightTextField ؛ `.

شبيبة
دع WeightTextField = ({unit، InputProps، ... props}) => (
{... الدعائم}
InputProps = {{
بداية الزينة:{وحدة} و
... InputProps
}}
عند التغيير = {مثال}
القيمة = {مثال} />
) ؛
WeightTextField = نقي (WeightTextField) ؛

RunButton = تكوين (
withStyles (المظهر => ({
ضع الكلمة المناسبة: {
وزن الخط: '800'،
} ،
})) ،
نقي
)(زر)؛

const SubmitButton = pure (Button) ؛

فئة FormPage توسع المكون {
الدولة = {مثال: ''} ؛

change = e => this.setState ({example: e.target.value}) ؛
إرسال = () => {
console.log ('Submit:'، this.state.example) ؛
} ؛

يقدم - يجعل() {
const {title} = this.props؛
const {example} = this.state؛

return (
  <form>
    {title}
    <WeightTextField
      unit='Kg'
      onChange={example}
      value={example} />
    <RunButton>Run</RunButton>
    <SubmitButton onClick={this.submit}>Submit</SubmitButton>
  </form>
);

}
}
""

لدي حالة استخدام حيث أحتاج إلى عرض 500-2000 مربع اختيار على صفحة في قائمة كبيرة. باستخدام مربعات اختيار المستعرض الأصلي ، يكون الأداء جيدًا ، ولكن باستخدام المكون <Checkbox> ، يكون الأداء ضعيفًا للغاية ويتوسع خطيًا مع عدد مربعات الاختيار على الصفحة. مثال: https://codesandbox.io/s/5x596w5lwn

أنا أستخدم mui @ next - هل هناك بعض الإستراتيجيات التي يمكنني استخدامها _now_ لجعل هذا عمليًا؟

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

  handleChange = index => event => {
    this.setState({

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

https://codesandbox.io/s/r7l64j6v5n

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

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

بدلاً من محاولة تحسين InputProps ، والفئات ، وما إلى ذلك ... نشجع الأشخاص على صنع مكونات دقيقة لجميع أغلفة استخدامهم

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

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

نعم. في هذه الحالة:

  • سنرغب في التوصية بمكتبات مثل إعادة التهيئة التي تجعل من السهل كتابة مكونات صغيرة عديمة الحالة. هيك ، سأرحب به إذا أخبرني أحدهم أن هناك نمطًا أو مكتبة أخرى تشبه إعادة تكوينها ولكنها تجعل بناء وظائف عديمة الحالة خالصة مثل أنماط إعادة تكوينها ولكنها لطيفة مثل استخدام بناء جملة المصمم
  • مثلما نقوم بإدراج اقتراحات حول كيفية استخدام مكتبات الإكمال التلقائي المتنوعة و css في مكتبات js باستخدام MUI ، فربما نرغب أيضًا في اقتراح أنماط تنظيم المجلد المختلفة ومكتبات قرصنة المسار (تلك التي تتيح لك تحويل الواردات ../../../../ui/Foo إلى شيء مثل something-local/Foo ) يمكن استخدامه لصنع استخدام سلسلتك المحلية الخاصة من المكونات الدقيقة التي تغلف MUI بطريقة لطيفة مثل استخدام import {TextField} from 'material-ui'; ولا تشعر وكأنها تراجع في سهولة المطور .

@ دانتمان رائع ، شكرا لك.

لقد احتجت عدة مرات لتطبيق sCU بسبب بطء أسلوب withStyles (أو بالأحرى JSS). لا أعرف كود JSS ولكن يبدو أنه يمكن تحسينه كثيرًا. عادةً ما أستخدم المكونات المصممة أو البراقة ، وبالتالي ينتهي بي الأمر مع JSS وواحد من الآخر في التطبيق وكلاهما يتفوقان على JSS.

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

كي لا نقول إنه لا يمكن أن يكون أسرع وأكيد أنه سيكون أجمل إذا كانت هناك حاجة إلى إشراف أقل ولكن على الأقل لما أراه سيكون من الأفضل قضاء بعض الوقت في تحسين JSS مباشرة من MUI في هذه الحالة.

Pajn شكرا على ردود الفعل. سيكون من الرائع حقًا أن نرى بعض المواقف التي يكون فيها أداء withStyles مشكلة أو حيث يتفوق عليه أداء المكونات المصممة.

هل قام أي شخص بفحص هذا الريبو https://github.com/reactopt/reactopt ؟

$ click - button (text: مقالات ) => CssBaseline,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,Main,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple

تقوم هذه المكونات بإعادة عرض غير ضرورية فقط بنقرة بسيطة ، فلماذا لا تحاول إجراء دورة حياة تحديث المكون؟

@ nimaa77

هل قام أي شخص بفحص هذا الريبو https://github.com/reactopt/reactopt ؟
لا، وأنا استخدم عادي لماذا-فعل-لك التحديث والكروم / الرد ديف قدرات الأدوات.

تقوم هذه المكونات بإعادة عرض غير ضرورية فقط بنقرة بسيطة ، فلماذا لا تحاول إجراء دورة حياة تحديث المكون؟

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

تضمين التغريدة

ألقِ نظرة على هذا المثال (انقر على الإضافات في الجانب ، وابحث عن "رد فعل ثابت" وانقر على مربع الاختيار الموجود على "عناصر تحويل - تفاعل - ثابت") وستلاحظ أنه بالكاد تم تحسين أي شيء:

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

Bessonov ربما يمكننا استخدام الدعامة لعمل طريقة shouldComponentUpdate لإجراء مقارنة سطحية (https://reactjs.org/docs/shallow-compare.html) أو إرجاع القيمة false دائمًا ،
لن يؤدي ذلك إلى زيادة حجم الحزمة مع نسختين من المكونات (نقية وعادية)

lucasljj لا أتوقع زيادة كبيرة في حجم الحزمة إذا تم ذلك كغلاف لمكون ذي حالة مثل المذكورة أعلاه. راجع أيضًا الملفات الشخصية أعلاه: المكونات النقية فقط أسرع من return false; في جامعة كاليفورنيا.

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

تعتبرbossonov Pure Components من العناصر التي يجب أن تكون افتراضية للتفاعل وليس لأنها جاءت متأخرة إلى الحفلة. لكنني أوافق على أن معظم الناس سيصنعون أغلفة نمط إعادة تشكيل تخفف من عدم وجودها على الشجرة الفرعية

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

تضمين التغريدة

سيكون الأداء هو إصدار التركيز بعد الإصدار 1.

رائع ، تم إصدار v1 :) هل هناك أي فكرة متى يجب معالجة الأداء؟ لقد لاحظت أن هذه المشكلة ليست جزءًا من مرحلة ما بعد الإصدار 1.

Bessonov أعتقد أنه سيكون من الرائع قضاء بعض الوقت في تحديث ROADMAP. بخصوص الأداء. لدي شيئان في ذهني قابلين للتنفيذ ، لكني آمل أن أكتشف المزيد:

  1. لا يمكننا تحسين شيء لا يمكننا رؤيته. نحن بحاجة إلى معيار. لقد رأيت مكتبتين مثيرتين للاهتمام حتى الآن:
  2. يتطلب عرض جانب خادم CSS حوالي 30٪ مما يحتاج React إلى عرضه. لأننا لا ندعم style = f(props) (حسنًا ، نحن لا ندعمه بعد: # 7633). يمكننا تنفيذ قدرة تخزين مؤقت فعالة للغاية ، مما يقلل التكلفة بنسبة تقترب من 0٪ للطلبات المتكررة. قد أعمل على ذلك للمكتب إذا كان أداء SSR يضر بمقاييس أعمالنا.
    لكنها ليست الخيارات الوحيدة ، يمكننا أيضًا التفكير في مكونات Babel الإضافية لتطبيق إعدادات JSS المسبقة المكلفة في وقت التجميع بدلاً من وقت التشغيل (لتحقيق التوازن مع الآثار المترتبة على حجم الحزمة) cckof.

شكرا لعناوين المواقع.

أتفق تمامًا مع 1 والمرتبط # 4305 أعلاه.

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

ستكون تحسينات وقت التجميع رائعة ومن وجهة نظري يجب أن تكون مفضلة ، لأنها يمكن أن تحسن التحميل والعرض لأول مرة.

شيء آخر هو نوع من التوثيق أو مثال على مشروع كيفية استخدام mui (و babel وما إلى ذلك) للحصول على أداء أفضل.

لا أعرف ما إذا كان يمكن استخدام jss-cache .

سيتمكن خط أنابيب المعالجة المسبقة ISTF + من حلق بعض مللي ثانية.

في يوم السبت ، 19 مايو ، 2018 ، الساعة 19:06 ، كتب أنطون بيسونوف [email protected] :

شكرا لعناوين المواقع.

أتفق تمامًا مع 1 والمرتبط # 4305
https://github.com/mui-org/material-ui/issues/4305 أعلاه.

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

ستكون تحسينات وقت التجميع رائعة ومن وجهة نظري يجب أن تكون
تكون مفضلة ، لأنها يمكن أن تحسن التحميل والعرض لأول مرة.

شيء آخر هو نوع من التوثيق أو مثال على مشروع كيفية استخدام mui
(و babel وما إلى ذلك) للحصول على أداء أفضل.

لا أعرف ما إذا كان http://cssinjs.org/jss-cache؟v=v3.0.0 ذاكرة التخزين المؤقت لـ jss
تستخدم.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/mui-org/material-ui/issues/10778#issuecomment-390418709 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AADOWGrCxNGqrT4MijiX8r9Ad32z6RsJks5t0FEtgaJpZM4S4woq
.

قد يكون مفيدًا في إعداد المعايير:
https://github.com/A-gambit/CSS-IN-JS-Benchmarks/blob/master/RESULT.md

يبدو أن Oh React-jss (الذي تستخدمه material-ui) بطيء جدًا

janhoeck ليس كذلك ، ولن تكون قادرًا على إثبات خلاف ذلك ، أنا متأكد.

kof أنا حقًا . في الواقع ، الأداء العام لواجهة المستخدم المادية ليس لامعًا.

4x-6x بالمقارنة مع أفروديت بطيء حقًا

Bessonov المنهجية المعيارية
https://twitter.com/necolas/status/954024318308007937؟lang=fr

النتائج في متصفحي:
⚠️ مع الشك

capture d ecran 2018-06-12 a 17 58 54

الأداء العام لواجهة المستخدم المادية ليس لامعًا

قد نكون مقيدين تمامًا بـ React نفسها وتكلفة المكونات.

Bessonov كل ما استخدمته للتحقق من الأداء ، عندما يتعلق الأمر oliviertassinari الذي نشره هو الأكثر واقعية.

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

kof لا ، MUI ليس سريعًا بشكل افتراضي. نحن مضطرون إلى تنفيذ الحلول للحصول على أداء مقبول. فقط على وجه اليقين: ألا ترى أن الأمر يتعلق بالأجهزة المحمولة وليس لأجهزة Mac المتطورة؟

لا تقلق أبدًا بشأن أدائها ما لم تفعل شيئًا خاطئًا تمامًا أو أساءت استخدام المكتبة

حسنًا ، فيما يلي بعض أمثلة Codeanbox. إذا استخدمنا مكونات MUI في حاوية وحفظنا قيم الإدخال في حالة الحاوية ، كما هو موضح في العروض التوضيحية للمكونات ، فسيصبح غير قابل للاستخدام بسرعة كبيرة. التفاف في PureComponent ، واستخدام مكونات غير خاضعة للرقابة ، وإعادة ترتيب الشجرة ، والعناصر الثابتة ، وحفظ الذاكرة ، وما إلى ذلك لمساعدتنا في الحفاظ على بعض الأداء المقبول. نرحب بك لإظهار كيفية استخدام MUI بشكل صحيح ، للحصول على نتائج أفضل ، على سبيل المثال في (أجهزة الصراف الآلي لم نعد نستخدم الدرج):
https://codesandbox.io/s/r1ov818nwm

oliviertassinari شكرا على الرابط. فيما يلي نتائج Chrome 66 على جهاز nexus 4. كما ترى ، كانت النتائج أقل بـ 10 مرات. أعتقد أنه في Crosswalk 21 / chrome 51 يمكن أن يكون أبطأ قليلاً:

screenshot_2018-06-12-18-20-19

قد نكون مقيدين تمامًا بـ React نفسها وتكلفة المكونات.

IMHO ليس بالضرورة ، كما ذكر آخرون أيضًا. يعد كل عرض يتم تجنبه مكسبًا كبيرًا للأداء والبطارية. لا تنس ، الأداء هو النقطة الثالثة في خريطة الطريق الخاصة بك: +1:

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

oliviertassinari هو ذلك evtl. من الممكن أن يقوم برنامج تضمين mui بإعادة عرض أنماط jss عند التحديث؟ قد يكون هناك بعض التسرب الذي يحتمل أن يؤدي عملاً غير ضروري.

kof

انظر إلى الأمر بهذه الطريقة [...]

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

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

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

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

لقد نظرت JSS في الأداء منذ اليوم الأول وقضيت ساعات لا حصر لها في التحسينات الدقيقة.

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

class RowText extends Component {
  shouldComponentUpdate = (nextProps, nextState) => {
    return false;
  };

  render() {
    const { title, artist } = this.props;
    return <ListItemText primary={title} secondary={artist} />;
  }
}

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

مرحبًا ، هذا يحدث فقط مع عنصر القائمة والقائمة. لماذا ا ؟ هل هناك شيء يمكنني القيام به؟

@ danielo515 من الصعب معرفة ذلك بدون المثال الكامل. تستخدم مكونات List أيضًا السياق ، لذا إذا كنت تقوم بتغيير هذه القيمة أيضًا ، فسيؤدي ذلك أيضًا إلى تشغيل عمليات إعادة العرض.

أفهم أن @ eps1lon. ومع ذلك ، هل يمكنك أن توضح كيف يمكن أن يحدث تغيير في السياق؟ أنا لا أنقل أي شيء إلى عنصر القائمة ، بل أقوم فقط بضياع الأطفال بداخله.

@ danielo515 بشكل أساسي في كل مرة يتم فيها عرض List . أتاحت واجهة برمجة تطبيقات السياق الجديدة بعض استراتيجيات التحسين التي يمكننا استكشافها من خلال حفظ قيمة السياق.

تتفاعل واجهة برمجة تطبيقات السياق حاليًا مع تشغيل عرض على كل مستهلك إذا تغيرت القيمة WRT إلى مساواة صارمة. نظرًا لأننا ننشئ عنصرًا جديدًا في كل استدعاء تصيير لـ List سيُعرض كل مستهلك أيضًا.

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

مكونات التغليف بـ React.memo تعمل بشكل جيد لأي شيء بدون أطفال. لدي نموذج به 3 ExpansionPanel وحوالي 14 FormControl وهو متأخر على سطح المكتب.

بدون حل لمشكلات الأداء هذه ، لن أتمكن من الاستمرار في استخدام واجهة المستخدم المادية

prevostc من الصعب معرفة الخطأ بدون مثال.

prevostc بدون رؤية إعادة إنتاج الأكواد ، لا يمكننا ولا يمكنك معرفة ما إذا كان هذا مرتبطًا بهذه المشكلة

prevostc قم

على سبيل المثال ، أنشئ مكوّنًا خالصًا / مذكّرًا MyExpansionPanel يأخذ دعائم البيانات / الأحداث ولكن ليس الأطفال ويكون مسؤولاً عن تقديم لوحة توسيع واحدة. ثم استخدم هذا <MyExpansionPanel ... /> لعرض كل من لوحات التوسيع الخاصة بك. ثم ستقتصر عمليات إعادة العرض على لوحة توسيع واحدة (أو اثنتين عند الانتقال بين اثنين).

oliviertassinarikofdantman
في ما يلي نسخة من الرموز والصندوق لمشكلة الأداء الخاصة بي: https://codesandbox.io/s/yvv2y2zxxx

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

تأتي مشكلة الأداء من إعادة التصيير الهائلة لمدخلات المستخدم ، لكن تغليف مكونات MUI في مكون نقي (React.memo) لا يفعل شيئًا لأن كل شيء هنا له أطفال وأطفال ، وهذا سيجبر إعادة تصيير AFAIK (المصدر: https: // React-api.html#reactpurecomponent)

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

يرجى ملاحظة أنني سأعلم بكل سرور أنني فعلت شيئًا خاطئًا لأنني أحب MUI وسأكون حزينًا إذا لم يكن هناك حل سهل <3

dantman كيف يمكنك كتابة ExpansionPanel لا تأخذ أي React.ReactNode كمدخلات (أطفال أو دعائم)؟ إذا كنت تقصد أنه يجب أن أكتب مكونًا محددًا لكل لوحة في تطبيقي ، فهذا غير ممكن لسوء الحظ ، لدي الكثير منهم.

screenshot 2018-12-20 at 22 04 08

screenshot 2018-12-20 at 21 56 57

screenshot 2018-12-20 at 22 05 00

dantman كيف يمكنك كتابة ExpansionPanel لا تأخذ أي React.ReactNode كمدخلات (أطفال أو دعائم)؟ إذا كنت تقصد أنه يجب أن أكتب مكونًا محددًا لكل لوحة في تطبيقي ، فهذا غير ممكن لسوء الحظ ، لدي الكثير منهم.

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

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

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

نعم ، واجهة المستخدم المادية أبطأ قليلاً من عناصر dom ذات المستوى المنخفض. ولكن حتى لو كان MUI Input أبطأ input الخام وأصبحت الأمور بطيئة جدًا بعد 100. ثم لا تزال لديك مشكلة حتى بدون MUI لأنه حتى لو كان أسرع بـ 10 مرات من الخام input سيجعل الموقع بطيئًا بنفس القدر إذا كان لديك 1000 منهم. لا يمكنك استخدام مكونات أحادية متجانسة في React حتى عندما لا تستخدم MUI. تحتاج إلى تقسيم تطبيقك إلى أجزاء ذات حجم معقول حتى يتمكن React من تحديد الحدود التي يمكنه تحسينها.

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

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

https://codesandbox.io/s/0o7vw76wzp

screen shot 2018-12-20 at 2 51 31 pm

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

يعتبر

حسنًا ، إليك اختبار تحمّل محدث https://codesandbox.io/s/wz7yy1kvqk

أتفق مع dantman على هذه النقطة العامة https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635 لكنني لم أكن أتوقع مثل هذه المشكلة في الأداء مع هذه الكمية المنخفضة من المكونات ، لكنني تحمل معها لي كما وجدت مصدر مشكلة الأداء الخاصة بي.

هل JSS بطيء؟ (تنبيه المفسد: لا)

بالإشارة إلى بعض التعليقات السابقة في هذا الموضوع ، أضفت مربع اختيار في اختبار التحمل لإزالة جميع المكالمات إلى withStyles وتوصلت إلى استنتاج مفاده أن JSS سريع وليس مصدر مشكلة الأداء (كما أشار kof في https://github.com/mui-org/material-ui/issues/10778#issuecomment-396609276).

screenshot 2018-12-22 at 15 17 26

المأزق

بالنسبة لحالة الاستخدام المحددة الخاصة بي ، تمكنت من تحديد المشكلة المتمثلة في إعادة عرض كل إدخال في النموذج عند تحديث النموذج ، على الرغم من تغيير إدخال واحد فقط بالفعل.
في لقطة الشاشة أدناه ، قمت بلف كل من FormControl والإدخال في مكون محفوظ ، وتجنب العرض إذا لم تتغير القيمة. اقترح dantman في الواقع أن أقوم بإنشاء مكون محدد لكل ExpansionPanel ولكن هذا حل أقل شمولية. كملاحظة جانبية ، لا يزال يتم إعادة عرض كل لوحة والأداء بعيد عن المستوى الأمثل ولكنه كافٍ في الوقت الحالي.

screenshot 2018-12-22 at 15 18 22

وبالتالي؟ ماذا بعد؟

أعتقد أنه لا توجد طريقة لتجنب هذا النوع من المشكلات مع تغيير رمز واجهة المستخدم المادية دون تغيير هائل في واجهة برمجة التطبيقات الحالية التي تعتمد بشكل كبير على تكوين React.ReactNode .
ولكن كما ذكر dantman في https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635 ، فإن MUI أبطأ قليلاً مما توقعته منه. عدم معالجة هذا على الإطلاق هو خطأ IMHO.

نظرًا لهذه المشكلة ، قد نحتاج إلى إنشاء صفحة مستند تتعلق بمشكلات الأداء وكيفية معالجتها. حتى إذا كانت صفحته ستعيد التوجيه بشكل أساسي إلى المستند الرسمي (https://reactjs.org/docs/optimizing-performance.html) وقائمة المكونات التي قد تسبب مشكلات في الأداء ، فهذه بداية.
سيكون من الأفضل التحكم في. تحذير المستخدم عند حدوث مثل هذه المشكلة ولكن لا يمكنني اكتشاف طريقة لاكتشاف المشكلات على مستوى واجهة المستخدم المادية.

prevostc هذه الرسالة جعلت يومي ، هذا هو نوع المجتمع الذي أحبه. هل لديك أفكار حول ما يمكن أن يغيره mui لتحسين الأداء وتجنب الحاجة إلى تحسينات أراضي المستخدم؟ قد يكون تغيير API قابلاً للتنفيذ.

لا أفعل: s

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

قد يكون أي تغيير في واجهة برمجة التطبيقات هو التفكير في إزالة أي عناصر React.ReactNode من واجهة برمجة التطبيقات (الأطفال وغيرها من الدعائم مثل الأيقونة ، وما إلى ذلك) ولكن لم أجد طريقة جيدة للاحتفاظ بنفس قابلية التكوين.
إليكم ما جربته: https://codesandbox.io/s/jpw36jw65 (تحذير: لم ينته).

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

هل هناك أي تقدم في إضافة القدرات (مثل تلك التي اقترحها Bessonov ) من أجل تحسين مشكلات الأداء التي تواجهها Material-UI حاليًا؟
عندما بدأنا في استخدام هذه المكتبة الرائعة لمشروعنا ، لم أكن أعلم أن مثل هذه المشكلات في الأداء قد تحدث عندما يصبح المشروع أكبر وأكبر ؛ بالإضافة إلى ذلك ، لم أشاهد أي قسم في مستندات Material-UI يخبرني بالحالات التي قد تتسبب في أن تصبح Material-UI بطيئة وتضر UX.
تم الإبلاغ عن الكثير من مشكلات الأداء - المرتبطة بشكل مباشر أو غير مباشر بـ Material-UI - في هذه المشكلة. أعتقد أنه سيكون فكرة جيدة أن تدرجهم في قضية أخرى حتى يتمكن الجميع من تتبع التقدم. إذا كنت تعتقد أنه لا بأس ، يمكنني فتح عدد جديد.

@ mkermani144 لم نتمكن بعد من رؤية تقرير أداء مرتبط بشكل مباشر بشيء تقوم به واجهة المستخدم المادية بشكل خاطئ. حتى الآن تم استخدام هذه القضية كمنتدى مساعدة للأشخاص الذين يعانون. هل تؤكد أنه لم يتم الإبلاغ عن أي شيء عملي؟ سأقول إن تجريد التفاعل الواضح

طاولة

وضع التطوير

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

في حالة الاختبار التالية ، نقوم بعرض 100 عنصر في وضع dev . يمكننا النظر في الحالات التالية:

  1. Table Raw: https://codesandbox.io/s/v066y5q7z3 : 63ms في العرض
  2. Table Material-UI Master: https://codesandbox.io/s/m4kwmvj9ly : 250ms في العرض
  3. Table Material-UI Next: https://codesandbox.io/s/2o35yny1jn : 262ms في العرض

لذا فإن النفقات العامة لاستخدام Material-UI في وضع dev على عنصر مضيف تبلغ حوالي x4 (الفرق أصغر في الإنتاج!) ، ببساطة لأننا نصنع مكونات وسيطة. هذا هو سبب أهمية المحاكاة الافتراضية بعد عرض قائمة تضم حوالي 100 عنصر جدول. الآن ، يمكننا الغوص قليلاً في لماذا وماذا يمكننا أن نفعل حيال ذلك؟

  1. جدول Raw + مكون الوظيفة. لماذا مكون وظيفي؟ نريد أن نلخص أسماء الفئات المستخدمة. لا نريد أن يكررها المستخدمون المكونون.
    https://codesandbox.io/s/1zl75mwlpj : 105ms في العرض
  2. جدول Raw + مكون الوظيفة + إعادة توجيه لماذا ForwardRef؟ نريد أن يكون المكون "شفافًا" ، بحيث يكون قادرًا على الوصول إلى العنصر المضيف باستخدام المرجع.
    https://codesandbox.io/s/32o2y0o9op : 120 مللي ثانية في العرض
  3. جدول Raw + مكون الوظيفة + forwardRef + withStyles. لماذا مع ستايلز؟ لأننا نريد تصميم مكوننا:
    https://codesandbox.io/s/j2n6pv768y : 200 مللي ثانية في العرض
  4. الجدول Raw + مكون الوظيفة + forwardRef + makeStyles. قد تكون الأنماط أسرع من withStyles ، لنجرب:
    https://codesandbox.io/s/yw52n07l3z : 130 مللي ثانية في العرض.

لذلك ، لدينا رافعة مالية واحدة متاحة: ترحيل كل المكونات من withStyles إلى makeStyles. يمكننا الفوز بحوالي 30٪ من الأداء (262 / (262-70)) في وضع التطوير .

وضع الإنتاج

لقد أجريت نفس حالات الاختبار في وضع الإنتاج:

  • n ° 1 30 مللي ثانية في الهيدرات
  • n ° 3 106ms في الهيدرات
  • n ° 4 40ms في الهيدرات
  • n ° 54 41ms في الهيدرات
  • n ° 6 80ms في الهيدرات
  • n ° 7 57ms في الهيدرات

لذا فإن الترحيل من withStyles إلى makeStyles لا يزال يمثل تسريعًا بنسبة 30٪ نظريًا في وضع الإنتاج .

إذا كنت تعتقد أنه لا بأس ، يمكنني فتح عدد جديد.

@ mkermani144 إذا كانت لديك حالة معينة حيث أن Material-UI تفعل ذلك بشكل خاطئ ، بالتأكيد.

قرأت عن جميع التعليقات أدناه هذه المسألة. مشكلتي لا تناسب أيًا من المشكلات الأخرى المذكورة سابقًا.

لدي مكوِّن List يحتوي على بعض ListItem s ، مع تحديد واحد منهم وتمييزه. عندما أنقر فوق ListItem لتحديده وتمييزه ، تتم إعادة عرض القائمة بأكملها (التي تحتوي على العناصر الفرعية) مرة أخرى.

أعلم أن هذه المشكلة قد تبدو تمامًا مثل تعليق سابق ، لكنها ليست كذلك ؛ على الأقل أنا اعتقد ذلك.

لنلقِ نظرة على النتائج من ملف تعريف React:

image
كما ترى ، لدي مكون MyList في المستوى العلوي من الصورة. هذا المكون هو مجرد غلاف حول MUI List ويجعله نقيًا ، أي:

class MyList extends React.PureComponent {
  render() {
    return (
      <List>
        {this.props.children}
      </List>
    );
  }
}

لقد أضفت هذا الغلاف لأن @ eps1lon في أحد تعليقاته ذكر أن إعادة عرض List تؤدي إلى تحديث السياق ، وهذا التحديث السياقي يجعل جميع المستهلكين (بما في ذلك ListItem s) يعيدون العرض أيضًا .

حاولت أيضًا جعل كل ما عندي من ListItem s خالصًا وملفًا للتطبيق مرة أخرى. كانت النتائج متشابهة ، باستثناء أن المكوِّن المخصص (على سبيل المثال MyListItem ) لم يعيد تصيير _itself_ ، ولكن جميع العناصر الفرعية التي تحته __did__.

أعلم أن المشكلة تحدث لأن السياق الذي تستخدمه MUI لتصميم يعيد تصيير _ بطريقة ما_. لكني لا أعرف لماذا تحدث إعادة التصيير هذه وكيف يمكنني تجنبها.

أم أنني أفعل شيئًا خاطئًا؟

ملاحظة: أستخدم حل تصميم MUI جديد (ألفا) ، أي @material-ui/styles . لا أعرف ما إذا كان هذا مهمًا.

@ mkermani144 قم بإزالة Material-UI مع العناصر الأصلية ، لاحظ أن إعادة العرض لا تزال موجودة. المنطق الخالص لن يساعد مثل هذا. يقوم React.createElement بإنشاء مراجع جديدة في كل تصيير ، وهو يبطل PureComponent الخاص بك.

نعم ، أعلم أن العناصر هي كائنات ، والكائنات ليست متساوية تمامًا في جافا سكريبت ، لذلك فشل sCU .

لكنني لا أفهم ما تقصده عندما تقول أن React.createElement تم استدعاءه مرة أخرى. أي استدعاء لـ createElement ؟ إذا كنت تقصد المكالمات داخل List ، فإنها تستدعي فقط createElement لأطفالها ( ListItem s) فقط إذا تمت إعادة تقديمها. إذا لم تتم إعادة تصييرها ، فلن يتم استدعاء createElement ولن تحدث إعادة تصيير. المشكلة هي أن List نفسه يتم إعادة تقديمه.

@ mkermani144 إذا كان بإمكانك إنشاء مثال على الحد الأدنى من التكاثر ، فيمكننا إلقاء نظرة عليه.

يتم عرض MyList (وبالتالي List ) بسبب المكون الذي يعرض MyList (دعنا نطلق عليه MyComponent ). لا يساعد PureComponent على MyList حيث تم عرض MyComponent وإنشاء أطفال جدد مقابل MyList بحيث يفشل الشيك MyList s.

من المحتمل أن تتم إعادة عرض MyComponent بك لأنه يوجد مكان تخزن فيه حالة العنصر المحدد.

أعتقد أن تنفيذ MUIs للقائمة يجب أن يتغير لعدم إعادة إنشاء قيمة سياق القائمة في كل عرض
هنا: https://github.com/mui-org/material-ui/blob/fb4889f42613b05220c49f8fc361451066989328/packages/material-ui/src/List/List.js#L57

لذا بدلاً من ذلك ، اجعل القائمة تبدو كما يلي:

const List = React.forwardRef(function List(props, ref) {
  const {
    children,
    classes,
    className,
    component: Component,
    dense,
    disablePadding,
    subheader,
    ...other
  } = props;
  const context = React.useMemo(() => ({ dense }), [dense]);

  return (
    <Component
      className={clsx(
        classes.root,
        {
          [classes.dense]: dense && !disablePadding,
          [classes.padding]: !disablePadding,
          [classes.subheader]: subheader,
        },
        className,
      )}
      ref={ref}
      {...other}
    >
      <ListContext.Provider value={context}>
        {subheader}
        {children}
      </ListContext.Provider>
    </Component>
  );
});

سيؤدي ذلك إلى تبسيط إنشاء إصدارات sCU من ListItems

يتم إعادة عرض MyList (وبالتالي القائمة) بسبب المكون الذي يعرض MyList (دعنا نسميها MyComponent). لا يساعد PureComponent في MyList حيث تم إعادة عرض MyComponent وإنشاء عناصر فرعية جديدة لـ MyList بحيث يفشل فحص MyLists.

Pajn لا ، انظر إلى نتائج ملف التعريف الخاص بي في React . لم يتم إعادة تقديم MyList (إنه رمادي) ، ولكن تم إعادة عرض List (لونه أزرق). لا أصر على استخدام PureComponent مقابل MyList . على الرغم من أنني نفذت sCU مقابل MyList حتى لا يتم إعادة تصييرها ، فإن List __ يتم إعادة التقديم__.

تضمين التغريدة
لقد أنشأت مثالًا على الحد الأدنى من التكاثر:

import React, { Component } from 'react';

import StylesProvider from '@material-ui/styles/StylesProvider';
import ThemeProvider from '@material-ui/styles/ThemeProvider';

import { createMuiTheme } from '@material-ui/core';

import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';

const theme = createMuiTheme({});

const MyListItem = React.memo(ListItem, (prev, next) => prev.selected === next.selected);

class App extends Component {
  state = {
    selected: null,
  }
  render() {
    return (
      <StylesProvider>
        <ThemeProvider theme={theme}>
          <List>
            {[0, 1, 2, 3, 4].map(el => (
              <MyListItem
                button
                selected={el === this.state.selected}
                onClick={() => this.setState({ selected: el })}
              >
                {el}
              </MyListItem>
            ))}
          </List>
        </ThemeProvider>
      </StylesProvider>
    );
  }
}

export default App;

تفاعل نتائج المحلل (بعد النقر على عنصر القائمة الرابع):

image

كما ترى ، يعمل كما هو متوقع ، أي لا توجد عمليات إعادة تصيير إضافية (باستثناء ButtonBase داخل ListItem s). المشكلة هي أن هذا التكاثر _أدنى _ جدا؛ هناك الكثير من الأشياء التي تخطيتها.

أعلم أنه لا يمكنك إخباري ما هو الخطأ في الكود الخاص بي الذي يتسبب في عمليات إعادة تصيير إضافية. لكني أطرح عليك سؤالاً: ما الذي يمكن أن يتسبب في إعادة تصيير مكونات WithStylesInner التي تغلف مكونات MUI؟

@ mkermani144 ما رأيك في هذا الإصلاح؟

--- a/packages/material-ui/src/List/List.js
+++ b/packages/material-ui/src/List/List.js
@@ -40,6 +40,13 @@ const List = React.forwardRef(function List(props, ref) {
     ...other
   } = props;

+  const context = React.useMemo(
+    () => ({
+      dense,
+    }),
+    [dense],
+  );
+
   return (
     <Component
       className={clsx(
@@ -54,7 +61,7 @@ const List = React.forwardRef(function List(props, ref) {
       ref={ref}
       {...other}
     >
-      <ListContext.Provider value={{ dense }}>
+      <ListContext.Provider value={context}>
         {subheader}
         {children}
       </ListContext.Provider>

هل تريد تقديم طلب سحب؟ :) نحن نستخدم نفس الإستراتيجية مع مكون الجدول. إنه يعمل بشكل رائع. شكرا لك على الإبلاغ عن المشكلة!

تضمين التغريدة هذا هو بالضبط ما اقترحه Pajn سابقًا. لقد قدمت PR .

تم دمج 14934 ؛ ومع ذلك ، قد يصبح المكون List عقبة في الأداء إذا كان كبيرًا بما يكفي ، بغض النظر عن مقدار تحسينه. ألا يجب أن نقدم مثالاً يوضح استخدام react-window أو react-virtualized مع List ، مثل الذي لدينا في Table docs؟

ألا يجب أن نقدم مثالاً يوضح استخدام نافذة رد الفعل أو التفاعل الافتراضي مع مكون القائمة ، مثل الذي لدينا في مستندات الجدول؟

سيكون ذلك رائعًا: +1:

Fwiw لقد أنشأت تطبيق دردشة ويحتاج التطبيق إلى عرض قائمة كبيرة من جهات الاتصال. واجهتني نفس المشكلة
@ mkermani144 كان.

https://stackoverflow.com/questions/55969987/why-do-the-children-nodes-rerender-when-the-parent-node-is-not-even-being-update/55971559

@ henrylearn2rock هل فكرت في استخدام المحاكاة الافتراضية؟ لقد أضفنا عرضًا توضيحيًا للقائمة: https://next.material-ui.com/demos/lists/#virtualized -list.

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

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

هذه ليست طريقة عمل React.PureComponent أو React.memo. إنه يؤثر فقط على المكون نفسه. قد لا يزال يتعين على الأطفال إعادة العرض إذا تغير السياق.

pytyl هل يمكنك مشاركة الكود حيث استخدمت PureComponent وتوقعت أن تمنع أي إعادة تصيير في الشجرة الفرعية؟

@ eps1lon ، تجعل الوثائق التالية الأمر يبدو وكأنه إرجاع خطأ من shouldComponentUpdate يتخطى تلقائيًا إعادة تصيير المكونات الفرعية.
https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action

نظرًا لأن shouldComponentUpdate أعاد خطأ للشجرة الفرعية المتجذرة في C2 ، لم تحاول React تصيير C2 ، وبالتالي لم يكن عليها حتى استدعاء shouldComponentUpdate على C4 و C5.

ربما أكون مخطئا في هذا؟ فيما يلي لقطة من ملف التعريف الخاص بي. من أجل الاختبار فقط ، أعيد صراحة القيمة false لـ shouldComponentUpdate في مكون القائمة الخاص بي:

Screen Shot 2019-05-08 at 7 46 32 PM

أدى هذا إلى عدم إعادة تصيير جميع مكونات الأطفال الخاصة بي (الفئات ، والفئة ، وعناصر الفئة ، والفئة العنصر). يبدو أن العديد من الأشياء المتعلقة بـ MUI يتم إعادة عرضها في الجزء السفلي مما يتسبب في حدوث الكثير من التأخير. أشياء مثل withStyles ، Typography ، ButtonBase. لا يزال رد الفعل جديدًا بعض الشيء ، لذا يرجى المعذرة لجهلي. يوجد أدناه الكود الخاص بي لمكون القائمة (حيث أعيد خطأ لـ shouldComponentUpdate):

import React, { Component } from "react";
import Categories from "./Categories";
import { withStyles, Paper } from "@material-ui/core";

const styles = theme => ({
  root: {
    paddingTop: 0,
    marginLeft: theme.spacing.unit * 2,
    marginRight: theme.spacing.unit * 2,
    marginTop: theme.spacing.unit * 1
  }
});

class Menu extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.categories.length == this.props.categories.length) {
      return false;
    }
    return true;
  }

  render() {
    const { classes, categories } = this.props;

    return (
      <Paper className={classes.root}>
        <Categories categories={categories} />
      </Paper>
    );
  }
}

export default withStyles(styles)(Menu);

سأحتاج إلى أكواد وصندوق كامل لفهم المشكلة.

@ eps1lon سأحاول إنتاج واحد ليوم غد. شكرا لك.

@ eps1lon هنا هو codepen:
https://codesandbox.io/s/348kwwymj5

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

نظام
MacBook Pro (Retina ، 13 بوصة ، أوائل 2015)
3.1 جيجاهرتز Intel Core i7
Firefox 66.0.3

الحالة 1 (ينقر المستخدم على عنصر القائمة)
مدة العرض: 218ms

Screen Shot 2019-05-10 at 4 45 26 AM

Screen Shot 2019-05-10 at 4 45 48 AM

الحالة 2 (ينقر المستخدم على زر "إضافة إلى الطلب" في مربع الحوار)
مدة التقديم: 356ms

Screen Shot 2019-05-10 at 4 46 24 AM

Screen Shot 2019-05-10 at 4 47 10 AM

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

نظرًا لأنه يتم إعادة عرض WithStyles (ButtonBase) ، أفترض أن WithStyles يستخدم سياقًا تم إعادة إنشائه على الرغم من أنه لا يحتاج إلى ذلك.

تمكنت من العثور على هذا https://github.com/mui-org/material-ui/blob/048c9ced0258f38aa38d95d9f1cfa4c7b993a6a5/packages/material-ui-styles/src/StylesProvider/StylesProvider.js#L38 ولكن لا يمكنني العثور على مكان فيه يتم استخدام StylesProvider في الكود الفعلي (بحث GitHubs ليس جيدًا جدًا) ولكن قد يكون السبب.

هل يعرف @ eps1lon ما إذا كان هذا هو السبب؟ إذا كان الأمر كذلك ، فمن المحتمل أن يؤدي استخدام useMemo الموجود في كائن السياق إلى إصلاح ذلك. على الرغم من أنني لا أعرف ما إذا كانت الخيارات المحلية مستقرة أو ما إذا كان يجب نشر useMemo بشكل أكبر.

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

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

pytyl لقد

@ eps1lon أعتقد أننا يجب أن نغلق هذه المسألة. سيكون من الأفضل التركيز على القضايا المحددة على وجه التحديد.

TL ؛ DR: إنشاء شرائح سياق ، وحفظ قيم السياق ، ولا توجد مشكلة في واجهة المستخدم المادية على وجه التحديد: https://codesandbox.io/s/8lx6vk2978

هل قمت ببعض التنقيب والمشكلة هي أن لديك هذا السياق العالمي الكبير الذي تمت إعادة إنشائه أثناء العرض. تقوم بإعادة عرض تطبيقك عند النقر في أي نقطة يتم إعادة إنشاء السياق العام. يستمع CategoryItem الخاص بك إليه والذي يظهر 100 مرة في تطبيقك. نظرًا لأن لديك قائمة 100 مادة-واجهة مستخدم ، فإنك تواجه الموت الكلاسيكي بألف تخفيضات.

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

يمكن أن يؤدي هذا إلى إنشاء شجرة كبيرة جدًا ويجعل الدعائم جحيمة كلما زاد عدد السياقات لديك. أشجعك على إلقاء نظرة على useContext . سيساعدك كثيرًا إذا بدأت في مواجهة هذه المشكلات.

oliviertassinari من الجيد جمع المزالق الشائعة بالحلول. يمكننا أن نقرر ما إذا كنا نريد إنشاء قضايا منفصلة عنه.

oliviertassinari @ شكرًا

لقد واجهت للتو مشكلة في أداء العرض البطيء. لقد قمت بحلها تمامًا عن طريق استبدال جميع مثيلات المكون <Box> بـ <div> s. لقد قمت بتصحيح الأخطاء باستخدام رد فعل devtools flamegraph ، وذهبت من حوالي 420 مللي ثانية إلى 20 مللي ثانية.

مع <Box> es؛
Screen Shot 2019-08-16 at 12 47 25 AM

بدون <Box> es:
Screen Shot 2019-08-16 at 12 42 38 AM

mankittens يمكنك الاحتفاظ بمكون Box ، باستخدام مكونات مصممة كمحرك نمط. سيكون الأداء أفضل بكثير. يجب أن تتحسن مع JSS في المستقبل القريب https://github.com/mui-org/material-ui/pull/16858.

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

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

revskill10 picture revskill10  ·  3تعليقات

iamzhouyi picture iamzhouyi  ·  3تعليقات

chris-hinds picture chris-hinds  ·  3تعليقات

ghost picture ghost  ·  3تعليقات

pola88 picture pola88  ·  3تعليقات