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 फ़ंक्शन, कॉम्पोनेंट को अलग-अलग करने का एक बिल्ट-इन तरीका देता है में बहुत कम मेहनत लगती है. आप इसके बाद, जब इसे Suspense के साथ जोड़ा जाता है, तो लोड होने की स्थितियों का ध्यान रखें कॉम्पोनेंट.

सस्पेंस

उपयोगकर्ताओं को बड़े JavaScript पेलोड भेजने में समस्या पेज को पूरी तरह लोड होने में लगने वाला समय. खास तौर पर, कमज़ोर डिवाइसों पर और इंटरनेट कनेक्शन की ज़रूरत पड़ेगी. इस वजह से, कोड को बांटना और लेज़ी लोडिंग होना बेहद उपयोगी है.

हालांकि, इस प्रक्रिया में थोड़ा समय लग सकता है. नेटवर्क पर एक कोड-स्प्लिट कॉम्पोनेंट फ़ेच किया जा रहा है, इसलिए यह ज़रूरी है कि लोड होने की उपयोगी स्थिति दिखाता है. Suspense के साथ React.lazy का इस्तेमाल किया जा रहा है कॉम्पोनेंट इस समस्या को हल करने में मदद करता है.

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 बनाने वाला कोड छोटा है, जो लोड होने वाला स्पिनर कुछ समय के लिए ही क्यों दिखता है. इससे बड़ा कॉम्पोनेंट को लोड होने में ज़्यादा समय लग सकता है. खास तौर पर, ऐसा कमज़ोर नेटवर्क कनेक्शन.

यह कैसे काम करता है, इस बारे में बेहतर तरीके से बताने के लिए:

  • साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन.
  • DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.
  • नेटवर्क टैब पर क्लिक करें.
  • थ्रॉटलिंग ड्रॉपडाउन पर क्लिक करें. यह डिफ़ॉल्ट रूप से कोई थ्रॉटलिंग नहीं पर सेट होता है. फ़ास्ट 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 आपको नेटवर्क के दौरान, कुछ समय के लिए लोड होने की स्थिति दिखाने की अनुमति देता है अनुरोध हुड के तहत किए जाते हैं. लेकिन क्या होगा अगर वे नेटवर्क अनुरोध किसी वजह से? हो सकता है कि आप ऑफ़लाइन हों या शायद आपका वेब ऐप्लिकेशन किसी वर्शन वाले यूआरएल को लेज़ी-लोड करें जो पुराना हो चुका है और सर्वर को दोबारा डिप्लॉय करने के बाद, उपलब्ध नहीं है.

इस तरह की लोडिंग को अच्छी तरह से मैनेज करने के लिए, प्रतिक्रिया का एक स्टैंडर्ड पैटर्न है गड़बड़ियां: गड़बड़ी की सीमा का इस्तेमाल किया जा रहा है. जैसा कि दस्तावेज़ में बताया गया है, अगर कोई भी प्रतिक्रिया कॉम्पोनेंट, गड़बड़ी की सीमा के तौर पर काम करता है, तो वह इनमें से किसी एक को लागू करता है (या दोनों) लाइफ़साइकल तरीकों 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. ऐसी अन्य चीज़ों को अलग-अलग हिस्सों में बांटें जो स्क्रीन पर दिखाई नहीं दे रही हैं और आपके कॉन्टेंट के लिए अहम नहीं हैं उपयोगकर्ता.