वेब ऐप्लिकेशन को तेज़ी से लोड करने की तकनीक, यहां तक कि फ़ीचर फ़ोन पर भी लोड होती है

हमने PROXX में कोड को बांटने, कोड इनलाइन करने, और सर्वर साइड रेंडरिंग का इस्तेमाल कैसे किया.

Google I/O 2019 में मेरिको, जेक और मैंने PROXX भेजा. यह वेब के लिए एक आधुनिक माइन्सवीपर-क्लोन है. जो चीज़ PROXX को सबसे अलग बनाती है, वह है सुलभता (इसे स्क्रीनरीडर की मदद से चलाया जा सकता है!) और एक फ़ीचर फ़ोन पर, जैसे कि महंगे डेस्कटॉप डिवाइस पर चलाना. फ़ीचर फ़ोन कई तरह से सीमित होते हैं:

  • कमज़ोर सीपीयू
  • कमज़ोर या गैर-मौजूद जीपीयू
  • ऐसी छोटी स्क्रीन जिनमें टच इनपुट मौजूद नहीं हैं
  • बहुत कम मेमोरी

लेकिन वे एक आधुनिक ब्राउज़र चलाते हैं और बहुत किफायती हैं. इस वजह से, फ़ीचर फ़ोन उभरते हुए बाज़ारों में तेज़ी से तरक्की कर रहे हैं. इस प्राइस पॉइंट की मदद से, ऐसे नए दर्शकों को ऑनलाइन प्लैटफ़ॉर्म पर आने और आधुनिक वेब का इस्तेमाल करने में मदद मिलती है जिनके लिए पहले यह सुविधा उपलब्ध नहीं थी. साल 2019 में अनुमान लगाया गया है कि सिर्फ़ भारत में करीब 40 करोड़ फ़ीचर फ़ोन बिकेंगे. इसलिए, हो सकता है कि फ़ीचर फ़ोन के उपयोगकर्ताओं की संख्या इनमें शामिल हो. इसके अलावा, उभरते हुए बाज़ारों में इंटरनेट कनेक्शन की स्पीड 2G जैसी है. हमने कैसे PROXX को फ़ीचर फ़ोन के साथ ठीक से काम करने में मदद की?

PROXX गेमप्ले.

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

यह दो हिस्सों की सीरीज़ का पहला हिस्सा है. पहला भाग लोड होने की परफ़ॉर्मेंस पर फ़ोकस करता है और दूसरा भाग रनटाइम की परफ़ॉर्मेंस पर फ़ोकस करता है.

हालातों को बरकरार रखना

किसी असल डिवाइस पर, कॉन्टेंट लोड होने की परफ़ॉर्मेंस की जांच करना बहुत ज़रूरी है. अगर आपके पास कोई असली डिवाइस नहीं है, तो मेरा सुझाव है कि आप WebPageTest पर जाएं, खास तौर पर "आसान" सेटअप पर जाएं. WPT, एम्युलेट किए गए 3G कनेक्शन वाले असल डिवाइस पर लोडिंग टेस्ट करता है.

3G स्पीड मापने की अच्छी स्पीड है. भले ही, हो सकता है कि आप 4G, LTE या 5G का इस्तेमाल करना पसंद करें, लेकिन मोबाइल इंटरनेट की हकीकत इससे अलग है. यह मुमकिन है कि आप किसी ट्रेन में, किसी कॉन्फ़्रेंस में, किसी कॉन्सर्ट में या किसी फ़्लाइट में हों. वहां पर आपको जो अनुभव होगा वह 3G के करीब होने की संभावना है, और कभी-कभी तो और भी खराब हो जाता है.

यह कहा जाता है कि हम इस लेख में 2G पर ध्यान देने जा रहे हैं, क्योंकि PROXX साफ़ तौर पर फ़ीचर फ़ोन और अपनी टारगेट ऑडियंस के उभरते बाज़ारों को टारगेट कर रहा है. WebPageTest का टेस्ट पूरा हो जाने पर, आपको एक वॉटरफ़ॉल (DevTools में दिखने वाले वॉटरफ़ॉल जैसा) के साथ-साथ सबसे ऊपर एक फ़िल्मस्ट्रिप दिखेगी. फ़िल्म स्ट्रिप से पता चलता है कि ऐप्लिकेशन लोड होने के दौरान, उपयोगकर्ता को क्या दिखता है. 2G पर, PROXX के ऑप्टिमाइज़ न किए गए वर्शन का लोड होने का अनुभव बहुत खराब है:

