JavaScript के साथ इंटरैक्टिविटी जोड़ना

पब्लिश करने की तारीख: 31 दिसंबर, 2013

JavaScript की मदद से हम पेज के हर पहलू में बदलाव कर सकते हैं: कॉन्टेंट, स्टाइलिंग और उपयोगकर्ता इंटरैक्शन पर इसके रिस्पॉन्स के बारे में भी बताया गया है. हालाँकि, JavaScript यह काम भी कर सकता है डीओएम कंस्ट्रक्शन को ब्लॉक करें और पेज रेंडर होने में देरी करें. बेहतर परफ़ॉर्मेंस देने के लिए, अपने JavaScript को एसिंक्रोनस बनाएं और रेंडरिंग के अहम पाथ से ग़ैर-ज़रूरी JavaScript को हटाएं.

खास जानकारी

  • JavaScript, DOM और CSSOM पर क्वेरी कर सकता है और उनमें बदलाव कर सकता है.
  • CSSOM पर JavaScript को चलाने से जुड़ी समस्याएं.
  • JavaScript, DOM के निर्माण को तब तक ब्लॉक करता है, जब तक कि साफ़ तौर पर एस्किन के तौर पर एलान न किया जाए.

JavaScript एक डाइनैमिक भाषा है, जो ब्राउज़र में चलती है और हमें पेज के काम करने के हर पहलू में बदलाव करने की सुविधा देती है: हम डीओएम ट्री में एलिमेंट जोड़कर और हटाकर कॉन्टेंट में बदलाव कर सकते हैं; हम हर एलिमेंट की CSSOM प्रॉपर्टी में बदलाव कर सकते हैं; हम उपयोगकर्ता के इनपुट को हैंडल कर सकते हैं; और बहुत कुछ. इसे समझने के लिए, देखें कि पिछली "नमस्ते दुनिया" पर क्या होता है उदाहरण को छोटी इनलाइन स्क्रिप्ट जोड़ने के लिए बदल दिया गया है:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline'; // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
    </script>
  </body>
</html>

इसे आज़माएँ

  • JavaScript की मदद से, हम डीओएम तक पहुंच सकते हैं और छिपे हुए स्पैन नोड के रेफ़रंस को बाहर निकाल सकते हैं; ऐसा हो सकता है कि नोड, रेंडर ट्री में न दिखे, लेकिन DOM में अब भी मौजूद हो. फिर, जब हमारे पास संदर्भ होता है, तो हम उसके टेक्स्ट को (.textContent के ज़रिए) बदल सकते हैं और यहां तक कि इसकी परिकलित डिसप्ले स्टाइल प्रॉपर्टी को "कोई नहीं" से बदल भी सकते हैं से "इनलाइन" करने के लिए सेट करें. अब हमारे पेज पर "इंटरैक्टिव छात्र-छात्राओं को नमस्ते!" दिखेगा.

  • JavaScript की मदद से, डीओएम में नए एलिमेंट बनाए जा सकते हैं, उनकी स्टाइल तय की जा सकती है, उन्हें जोड़ा जा सकता है, और हटाया जा सकता है. तकनीकी तौर पर, हमारा पूरा पेज सिर्फ़ एक बड़ी JavaScript फ़ाइल हो सकती है, जो एलिमेंट को एक-एक करके बनाती है और उन्हें स्टाइल देती है. हालांकि यह काम करेगा, लेकिन असल में HTML और CSS का उपयोग करना ज़्यादा आसान है. अपने JavaScript फ़ंक्शन के दूसरे हिस्से में, हम एक नया div एलिमेंट बनाते हैं, उसका टेक्स्ट कॉन्टेंट सेट करते हैं, उसे स्टाइल देते हैं, और उसे बॉडी में जोड़ते हैं.

मोबाइल डिवाइस पर रेंडर किए गए पेज की झलक.

इसके बाद, हमने मौजूदा DOM नोड के कॉन्टेंट और सीएसएस स्टाइल में बदलाव किया. साथ ही, दस्तावेज़ में एक नया नोड जोड़ा. हमारा पृष्ठ कोई भी डिज़ाइन पुरस्कार नहीं जीतेगा, लेकिन यह JavaScript की क्षमता और क्षमता को दर्शाता है.

हालाँकि, JavaScript हमें काफ़ी क्षमता देता है, लेकिन यह पेज कैसे और कब रेंडर किया जाता है, इस पर कई अतिरिक्त सीमाएं लागू करता है.

