لست بحاجة إلى شحن رمز أكثر من اللازم للمستخدمين، لذا قسّم حزمك للتأكد من عدم حدوث ذلك أبدًا!
تسهّل طريقة React.lazy تقسيم الرمز البرمجي لتطبيق React على مستوى المكوّن باستخدام عمليات الاستيراد الديناميكية.
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
ما هي فائدة ذلك؟
يتكون تطبيق React الكبير عادةً من العديد من المكونات وطرق الأدوات المساعدة ومكتبات الجهات الخارجية. إذا لم يتم بذل جهد لمحاولة تحميل أجزاء مختلفة من التطبيق فقط عند الحاجة إليها، سيتم إرسال حزمة واحدة كبيرة من JavaScript إلى المستخدمين فور تحميل الصفحة الأولى. ويمكن أن يؤثر ذلك في أداء الصفحة بشكل كبير.
توفّر الدالة React.lazy طريقة مضمّنة لفصل المكوّنات في أحد التطبيقات إلى أجزاء منفصلة من JavaScript مع القليل من الجهد. يمكنك بعد ذلك الاهتمام بحالات التحميل عند دمجها مع مكوّن Suspense.
تشويق
تكمن مشكلة إرسال حمولة JavaScript كبيرة إلى المستخدمين في طول الوقت الذي يستغرقه تحميل الصفحة، خاصةً على الأجهزة والاتصالات الضعيفة بالشبكة. لهذا السبب، يُعدّ تقسيم الرموز البرمجية والتحميل الكسول مفيدًا للغاية.
ومع ذلك، سيكون هناك دائمًا تأخير طفيف يواجهه المستخدمون عند جلب مكوّن مقسّم عبر الشبكة، لذا من المهم عرض حالة تحميل مفيدة. يساعد استخدام React.lazy مع مكوّن Suspense في حلّ هذه المشكلة.
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
</Suspense>
)
يقبل Suspense مكوّن fallback الذي يسمح لك بعرض أي مكوّن React كحالة تحميل. يوضّح المثال التالي طريقة عمل ذلك.
لا يتم عرض الصورة الرمزية إلا عند النقر على الزر، حيث يتم إرسال طلب لاسترداد الرمز اللازم لـ AvatarComponent المعلّق.
في هذه الأثناء، يتم عرض مكوّن التحميل الاحتياطي.
في هذه الحالة، يكون الرمز الذي يتألف منه AvatarComponent صغيرًا، ولهذا السبب يظهر مؤشر التحميل لفترة قصيرة فقط. يمكن أن تستغرق المكونات الأكبر وقتًا أطول في التحميل، خاصةً في اتصالات الشبكة الضعيفة.
لتوضيح طريقة عمل ذلك بشكل أفضل:
- لمعاينة الموقع الإلكتروني، انقر على عرض التطبيق، ثم انقر على
ملء الشاشة
.
- اضغط على `Control+Shift+J` (أو `Command+Option+J` على أجهزة Mac) لفتح "أدوات مطوّري البرامج".
- انقر على علامة التبويب الشبكة.
- انقر على القائمة المنسدلة التقييد التي تكون مضبوطة على بدون تقييد تلقائيًا. اختَر شبكة الجيل الثالث السريعة.
- انقر على الزر انقر هنا (Click Me) في التطبيق.
سيظهر مؤشر التحميل لفترة أطول الآن. لاحظ كيف يتم جلب كل الرموز البرمجية التي تشكّل AvatarComponent كجزء منفصل.
تعليق مكوّنات متعددة
من الميزات الأخرى في Suspense أنّه يتيح لك تعليق تحميل مكوّنات متعددة، حتى إذا كان يتم تحميلها جميعًا بشكل بطيء.
على سبيل المثال:
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
)
هذه طريقة مفيدة للغاية لتأخير عرض مكونات متعددة أثناء عرض حالة تحميل واحدة فقط. بعد الانتهاء من جلب جميع المكونات، يتمكن المستخدم من رؤيتها جميعًا معروضة في نفس الوقت.
يمكنك الاطّلاع على ذلك من خلال التضمين التالي:
بدون ذلك، من السهل مواجهة مشكلة التحميل المتدرج، أو تحميل أجزاء مختلفة من واجهة المستخدم واحدة تلو الأخرى مع وجود مؤشر تحميل خاص بكل منها. وقد يؤدي ذلك إلى جعل تجربة المستخدم تبدو أكثر إزعاجًا.
التعامل مع حالات تعذُّر التحميل
يتيح لك Suspense عرض حالة تحميل مؤقتة أثناء إجراء طلبات الشبكة في الخلفية. ولكن ماذا لو فشلت طلبات الشبكة هذه لسبب ما؟ قد تكون غير متصل بالإنترنت، أو قد يكون تطبيق الويب يحاول
التحميل الكسول عنوان URL لإصدار قديم
ولم يعُد متاحًا بعد إعادة نشر الخادم.
يحتوي React على نمط قياسي للتعامل بسلاسة مع هذه الأنواع من أخطاء التحميل: استخدام حدود الخطأ. كما هو موضّح في المستندات، يمكن لأي مكوّن React أن يعمل كحدود للأخطاء إذا كان ينفّذ إحدى (أو كلتا) طريقتَي مراحل النشاط static getDerivedStateFromError() أو componentDidCatch().
لرصد حالات تعذُّر التحميل الكسول ومعالجتها، يمكنك تضمين مكوّن Suspense
في مكوّنات رئيسية تعمل كحدود للأخطاء. داخل طريقة render() لحدود الخطأ، يمكنك عرض العناصر الفرعية كما هي في حال عدم وجود خطأ، أو عرض رسالة خطأ مخصّصة في حال حدوث خطأ:
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {hasError: false};
}
static getDerivedStateFromError(error) {
return {hasError: true};
}
render() {
if (this.state.hasError) {
return <p>Loading failed! Please reload.</p>;
}
return this.props.children;
}
}
const DetailsComponent = () => (
<ErrorBoundary>
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
</ErrorBoundary>
)
الخاتمة
إذا لم تكن متأكدًا من أين تبدأ في تطبيق تقسيم الرمز على تطبيق React، فاتبع الخطوات التالية:
- ابدأ على مستوى المسار. المسارات هي أبسط طريقة لتحديد نقاط
تطبيقك التي يمكن تقسيمها. توضّح
مستندات React
كيفية استخدام
Suspenseمعreact-router. - حدِّد أي مكوّنات كبيرة على صفحة في موقعك الإلكتروني لا يتم عرضها إلا عند تفاعلات معيّنة من المستخدمين (مثل النقر على زر). سيؤدي تقسيم هذه المكوّنات إلى تقليل حمولات JavaScript.
- ننصحك بتقسيم أي محتوى آخر خارج الشاشة وغير مهم للمستخدم.