Next.js में डाइनैमिक इंपोर्ट के साथ कोड बांटना

कोड विभाजन और स्मार्ट लोडिंग रणनीतियों की मदद से अपने Next.js ऐप्लिकेशन की स्पीड कैसे बढ़ाएं.

मिलिका मिहाजलिया
मिलिका मिहाजलिया

आपको क्या सीखने को मिलेगा?

इस पोस्ट में अलग-अलग तरह के कोड स्प्लिटिंग के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि Next.js ऐप्लिकेशन की स्पीड बढ़ाने के लिए, डाइनैमिक इंपोर्ट का इस्तेमाल कैसे करें.

रूट-आधारित और कॉम्पोनेंट के हिसाब से कोड को बांटना

डिफ़ॉल्ट रूप से, Next.js हर रूट के लिए आपके JavaScript को अलग-अलग हिस्सों में बांट देता है. जब उपयोगकर्ता आपका ऐप्लिकेशन लोड करते हैं, तो Next.js सिर्फ़ शुरुआती रूट के लिए ज़रूरी कोड भेजता है. जब उपयोगकर्ता ऐप्लिकेशन पर नेविगेट करते हैं, तो वे अन्य रूट से जुड़े हिस्सों को फ़ेच करते हैं. रूट के हिसाब से कोड को बांटने से, एक बार में पार्स और कंपाइल करने वाली स्क्रिप्ट की संख्या कम हो जाती है. इससे पेज लोड होने में कम समय लगता है.

हालांकि, रूट के हिसाब से कोड को बांटना डिफ़ॉल्ट रूप से होता है, फिर भी कॉम्पोनेंट लेवल पर कोड को बांटने की सुविधा की मदद से, लोड होने की प्रोसेस को और ऑप्टिमाइज़ किया जा सकता है. अगर आपके ऐप्लिकेशन में बड़े कॉम्पोनेंट हैं, तो उन्हें अलग-अलग ग्रुप में बांटना अच्छा आइडिया है. इस तरह, ऐसे बड़े कॉम्पोनेंट जो ज़रूरी नहीं हैं या जो सिर्फ़ कुछ उपयोगकर्ता इंटरैक्शन (जैसे कि किसी बटन पर क्लिक करना) पर रेंडर होते हैं उन्हें लेज़ी लोड किया जा सकता है.

Next.js डाइनैमिक import() के साथ काम करता है. इसकी मदद से, JavaScript मॉड्यूल (इसमें रिऐक्ट कॉम्पोनेंट भी शामिल हैं) को डाइनैमिक तरीके से इंपोर्ट किया जा सकता है और हर इंपोर्ट को एक अलग हिस्से के तौर पर लोड किया जा सकता है. इससे आपको कॉम्पोनेंट-लेवल पर कोड को बांटने की सुविधा मिलती है. साथ ही, रिसॉर्स लोडिंग को कंट्रोल किया जा सकता है, ताकि उपयोगकर्ता सिर्फ़ साइट के उस हिस्से के लिए ज़रूरी कोड डाउनलोड करें जिसे वे देख रहे हैं. Next.js में, ये कॉम्पोनेंट डिफ़ॉल्ट रूप से सर्वर साइड से रेंडर किए गए (एसएसआर) होते हैं.

कार्रवाई में डाइनैमिक इंपोर्ट

इस पोस्ट में सैंपल ऐप्लिकेशन के कई वर्शन शामिल हैं. इनमें एक बटन वाला एक सामान्य पेज शामिल है. बटन पर क्लिक करने पर, आपको एक प्यारा सा कुत्ते का बच्चा दिखेगा. ऐप्लिकेशन के हर वर्शन पर जाने पर, आपको दिखेगा कि डाइनैमिक इंपोर्ट स्टैटिक इंपोर्ट से कैसे अलग हैं और उनके साथ कैसे काम किया जाता है.

ऐप्लिकेशन के पहले वर्शन में, पिल्ला components/Puppy.js में रहता है. पेज पर पिल्ला दिखाने के लिए, ऐप्लिकेशन स्टैटिक इंपोर्ट स्टेटमेंट के साथ index.js में Puppy कॉम्पोनेंट को इंपोर्ट करता है:

import Puppy from "../components/Puppy";

यह देखने के लिए कि Next.js ऐप्लिकेशन को कैसे बंडल करता है, DevTools में नेटवर्क ट्रेस की जांच करें:

  1. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

  2. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.

  3. नेटवर्क टैब पर क्लिक करें.

  4. कैश मेमोरी बंद करें चेकबॉक्स चुनें.

  5. पेज को फिर से लोड करें.

पेज को लोड करने पर, Puppy.js कॉम्पोनेंट के साथ-साथ सभी ज़रूरी कोड index.js में बंडल हो जाते हैं:

DevTools नेटवर्क टैब, जिसमें छह JavaScript फ़ाइलें दिख रही हैं: index.js, app.js, webpack.js, मुख्य.js, 0.js, और डीएल (डाइनैमिक-लिंक लाइब्रेरी) फ़ाइल.

