تقسیم کد با React.lazy و Suspense

شما هرگز نیازی به ارسال کد بیش از حد لازم برای کاربران خود ندارید، بنابراین بسته های خود را تقسیم کنید تا مطمئن شوید که هرگز این اتفاق نمی افتد!

روش React.lazy تقسیم کد یک برنامه React را در سطح جزء با استفاده از واردات پویا آسان می کند.

import React, { lazy } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const DetailsComponent = () => (
  <div>
    <AvatarComponent />
  </div>
)

چرا این مفید است؟

یک برنامه بزرگ React معمولاً شامل بسیاری از مؤلفه‌ها، روش‌های کاربردی و کتابخانه‌های شخص ثالث است. اگر تلاشی برای بارگیری بخش‌های مختلف برنامه تنها در صورت نیاز انجام نشود، یک بسته بزرگ جاوا اسکریپت به محض بارگذاری صفحه اول برای کاربران شما ارسال می‌شود. این می تواند عملکرد صفحه را به طور قابل توجهی تحت تاثیر قرار دهد.

تابع React.lazy یک روش داخلی برای تفکیک اجزای یک برنامه به تکه های جداگانه جاوا اسکریپت با کار بسیار کمی ارائه می دهد. پس از آن می توانید از حالت های بارگذاری مراقبت کنید که آن را با مؤلفه Suspense جفت کنید.

تعلیق

مشکل ارسال بار بزرگ جاوا اسکریپت به کاربران، مدت زمانی است که طول می کشد تا صفحه بارگذاری شود، به خصوص در دستگاه های ضعیف تر و اتصالات شبکه. به همین دلیل است که تقسیم کد و بارگذاری تنبل بسیار مفید است.

با این حال، زمانی که یک مؤلفه تقسیم کد از طریق شبکه واکشی می شود، همیشه یک تأخیر جزئی وجود دارد که کاربران باید آن را تجربه کنند، بنابراین نمایش وضعیت بارگذاری مفید بسیار مهم است. استفاده از 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 تشکیل می‌دهد، کوچک است، به همین دلیل است که چرخنده بارگذاری فقط برای مدت زمان کوتاهی نمایش داده می‌شود. بارگذاری اجزای بزرگتر، به خصوص در اتصالات ضعیف شبکه، ممکن است بسیار بیشتر طول بکشد.

برای نشان دادن بهتر نحوه کار:

  • برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .
  • «Control+Shift+J» (یا «Command+Option+J» در Mac) را فشار دهید تا DevTools باز شود.
  • روی تب Network کلیک کنید.
  • روی منوی کشویی Throttling کلیک کنید که به طور پیش فرض روی No throttling تنظیم شده است. Fast 3G را انتخاب کنید.
  • روی دکمه کلیک کن در برنامه کلیک کنید.

نشانگر بارگیری اکنون برای مدت طولانی تری نشان داده می شود. توجه کنید که چگونه تمام کدهایی که AvatarComponent تشکیل می دهند به عنوان یک تکه جداگانه واکشی می شوند.

پانل شبکه DevTools که یک فایل chunk.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. از سطح مسیر شروع کنید. مسیرها ساده ترین راه برای شناسایی نقاطی از برنامه شما هستند که می توانند تقسیم شوند. اسناد React نشان می‌دهد که چگونه می‌توان Suspense به همراه react-router استفاده کرد.
  2. هر مؤلفه بزرگی را در یک صفحه در سایت خود شناسایی کنید که فقط در تعاملات خاص کاربر (مانند کلیک کردن روی یک دکمه) رندر می شود. تقسیم این مؤلفه ها بارهای جاوا اسکریپت شما را به حداقل می رساند.
  3. هر چیز دیگری را که خارج از صفحه است و برای کاربر حیاتی نیست تقسیم کنید.