फ़िल्मस्ट्रिप वीडियो यह दिखाता है कि जब PROXX किसी एम्युलेट किए गए 2G कनेक्शन पर किसी असली और कम कीमत वाले डिवाइस पर लोड होता है, तो उपयोगकर्ता को क्या दिखता है.

3G पर लोड होने पर, उपयोगकर्ता को 4 सेकंड का व्हाइट कुछ दिखाई नहीं देता. 2G सेवा से ज़्यादा होने पर, उपयोगकर्ता को 8 सेकंड से ज़्यादा समय तक कुछ भी नहीं दिखता. अगर आपने परफ़ॉर्मेंस क्यों मायने रखती है लेख पढ़ें, तो आपको पता चल जाएगा कि बेसब्री से इंतज़ार करने की वजह से, हमारे संभावित उपयोगकर्ताओं का बड़ा हिस्सा हमारे पास नहीं है. स्क्रीन पर कुछ भी दिखाने के लिए, उपयोगकर्ता को 62 केबी का पूरा JavaScript डाउनलोड करना होगा. इस मामले में सबसे ज़रूरी बात यह है कि स्क्रीन पर जो कुछ भी दिखता है वह इंटरैक्टिव भी होता है. या फिर ऐसा होना चाहिए?

PROXX के ऑप्टिमाइज़ नहीं किए गए वर्शन में [फ़र्स्ट मीनिंगफ़ुल पेंट][एफ़एमपी] _तकनीकी रूप से_ [इंटरैक्टिव][टीटीआई] है, लेकिन उपयोगकर्ता के लिए किसी काम का नहीं है.

gzip'd JS के करीब 62 केबी डाउनलोड होने और डीओएम जनरेट होने के बाद, उपयोगकर्ता को हमारा ऐप्लिकेशन देखने को मिलता है. यह ऐप्लिकेशन तकनीकी रूप से इंटरैक्टिव है. हालांकि, इस तस्वीर को देखने पर एक अलग एहसास होता है. वेब फ़ॉन्ट अब भी बैकग्राउंड में लोड हो रहे हैं. साथ ही, जब तक वे तैयार नहीं होते, तब तक उपयोगकर्ता को कोई टेक्स्ट नहीं दिखता. इस स्टेटस को फ़र्स्ट मीनिंगफ़ुल पेंट (एफ़एमपी) के तौर पर मंज़ूरी मिली है, लेकिन यह इंटरैक्टिव नहीं है. इसकी वजह यह है कि लोगों को यह पता नहीं चलता कि कोई इनपुट किस बारे में है. ऐप्लिकेशन पूरी तरह से काम करने के लिए तैयार होने तक, 3G नेटवर्क पर एक सेकंड और 2G नेटवर्क पर तीन सेकंड लगते हैं. कुल मिलाकर, 3G नेटवर्क पर ऐप्लिकेशन को इंटरैक्टिव होने में 6 सेकंड और 2G पर 11 सेकंड लगते हैं.

वॉटरफ़ॉल ऐनलिसिस

अब जब हम जानते हैं कि उपयोगकर्ता क्या देखता है, तो हमें क्यों पता लगाना होगा. इसके लिए, हम वॉटरफ़ॉल को देखकर यह विश्लेषण कर सकते हैं कि संसाधन बहुत देरी से क्यों लोड हो रहे हैं. PROXX के लिए हमारे 2G ट्रेस में हमें दो मुख्य लाल फ़्लैग दिखते हैं:

  1. इसमें कई रंगों वाली कई पतली लाइनें होती हैं.
  2. JavaScript फ़ाइलों की मदद से एक चेन बनती है. उदाहरण के लिए, दूसरा संसाधन, पहला संसाधन खत्म होने के बाद ही लोड होता है और तीसरा संसाधन सिर्फ़ तब शुरू होता है, जब दूसरा संसाधन पूरा हो जाता है.
वॉटरफ़ॉल से यह अहम जानकारी मिलती है कि कौनसे संसाधन कब लोड हो रहे हैं और उनमें कितना समय लग रहा है.

कनेक्शन की संख्या कम करना