सबसे पहले, ध्यान दें कि पिछले उदाहरण में बताया गया है कि हमारी इनलाइन स्क्रिप्ट, पेज के निचले हिस्से के पास है. क्यों? आपको खुद आज़माकर देखना चाहिए, लेकिन अगर हम स्क्रिप्ट को <span> एलिमेंट से ऊपर ले जाते हैं, तो आप देखेंगे कि स्क्रिप्ट काम नहीं कर रही है. साथ ही, यह शिकायत करती है कि उसे दस्तावेज़ के किसी <span> एलिमेंट का रेफ़रंस नहीं मिला; इसका मतलब है कि getElementsByTagName('span'), null दिखाता है. इससे एक अहम प्रॉपर्टी के बारे में पता चलता है: हमारी स्क्रिप्ट ठीक उसी समय एक्ज़ीक्यूट होती है जहां उसे दस्तावेज़ में डाला गया होता है. जब एचटीएमएल पार्सर को कोई स्क्रिप्ट टैग मिलता है, तो वह डीओएम को बनाने की अपनी प्रोसेस को रोक देता है और JavaScript इंजन को कंट्रोल देता है; जब JavaScript इंजन का काम पूरा हो जाता है, तो ब्राउज़र उसे वहीं से शुरू करता है जहां उसे छोड़ा गया था और DOM निर्माण को फिर से शुरू करता है.

दूसरे शब्दों में कहें, तो हमारे स्क्रिप्ट ब्लॉक को पेज पर बाद में कोई एलिमेंट नहीं मिलता, क्योंकि उन्हें अभी तक प्रोसेस नहीं किया गया है! इसे कुछ अलग तरीके से कहें: इनलाइन स्क्रिप्ट को लागू करने से, डीओएम का निर्माण रुक जाता है. इससे शुरुआती रेंडरिंग में भी देरी होती है.

हमारे पेज में स्क्रिप्ट जोड़ने की एक और खास बात यह है कि वे न सिर्फ़ DOM, बल्कि CSSOM प्रॉपर्टी को भी पढ़ सकती हैं और उनमें बदलाव कर सकती हैं. यहां तक कि हम अपने उदाहरण में भी यही कर रहे हैं. स्पैन एलिमेंट की डिसप्ले प्रॉपर्टी को 'कोई नहीं' से 'इनलाइन' में बदल देते हैं. आखिरी नतीजा? अब हमारे पास रेस कंडीशन है.

अगर स्क्रिप्ट चलाने के दौरान, ब्राउज़र ने CSSOM को डाउनलोड और बनाना पूरा नहीं किया है, तो क्या होगा? यह जवाब परफ़ॉर्मेंस के लिहाज़ से बहुत अच्छा नहीं है: ब्राउज़र, स्क्रिप्ट को एक्ज़ीक्यूट करने और डीओएम बनाने में तब तक देरी करता है, जब तक कि CSSOM डाउनलोड नहीं हो जाता.

कम शब्दों में, JavaScript, डीओएम, सीएसएसओएम, और JavaScript के बीच कई नई डिपेंडेंसी जोड़ता है. इससे ब्राउज़र को पेज को प्रोसेस करने और स्क्रीन पर रेंडर करने में काफ़ी देरी हो सकती है:

  • दस्तावेज़ में स्क्रिप्ट की जगह अहम होती है.
  • जब ब्राउज़र को कोई स्क्रिप्ट टैग मिलता है, तो DOM का निर्माण तब तक रुक जाता है, जब तक स्क्रिप्ट पूरी तरह से लागू नहीं हो जाती.
  • JavaScript, डीओएम और सीएसएसओएम से क्वेरी कर सकता है और उनमें बदलाव कर सकता है.
  • CSSOM तैयार होने तक, JavaScript का एक्ज़ीक्यूशन रोक दिया जाता है.

बहुत हद तक, "ज़रूरी रेंडरिंग पाथ को ऑप्टिमाइज़ करना" एचटीएमएल, सीएसएस, और JavaScript के बीच डिपेंडेंसी ग्राफ़ को समझना और उसे ऑप्टिमाइज़ करना.

पार्सर ब्लॉकिंग बनाम एसिंक्रोनस JavaScript

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

स्क्रिप्ट टैग का इस्तेमाल करके शामिल की गई स्क्रिप्ट के बारे में क्या? पिछले उदाहरण को देखें और कोड को एक अलग फ़ाइल में एक्सट्रैक्ट करें:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script External</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js"></script>
  </body>
</html>

app.js

var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

इसे आज़माएँ

क्या हम किसी <script> टैग या इनलाइन JavaScript स्निपेट को दोनों एक ही तरह से व्यवहार करने की उम्मीद करते हों. दोनों ही मामलों में, ब्राउज़र रुक जाता है और स्क्रिप्ट को लागू करता है, ताकि वह दस्तावेज़ के बाकी हिस्से को प्रोसेस कर सके. हालांकि, बाहरी JavaScript फ़ाइल के मामले में, ब्राउज़र को डिस्क, कैश मेमोरी या किसी रिमोट सर्वर से स्क्रिप्ट फ़ेच होने का इंतज़ार करने के लिए रोकना पड़ता है. इससे, क्रिटिकल रेंडरिंग पाथ में 10 से 1,000 मिलीसेकंड तक की देरी हो सकती है.

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

ऐसा करने के लिए, async एट्रिब्यूट को <script> एलिमेंट में जोड़ा जाता है:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script Async</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js" async></script>
  </body>
</html>

इसे आज़माएँ

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

सुझाव/राय दें या शिकायत करें