मुझे क्लिक करें बटन दबाने पर, नेटवर्क टैब में सिर्फ़ JPEG फ़ॉर्मैट के पिल्ले का अनुरोध जोड़ा जाता है:

DevTools नेटवर्क टैब पर क्लिक करने के बाद, वही छह JavaScript फ़ाइलें और एक इमेज दिख रही है.

इस तरीके का नुकसान यह है कि भले ही उपयोगकर्ता पिल्ले को देखने के लिए बटन पर क्लिक नहीं करते हैं, लेकिन उन्हें Puppy कॉम्पोनेंट लोड करना होगा, क्योंकि यह index.js में शामिल है. इस छोटे से उदाहरण में यह कोई बड़ी बात नहीं है, लेकिन असल में इस्तेमाल किए जाने वाले ऐप्लिकेशन में, बड़े कॉम्पोनेंट को ज़रूरत होने पर ही लोड करना एक बड़ा सुधार है.

अब ऐप्लिकेशन का दूसरा वर्शन देखें, जिसमें स्टैटिक इंपोर्ट को डाइनैमिक इंपोर्ट से बदल दिया जाता है. Next.js में next/dynamic शामिल है, जिसकी मदद से Next.js में किसी भी कॉम्पोनेंट के लिए डाइनैमिक इंपोर्ट का इस्तेमाल किया जा सकता है:

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

नेटवर्क ट्रेस की जांच करने के लिए, पहले उदाहरण में दिया गया तरीका अपनाएं.

पहली बार ऐप्लिकेशन लोड करने पर, सिर्फ़ index.js डाउनलोड होता है. इस बार यह 0.5 केबी से छोटा है (यह 37.9 केबी से कम होकर 37.4 केबी हो गया है) क्योंकि इसमें Puppy कॉम्पोनेंट का कोड शामिल नहीं है:

DevTools नेटवर्क वही छह JavaScript फ़ाइलें दिखाता है. हालांकि, index.js अब 0.5 केबी छोटा हो गया है.

Puppy कॉम्पोनेंट अब एक अलग हिस्से 1.js में है, जो सिर्फ़ बटन दबाने पर ही लोड होता है:

बटन पर हुए क्लिक के बाद DevTools नेटवर्क टैब. इसमें ज़्यादा 1.js फ़ाइल और फ़ाइल की सूची के निचले हिस्से में जोड़ी गई इमेज दिखती है.

असल दुनिया के ऐप्लिकेशन में, कॉम्पोनेंट अक्सर काफ़ी बड़े होते हैं और लेज़ी लोडिंग आपके शुरुआती JavaScript पेलोड को सैकड़ों किलोबाइट तक कम कर सकती है.

कस्टम लोडिंग इंडिकेटर वाले डाइनैमिक इंपोर्ट

जब रिसॉर्स लेज़ी-लोड होते हैं, तो लोड होने में लगने वाले समय का इंडिकेटर देना बेहतर होता है. Next.js में, dynamic() फ़ंक्शन में अतिरिक्त तर्क देकर ऐसा किया जा सकता है:

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

लोड होने वाले इंडिक्टर को काम करने के लिए, DevTools में धीमे नेटवर्क कनेक्शन को सिम्युलेट करें:

  1. साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

  2. DevTools खोलने के लिए, `Control+Shift+J` (या Mac पर `Command+Option+J`) दबाएं.

  3. नेटवर्क टैब पर क्लिक करें.

  4. कैश मेमोरी बंद करें चेकबॉक्स चुनें.

  5. Throttling ड्रॉप-डाउन सूची में, फ़ास्ट 3G चुनें.

  6. मुझे क्लिक करें बटन दबाएं.

अब आपके बटन पर क्लिक करने से, कॉम्पोनेंट लोड होने में कुछ समय लग सकता है और ऐप्लिकेशन उस दौरान "लोड हो रहा है..." मैसेज दिखाता है.

गहरे रंग की स्क्रीन पर टेक्स्ट

SSR के बिना डाइनैमिक इंपोर्ट

अगर आपको किसी कॉम्पोनेंट को सिर्फ़ क्लाइंट साइड (जैसे कि चैट विजेट) पर रेंडर करना है, तो ssr विकल्प को false पर सेट करके ऐसा किया जा सकता है:

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

नतीजा

डाइनैमिक इंपोर्ट की सुविधा के साथ, Next.js आपको कॉम्पोनेंट-लेवल पर कोड को अलग-अलग करने की सुविधा देता है. इससे आपका JavaScript पेलोड कम हो सकता है और ऐप्लिकेशन लोड होने में लगने वाला समय बढ़ सकता है. सभी कॉम्पोनेंट, सर्वर साइड से डिफ़ॉल्ट रूप से रेंडर होते हैं. ज़रूरत पड़ने पर, इस विकल्प को बंद किया जा सकता है.