हर थिन लाइन (dns, connect, ssl) का मतलब है कि एक नया एचटीटीपी कनेक्शन बनता है. नया कनेक्शन सेट अप करने में बहुत खर्च आता है, क्योंकि 3G पर यह करीब 1 सेकंड और 2G पर करीब 2.5 सेकंड लगता है. अपने वॉटरफ़ॉल में, हमें इसके लिए एक नया कनेक्शन दिखता है:

  • अनुरोध #1: हमारा index.html
  • अनुरोध #5: fonts.googleapis.com की फ़ॉन्ट स्टाइल
  • अनुरोध #8: Google Analytics
  • अनुरोध #9: fonts.gstatic.com से एक फ़ॉन्ट फ़ाइल
  • अनुरोध #14: वेब ऐप्लिकेशन मेनिफ़ेस्ट

index.html का नया कनेक्शन इस्तेमाल नहीं किया जा सकता. कॉन्टेंट पाने के लिए, ब्राउज़र को हमारे सर्वर से कनेक्ट करना होगा. Google Analytics के लिए नए कनेक्शन को कम से कम Analytics जैसी इनलाइनिंग से रोका जा सकता है, लेकिन Google Analytics हमारे ऐप्लिकेशन को रेंडर या इंटरैक्टिव होने से नहीं रोक रहा है. इसलिए, हमें इस बात की परवाह नहीं है कि यह कितनी तेज़ी से लोड होता है. आम तौर पर, Google Analytics को ऐसे समय में लोड किया जाना चाहिए जब बाकी सभी चीज़ें पहले से लोड हो चुकी हों. इस तरह यह शुरुआती लोड के दौरान बैंडविड्थ या प्रोसेसिंग पावर का इस्तेमाल नहीं करता. वेब ऐप्लिकेशन मेनिफ़ेस्ट के लिए नया कनेक्शन, डेटा फ़ेच करने की खास जानकारी में बताया गया है, क्योंकि मेनिफ़ेस्ट को बिना क्रेडेंशियल वाले कनेक्शन पर लोड करना होगा. ध्यान दें, वेब ऐप्लिकेशन मेनिफ़ेस्ट हमारे ऐप्लिकेशन को रेंडर होने या इंटरैक्टिव होने से नहीं रोकता है, इसलिए हमें इस पर ध्यान देने की ज़रूरत नहीं है.

हालांकि, दो फ़ॉन्ट और उनकी स्टाइल एक समस्या है, क्योंकि वे रेंडरिंग और इंटरैक्टिविटी को भी ब्लॉक करते हैं. अगर हम fonts.googleapis.com से डिलीवर की गई सीएसएस देखें, तो इसके लिए बस दो @font-face नियम हैं. हर फ़ॉन्ट के लिए एक नियम है. फ़ॉन्ट की स्टाइल इतनी छोटी हैं कि हमने एक ग़ैर-ज़रूरी कनेक्शन को हटाकर, इसे अपने एचटीएमएल में इनलाइन करने का फ़ैसला लिया. फ़ॉन्ट फ़ाइलों के कनेक्शन सेटअप के खर्च से बचने के लिए, हम उन्हें अपने सर्वर पर कॉपी कर सकते हैं.

लोड को साथ-साथ लोड करना

वॉटरफ़ॉल को देखकर पता चलता है कि पहली JavaScript फ़ाइल लोड होने के बाद, नई फ़ाइलें तुरंत लोड होना शुरू हो जाती हैं. मॉड्यूल डिपेंडेंसी के लिए आम तौर पर ऐसा होता है. शायद हमारे मुख्य मॉड्यूल में स्टैटिक इंपोर्ट होते हैं, इसलिए इन इंपोर्ट के लोड होने तक JavaScript नहीं चल सकता. यहां इस बात का ध्यान रखना ज़रूरी है कि इस तरह की डिपेंडेंसी, बिल्ड टाइम के दौरान पता चलती हैं. हम <link rel="preload"> टैग का इस्तेमाल करके यह पक्का कर सकते हैं कि एचटीएमएल मिलने के बाद से सभी डिपेंडेंसी लोड हो जाएंगी.

नतीजे

आइए देखते हैं कि हमारे बदलावों से क्या नतीजे मिले. यह ज़रूरी है कि हमारे टेस्ट सेटअप में ऐसा कोई भी वैरिएबल न बदला जाए जिससे नतीजों पर असर पड़ सकता हो. इसलिए, हम इस लेख के बाकी हिस्से में WebPageTest के आसान सेटअप का इस्तेमाल करेंगे और फ़िल्मस्ट्रिप देखेंगे:

हम WebPageTest की फ़िल्मस्ट्रिप का इस्तेमाल करके यह देखते हैं कि हमारे बदलावों से क्या हुआ.

इन बदलावों से हमारे TTI को 11 से कम करके 8.5 कर दिया गया, जो हमारे द्वारा निकाले जाने वाले कनेक्शन सेटअप समय का लगभग 2.5 सेकंड है. बहुत अच्छे.

प्रीरेंडरिंग

हमने अपने TTI को कम किया है. हालांकि, इससे उस लंबे सफ़ेद स्क्रीन पर कोई असर नहीं पड़ा है जिसे लोगों को 8.5 सेकंड तक सहना पड़ता है. आम तौर पर, एफ़एमपी में सबसे बड़े सुधार अपने index.html में अलग-अलग स्टाइल में मार्कअप करके किए जा सकते हैं. इसे पाने की सामान्य तकनीकें, प्रीरेंडरिंग और सर्वर-साइड रेंडरिंग हैं. ये एक-दूसरे से काफ़ी हद तक संबंधित हैं. इनके बारे में वेब पर रेंडरिंग में बताया गया है. दोनों तकनीकें, वेब ऐप्लिकेशन को नोड में चलाती हैं और नतीजे के तौर पर मिलने वाले DOM को एचटीएमएल में बनाती हैं. सर्वर-साइड रेंडरिंग में ऐसा हर अनुरोध के लिए, सर्वर साइड पर होता है. वहीं, प्रीरेंडरिंग के दौरान ऐसा किया जाता है और यह आउटपुट को आपके नए index.html के तौर पर सेव करती है. PROXX एक JAMStack ऐप्लिकेशन है और इसका कोई सर्वर साइड नहीं है. इसलिए, हमने प्रीरेंडरिंग को लागू करने का फ़ैसला लिया है.

प्रीरेंडरर को लागू करने के कई तरीके हैं. PROXX में हमने Puppeteer का इस्तेमाल करने का विकल्प चुना है. यह Chrome को बिना किसी यूज़र इंटरफ़ेस (यूआई) के शुरू करता है. साथ ही, आपको Node API की मदद से उस इंस्टेंस को रिमोट तौर पर कंट्रोल करने की अनुमति देता है. हम इसका इस्तेमाल अपने मार्कअप और JavaScript को इंजेक्ट करने के लिए करते हैं. इसके बाद, हम डीओएम को एचटीएमएल की स्ट्रिंग के रूप में पढ़ते हैं. हम CSS मॉड्यूल का इस्तेमाल कर रहे हैं. इसलिए, हमें उन स्टाइल के लिए सीएसएस इनलाइनिंग मिलती है जो हमें बिना किसी शुल्क के चाहिए.

  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setContent(rawIndexHTML);
  await page.evaluate(codeToRun);
  const renderedHTML = await page.content();
  browser.close();
  await writeFile("index.html", renderedHTML);

इसके बाद, हम एफ़एमपी में सुधार की उम्मीद कर सकते हैं. हमें अब भी पहले की तरह ही JavaScript को लोड और लागू करना होगा. इसलिए, हमें TTI की मदद से टीटीआई में बहुत ज़्यादा बदलाव नहीं आना चाहिए. अगर कुछ भी होता है, तो हमारा index.html काफ़ी बड़ा हो गया है और हमें TTI को दूर करना पड़ सकता है. इसका सिर्फ़ एक ही तरीका है: WebPageTest चलाना.

फ़िल्मस्ट्रिप से पता चलता है कि एफ़एमपी मेट्रिक में साफ़ तौर पर सुधार हुआ है. टीटीआई पर ज़्यादातर असर नहीं पड़ता.

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

इनलाइन करना

DevTools और WebPageTest, दोनों की एक अन्य मेट्रिक है. यह टाइम टू फ़र्स्ट बाइट (टीटीएफ़बी) है. यह अनुरोध के पहले बाइट से मिलने वाले रिस्पॉन्स के पहले बाइट को भेजने में लगने वाला समय होता है. इस समय को अक्सर दोतरफ़ा यात्रा का समय (आरटीटी) भी कहा जाता है. हालांकि, तकनीकी रूप से इन दोनों नंबरों में अंतर होता है: आरटीटी में सर्वर साइड पर अनुरोध प्रोसेस होने में लगने वाला समय शामिल नहीं होता. DevTools और WebPageTest, अनुरोध/रिस्पॉन्स ब्लॉक में हल्के रंग से TTFB को विज़ुअलाइज़ करते हैं.

