React.lazy ve Suspense ile kod bölme

Kullanıcılarınıza gerekenden fazla kod göndermeniz gerekmez. Bu nedenle, bu durumun hiç yaşanmaması için paketlerinizi bölün.

React.lazy yöntemi, dinamik içe aktarma işlemleri kullanarak bir React uygulamasının kodunu bileşen düzeyinde bölme işlemini kolaylaştırır.

import React, { lazy } from 'react';

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

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

Bu neden yararlı?

Büyük bir React uygulaması genellikle birçok bileşen, yardımcı program yöntemi ve üçüncü taraf kitaplıklardan oluşur. Bir uygulamanın farklı bölümlerini yalnızca ihtiyaç duyulduğunda yüklemeye çalışırsanız kullanıcılarınız ilk sayfayı yükler yüklemez büyük bir JavaScript paketi gönderilir. Bu durum sayfa performansını önemli ölçüde etkileyebilir.

React.lazy işlevi, bir uygulamadaki bileşenleri çok az çalışmayla ayrı JavaScript parçalarına ayırmak için yerleşik bir yöntem sağlar. Ardından, Suspense bileşeniyle birlikte kullanırken yükleme durumlarını yönetebilirsiniz.

Gerilim

Kullanıcılara büyük bir JavaScript yük göndermenin sorunu, özellikle daha zayıf cihazlarda ve ağ bağlantılarında sayfanın yüklenmesinin tamamlanması için gereken süredir. Bu nedenle kod bölme ve yavaş yükleme son derece yararlıdır.

Bununla birlikte, bir kod bölme bileşeni ağ üzerinden getirilirken kullanıcıların yaşadığı küçük bir gecikme her zaman olacaktır. Bu nedenle, kullanışlı bir yükleme durumu göstermek önemlidir. React.lazySuspense bileşeniyle kullanmak bu sorunu çözmeye yardımcı olur.

import React, { lazy, Suspense } from 'react';

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

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
  </Suspense>
)

Suspense, herhangi bir React bileşenini yükleme durumu olarak görüntülemenize olanak tanıyan bir fallback bileşeni kabul eder. Aşağıdaki örnekte bunun işleyiş şekli gösterilmektedir. Avatar yalnızca düğme tıklandığında oluşturulur. Ardından, askıya alınmış AvatarComponent için gerekli kodu almak üzere bir istek gönderilir. Bu sırada yedek yükleme bileşeni gösterilir.

Burada, AvatarComponent öğesini oluşturan kod küçüktür. Bu nedenle, yükleme spinner'ı yalnızca kısa bir süre gösterilir. Özellikle zayıf ağ bağlantılarında büyük bileşenlerin yüklenmesi çok daha uzun sürebilir.

Bunun nasıl çalıştığına dair daha iyi bir örnek vermek için:

  • Siteyi önizlemek için Uygulamayı Görüntüle'ye, ardından Tam Ekran'a tam ekran basın.
  • Geliştirici Araçları'nı açmak için "Control+Üst Karakter+J" (veya Mac'te "Command+Option+J") tuşlarına basın.
  • sekmesini tıklayın.
  • Varsayılan olarak Kısıtlama yok şeklinde ayarlanan Hızlandırma açılır listesini tıklayın. Hızlı 3G'yi seçin.
  • Uygulamadaki Beni Tıkla düğmesini tıklayın.

Yükleme göstergesi artık daha uzun süre gösterilecek. AvatarComponent öğesini oluşturan tüm kodun ayrı bir parça olarak nasıl getirildiğine dikkat edin.

Bir chunk.js dosyasının indirilmesini gösteren DevTools ağ paneli

Birden çok bileşeni askıya alma

Suspense ürününün bir diğer özelliği de tümü geç yüklenmiş olsa bile birden fazla bileşenin yüklenmesini askıya almanıza olanak tanımasıdır.

Örneğin:

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>
)

Bu, yalnızca tek bir yükleme durumu gösterirken birden fazla bileşenin oluşturulmasını geciktirmek için son derece kullanışlı bir yöntemdir. Tüm bileşenler getirildikten sonra kullanıcı, bunların hepsini aynı anda görüntüleyebilir.

Bunu aşağıdaki yerleşik öğeyle görebilirsiniz:

Bu olmadan, aşamalı yükleme sorunuyla veya kullanıcı arayüzünün kendi yükleme göstergelerine sahip farklı bölümlerin birbiri ardına yüklenmesi sorunuyla karşılaşabilirsiniz. Bu durum, kullanıcı deneyimini daha sarsıcı hale getirebilir.

Yükleme hatalarını işleme

Suspense, arka planda ağ istekleri yapılırken geçici bir yükleme durumu göstermenize olanak tanır. Peki, bu ağ istekleri herhangi bir nedenle başarısız olursa ne olur? İnternete bağlı olmayabilirsiniz veya web uygulamanız, sunucu yeniden dağıtımı sonrasında artık kullanılamayan ve güncel olmayan bir sürümlü URL'yi yavaş yüklemeye çalışıyor olabilir.

React, bu tür yükleme hatalarını sorunsuz bir şekilde ele almak için standart bir kalıba sahiptir: hata sınırı kullanma. Belgelerde açıklandığı gibi, static getDerivedStateFromError() veya componentDidCatch() yaşam döngüsü yöntemlerinden birini (veya her ikisini de) uygulayan tüm React bileşenleri, hata sınırı olarak kullanılabilir.

Yavaş yükleme hatalarını algılayıp işlemek için Suspense bileşeninizi hata sınırı görevi gören bir üst bileşenle sarabilirsiniz. Hata sınırının render() yönteminde, hata yoksa çocukları olduğu gibi oluşturabilir veya bir sorun oluşursa özel bir hata mesajı oluşturabilirsiniz:

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>
)

Sonuç

React uygulamanıza kod bölme özelliğini nereden uygulayacağınızdan emin değilseniz aşağıdaki adımları uygulayın:

  1. Rota düzeyinden başlayın. Rotalar, uygulamanızda bölünebilecek noktaları belirlemenin en basit yoludur. Tepki dokümanları, Suspense'nin react-router ile birlikte nasıl kullanılabileceğini gösterir.
  2. Sitenizdeki bir sayfada yalnızca belirli kullanıcı etkileşimlerinde (ör. bir düğmenin tıklanması) oluşturulan büyük bileşenleri tanımlayın. Bu bileşenleri bölmek, JavaScript yüklerinizi en aza indirir.
  3. Ekran dışında olan ve kullanıcı için kritik olmayan diğer tüm öğeleri bölmeyi düşünebilirsiniz.