تقسيم الرمز باستخدام React.lazy وSuspense

لن تحتاج أبدًا إلى شحن رموز أكثر من اللازم للمستخدمين، لذا قسِّم الحِزم لضمان عدم حدوث ذلك مطلقًا.

تسهِّل طريقة 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 الذي يسمح لك بعرض أي تفاعل. المكون كحالة تحميل. يوضّح المثال التالي طريقة عمل هذه الميزة. لا يتم عرض الصورة الرمزية إلا عند النقر على الزر، حيث يتم عرض الطلب ثم إجراء استرداد الرمز اللازم لـ AvatarComponent المُعلَّقة. في هذه الأثناء، يتم عرض عنصر التحميل الاحتياطي.

هنا، الرمز الذي يتألف من AvatarComponent صغير وهو سبب ظهور مؤشر سريان عمل التحميل لفترة قصيرة فقط أكبر يمكن أن يستغرق تحميل المكونات وقتًا أطول، خاصةً على اتصالات الشبكة الضعيفة.

لتوضيح كيفية عمل ذلك بشكل أفضل:

  • لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط ملء الشاشة ملء الشاشة
  • اضغط على "Control+Shift+J" (أو "Command+Option+J" على أجهزة Mac) لفتح "أدوات مطوري البرامج".
  • انقر على علامة التبويب الشبكة.
  • انقر على القائمة المنسدلة Throttling (التقييد)، التي يتم ضبطها على بدون تقييد تلقائيًا. اختَر شبكة الجيل الثالث السريعة.
  • انقر على الزر انقر على Me في التطبيق.

سيظهر مؤشر التحميل لفترة أطول الآن. لاحظ كيف أن كل التعليمات البرمجية التي في AvatarComponent يتم جلبها باعتبارها مقطعًا منفصلاً.

لوحة شبكة في &quot;أدوات مطوّري البرامج&quot; تعرض ملف sample.js واحدًا يتم تنزيله

تعليق مكونات متعددة

من ميزات 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. طلبك، اتبع الخطوات التالية:

  1. ابدأ على مستوى المسار. والمسارات هي أبسط الطرق لتحديد نقاط تطبيقك التي يمكن تقسيمها. تشير رسالة الأشكال البيانية مستندات التفاعل عرض كيفية استخدام Suspense إلى جانب react-router
  2. حدِّد أي مكونات كبيرة في صفحة على موقعك لا يتم عرضها إلا على تفاعلات معينة للمستخدم (مثل النقر فوق الزر). تقسيم هذه إلى تقليل أحمال JavaScript.
  3. ننصحك بتقسيم أي شيء آخر خارج الشاشة وغير مهم المستخدم.