अनुरोध के लाइट सेक्शन से पता चलता है कि अनुरोध, रिस्पॉन्स की पहली बाइट पाने के लिए इंतज़ार कर रहा है.

अपने वॉटरफ़ॉल में देखा जा सकता है कि सभी अनुरोध, जवाब के पहले बाइट के इंतज़ार में ज़्यादातर समय बिताते हैं.

एचटीटीपी/2 पुश के पीछे यही समस्या थी. ऐप्लिकेशन डेवलपर यह जानता है कि कुछ संसाधनों की ज़रूरत है और वह उन्हें तार के नीचे पुश कर सकता है. जब तक क्लाइंट को लगता है कि उसे ज़्यादा संसाधन पाने की ज़रूरत है, तब तक वे पहले से ही ब्राउज़र की कैश मेमोरी में मौजूद होते हैं. एचटीटीपी/2 पुश की वजह से सही जवाब पाना बहुत मुश्किल होता है और इसे गलत माना जाता है. एचटीटीपी/3 के स्टैंडर्ड तय करने के दौरान, इस समस्या वाले स्पेस का फिर से इस्तेमाल किया जाएगा. फ़िलहाल, सभी ज़रूरी संसाधनों को इनलाइन करना सबसे आसान है. हालांकि, कैश मेमोरी में डेटा सेव करने की क्षमता को नुकसान पहुंच सकता है.

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

JavaScript में इनलाइनिंग की मदद से, हमने TTI को 8.5 से घटाकर 7.2 कर दिया है.

इसने हमारे टीटीआई को एक सेकंड का झटका दिया. अब हम उस मकाम पर पहुंच गए हैं जहां हमारे index.html में वे सारी चीज़ें मौजूद हैं जो शुरुआती रेंडर और इंटरैक्टिव होने के लिए ज़रूरी हैं. एचटीएमएल के डाउनलोड होने के दौरान भी, एचटीएमएल रेंडर हो सकता है और इससे हमारा एफ़एमपी बन सकता है. जैसे ही एचटीएमएल को पार्स और एक्ज़ीक्यूट किया जाता है, वैसे ही ऐप्लिकेशन इंटरैक्टिव हो जाता है.

कोड को तेज़ी से बांटना

हां, हमारे index.html में वह सब कुछ है जो इंटरैक्टिव होने के लिए ज़रूरी है. हालांकि, ध्यान से देखने पर पता चला है कि इसमें बाकी सब कुछ है. हमारी index.html का साइज़ करीब 43 केबी है. इस आधार पर समझें कि उपयोगकर्ता शुरुआत में किस चीज़ के साथ इंटरैक्ट कर सकता है: हमारे पास गेम को कॉन्फ़िगर करने का एक फ़ॉर्म है. इसमें कुछ कॉम्पोनेंट, एक स्टार्ट बटन, और उपयोगकर्ता सेटिंग को बनाए रखने और लोड करने के लिए शायद कुछ कोड शामिल होते हैं. बस इतना ही. तो 43 KB ही काफ़ी होता है.

PROXX का लैंडिंग पेज. यहां सिर्फ़ ज़रूरी कॉम्पोनेंट इस्तेमाल किए जाते हैं.

यह समझने के लिए कि हमारे बंडल का साइज़ कहां से आ रहा है, हम सोर्स मैप एक्सप्लोरर या इससे मिलते-जुलते टूल का इस्तेमाल करके, बंडल में मौजूद चीज़ों का पता लगा सकते हैं. आपके हिसाब से, हमारे बंडल में गेम लॉजिक, रेंडरिंग इंजन, विन स्क्रीन, खोए हुए डिवाइस की स्क्रीन, और कई सुविधाएं शामिल हैं. लैंडिंग पेज के लिए इन मॉड्यूल के सिर्फ़ एक छोटे सबसेट की ज़रूरत होती है. इंटरैक्टिविटी के लिए जिन चीज़ों की ज़रूरत नहीं होती है उन्हें लेज़ी तरीके से लोड होने वाले मॉड्यूल में ले जाने पर, टीटीआई को बहुत ज़्यादा कम कर दिया जाता है.

