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

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

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

खास जानकारी

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

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

<!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 की मदद से, डीओएम में जाकर छिपे हुए स्पैन नोड का रेफ़रंस पाया जा सकता है. हो सकता है कि नोड, रेंडर ट्री में न दिखे, लेकिन वह डीओएम में मौजूद होता है. इसके बाद, जब हमारे पास रेफ़रंस हो, तो हम .textContent के ज़रिए उसका टेक्स्ट बदल सकते हैं. इसके अलावा, उसकी कैलकुलेट की गई डिसप्ले स्टाइल प्रॉपर्टी को "none" से "inline" पर भी बदला जा सकता है. अब हमारे पेज पर "नमस्ते इंटरैक्टिव छात्र-छात्राएं!" दिखता है.

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

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

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

हालांकि, JavaScript हमें कई सुविधाएं देता है, लेकिन इससे पेज को रेंडर करने के तरीके और समय पर कई और सीमाएं आती हैं.

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

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

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

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

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

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

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

पार्स करने वाले को ब्लॉक करना बनाम असाइनोक्रोनस JavaScript

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

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

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

इसे आज़माएँ

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

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