PROXX के `index.html` के कॉन्टेंट का विश्लेषण करने से कई ऐसे संसाधन दिखते हैं जिनकी ज़रूरत नहीं होती. ज़रूरी संसाधन हाइलाइट किए जाते हैं.

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

PROXX में हमने एक lazy.js फ़ाइल बनाई है, जो स्टैटिक तौर पर उन सभी चीज़ों को इंपोर्ट करती है जिनकी हमें ज़रूरत नहीं है. इसके बाद, अपनी मुख्य फ़ाइल में हम lazy.js को डाइनैमिक तरीके से इंपोर्ट कर सकते हैं. हालांकि, Preact के कुछ कॉम्पोनेंट lazy.js में मिल गए थे. इससे काफ़ी मुश्किल हो गई थी, क्योंकि Preact आसानी से लोड होने वाले कॉम्पोनेंट को हैंडल नहीं कर पाएगी. इस वजह से हमने एक छोटा deferred कॉम्पोनेंट रैपर लिखा है, जो हमें असल कॉम्पोनेंट के लोड होने तक प्लेसहोल्डर रेंडर करने की अनुमति देता है.

export default function deferred(componentPromise) {
  return class Deferred extends Component {
    constructor(props) {
      super(props);
      this.state = {
        LoadedComponent: undefined
      };
      componentPromise.then(component => {
        this.setState({ LoadedComponent: component });
      });
    }

    render({ loaded, loading }, { LoadedComponent }) {
      if (LoadedComponent) {
        return loaded(LoadedComponent);
      }
      return loading();
    }
  };
}

इसके साथ, हम अपने render() फ़ंक्शन में कॉम्पोनेंट के प्रॉमिस का इस्तेमाल कर सकते हैं. उदाहरण के लिए, कॉम्पोनेंट लोड होने के दौरान, <Nebula> कॉम्पोनेंट, ऐनिमेशन वाले बैकग्राउंड की इमेज को रेंडर करता है. इसे खाली <div> से बदल दिया जाएगा. कॉम्पोनेंट लोड होने और इस्तेमाल के लिए तैयार होने के बाद, <div> को असल कॉम्पोनेंट से बदल दिया जाएगा.

const NebulaDeferred = deferred(
  import("/components/nebula").then(m => m.default)
);

return (
  // ...
  <NebulaDeferred
    loading={() => <div />}
    loaded={Nebula => <Nebula />}
  />
);

इन सभी चीज़ों को ध्यान में रखते हुए, हमने अपने index.html को घटाकर सिर्फ़ 20 केबी कर दिया, जो मूल साइज़ के आधे से कम है. एफ़एमपी और टीटीआई पर इसका क्या असर होता है? WebPageTest से आपको जानकारी मिलेगी!

फ़िल्मस्ट्रिप से पता चलता है: हमारे टीटीआई का समय 5.4 सेकंड है. 11वीं सदी के हमारे बेहतरीन वीडियो से मिला है एक शानदार सुधार.

हमारे FMP और TTI की दूरी सिर्फ़ 100 मि॰से॰ है, क्योंकि यह सिर्फ़ इनलाइन JavaScript को पार्स और लागू करने का काम है. 2G पर सिर्फ़ 5.4 सेकंड के बाद, यह ऐप्लिकेशन पूरी तरह से इंटरैक्टिव हो गया है. बाकी सभी, कम ज़रूरी मॉड्यूल बैकग्राउंड में लोड होते हैं.

बेहतर तरीके से मैनेज करें

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

नतीजा

मापना ज़रूरी है. ऐसी समस्याओं पर समय बर्बाद करने से बचने के लिए जो असली नहीं हैं, हमारा सुझाव है कि ऑप्टिमाइज़ेशन को लागू करने से पहले, हमेशा उन समस्याओं को मेज़र करें. इसके अलावा, मेज़रमेंट 3G कनेक्शन वाले असल डिवाइसों पर किया जाना चाहिए. इसके अलावा, अगर आपके पास कोई असली डिवाइस नहीं है, तो WebPageTest पर भी मेज़रमेंट किया जाना चाहिए.

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

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

दूसरा भाग देखने के लिए हमारे साथ बने रहें. इसमें हम हाइपर-कंज़्ड डिवाइसों पर रनटाइम की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के तरीके के बारे में बात करेंगे.