आधुनिक वेब ब्राउज़र के बारे में जानकारी (भाग 3)

मैरिको कोसाका

रेंडरर प्रोसेस के अंदरूनी काम

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

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

रेंडर करने वाली प्रोसेस, वेब कॉन्टेंट को मैनेज करती है

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

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

रेंडर करने की प्रक्रिया
इमेज 1: रेंडरर की प्रोसेस, जिसमें मुख्य थ्रेड, वर्कर थ्रेड, कंपोज़िटर थ्रेड, और रास्टर थ्रेड शामिल है

पार्स करना

डीओएम बनाना

जब रेंडरर प्रोसेस को नेविगेशन के लिए एक तय किया गया मैसेज मिलता है और उसे एचटीएमएल डेटा मिलता है, तो मुख्य थ्रेड, टेक्स्ट स्ट्रिंग (एचटीएमएल) को पार्स करना शुरू कर देता है और उसे डो फ़ंक्शन bजेक्ट मॉडल (DOM) में बदल देता है.

DOM, पेज को ब्राउज़र में दिखाता है. साथ ही, यह डेटा स्ट्रक्चर और एपीआई को भी दिखाता है, जिससे वेब डेवलपर JavaScript की मदद से इंटरैक्ट कर सकता है.

एचटीएमएल दस्तावेज़ को डीओएम में पार्स करना, एचटीएमएल स्टैंडर्ड से तय होता है. आपने देखा होगा कि किसी ब्राउज़र में एचटीएमएल फ़ीड करने से कभी भी गड़बड़ी नहीं होती. उदाहरण के लिए, बंद होने वाला </p> टैग एक मान्य एचटीएमएल है. Hi! <b>I'm <i>Chrome</b>!</i> जैसे गलत मार्कअप को (i टैग से पहले b टैग बंद किया जाता है) ऐसे मार्कअप को माना जाता है जैसे आपने Hi! <b>I'm <i>Chrome</i></b><i>!</i> लिखा है. ऐसा इसलिए होता है, क्योंकि एचटीएमएल स्पेसिफ़िकेशन को इस तरह डिज़ाइन किया जाता है कि वे गड़बड़ियों को अच्छी तरह से हैंडल कर सकें. अगर आपको यह जानना है कि ये चीज़ें कैसे की जाती हैं, तो एचटीएमएल स्पेसिफ़िकेशन के "पार्सर में गड़बड़ी को ठीक करने और उसमें अजीब मामलों के बारे में जानकारी" सेक्शन में पढ़ा जा सकता है.

सबरिसॉर्स लोड हो रहे हैं

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

डीओएम
इमेज 2: एचटीएमएल को पार्स करने और डीओएम ट्री बनाने वाला मुख्य थ्रेड

JavaScript, पार्स करने की प्रोसेस को ब्लॉक कर सकता है

जब एचटीएमएल पार्सर को <script> टैग मिलता है, तो यह एचटीएमएल दस्तावेज़ की पार्सिंग को रोक देता है. साथ ही, इसके लिए JavaScript कोड को लोड, पार्स, और एक्ज़ीक्यूट करना पड़ता है. क्यों? JavaScript, document.write() जैसी चीज़ों का इस्तेमाल करके दस्तावेज़ का आकार बदल सकता है, जिससे पूरे डीओएम स्ट्रक्चर में बदलाव होता है (एचटीएमएल स्पेसिफ़िकेशन में पार्स करने के मॉडल की खास जानकारी का डायग्राम अच्छा है). इसलिए पहले एचटीएमएल पार्सर को JavaScript चलाने के लिए इंतज़ार करना पड़ता है, ताकि वह एचटीएमएल दस्तावेज़ को पार्स करना फिर से शुरू कर सके. अगर आपको जानना है कि JavaScript को लागू करने पर क्या होता है, तो इस बारे में V8 टीम ने बातचीत की है और ब्लॉग पोस्ट किए हैं.

ब्राउज़र को संकेत दें कि आपको संसाधनों को किस तरह लोड करना है

वेब डेवलपर कई तरीकों से ब्राउज़र को संकेत भेज सकते हैं, ताकि संसाधनों को सही तरीके से लोड किया जा सके. अगर आपके JavaScript में document.write() का इस्तेमाल नहीं किया गया है, तो <script> टैग में async या defer एट्रिब्यूट जोड़ें. इसके बाद, ब्राउज़र JavaScript कोड को एसिंक्रोनस तरीके से लोड करता है और चलाता है. साथ ही, पार्स करने की प्रोसेस को ब्लॉक नहीं करता. अगर JavaScript मॉड्यूल सही है, तो इसका भी इस्तेमाल किया जा सकता है. <link rel="preload">, ब्राउज़र को यह बताने का एक तरीका है कि मौजूदा नेविगेशन के लिए संसाधन की ज़रूरत है और आपको जल्द से जल्द इसे डाउनलोड करना है. इस बारे में ज़्यादा जानकारी के लिए, संसाधन की प्राथमिकता तय करना – मदद पाने के लिए ब्राउज़र इंस्टॉल करना लेख पढ़ें.

स्टाइल कैलकुलेशन

पेज कैसा दिखेगा, यह जानने के लिए DOM का इस्तेमाल करना काफ़ी नहीं है. ऐसा इसलिए, क्योंकि हम सीएसएस में पेज एलिमेंट की स्टाइल बदल सकते हैं. मुख्य थ्रेड, सीएसएस को पार्स करता है और हर डीओएम नोड के लिए कंप्यूट की गई स्टाइल तय करता है. इससे यह जानकारी मिलती है कि सीएसएस सिलेक्टर के आधार पर, हर एलिमेंट पर किस तरह की स्टाइल लागू की जाती है. DevTools के computed सेक्शन में यह जानकारी देखी जा सकती है.

कंप्यूटेड स्टाइल
इमेज 3: कंप्यूट की गई स्टाइल को जोड़ने के लिए, सीएसएस को पार्स करने वाला मुख्य थ्रेड

भले ही, आपने कोई सीएसएस न दी हो, लेकिन हर डीओएम नोड में कंप्यूट किया गया स्टाइल होता है. <h1> टैग, <h2> टैग से बड़ा दिखता है और हर एलिमेंट के लिए मार्जिन तय किए जाते हैं. ऐसा इसलिए है, क्योंकि ब्राउज़र की एक डिफ़ॉल्ट स्टाइल शीट होती है. अगर आपको जानना है कि Chrome की डिफ़ॉल्ट सीएसएस कैसी है, तो सोर्स कोड यहां देखें.

लेआउट

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

लोगों की फ़ैक्स मशीन का गेम
इमेज 4: पेंटिंग के सामने खड़ा एक व्यक्ति, दूसरे व्यक्ति से जुड़ी फ़ोन लाइन

लेआउट, एलिमेंट की ज्यामिति ढूंढने की प्रोसेस है. मुख्य थ्रेड, डीओएम और कंप्यूट किए गए स्टाइल को फ़ॉलो करता है और लेआउट ट्री बनाता है. इसमें x y कोऑर्डिनेट और बाउंडिंग बॉक्स के साइज़ जैसी जानकारी होती है. लेआउट ट्री की बनावट डीओएम ट्री जैसी हो सकती है. हालांकि, इसमें सिर्फ़ पेज पर दिखने वाली जानकारी से जुड़ी जानकारी होती है. अगर display: none लागू किया गया है, तो वह एलिमेंट लेआउट ट्री का हिस्सा नहीं है. हालांकि, visibility: hidden वाला एलिमेंट, लेआउट ट्री में शामिल है. इसी तरह, अगर p::before{content:"Hi!"} जैसे कॉन्टेंट वाली सूडो क्लास लागू की जाती है, तो उसे लेआउट ट्री में शामिल किया जाता है. भले ही, वह DOM में न हो.

लेआउट
इमेज 5: कंप्यूट किए गए स्टाइल और लेआउट ट्री के साथ डीओएम ट्री के ऊपर जा रहा मुख्य थ्रेड
इमेज 6: लाइन ब्रेक में बदलाव की वजह से मूव करने वाले पैराग्राफ़ के लिए बॉक्स लेआउट

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

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

पेंट

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

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

उदाहरण के लिए, हो सकता है कि कुछ एलिमेंट के लिए z-index को सेट किया गया हो. ऐसे में, एचटीएमएल में लिखे गए एलिमेंट के मुताबिक पेंटिंग बनाने से गलत रेंडरिंग होगी.

z-इंडेक्स पूरा नहीं हो पाया
इमेज 8: पेज के एलिमेंट, एचटीएमएल मार्कअप के हिसाब से दिख रहे हैं. इस वजह से, इमेज को गलत तरीके से रेंडर किया जा रहा है क्योंकि z-इंडेक्स को ध्यान में नहीं रखा गया था

पेंट किए गए इस चरण पर, मुख्य धागा लेआउट ट्री पर चलता है और पेंट रिकॉर्ड बनाता है. पेंट रिकॉर्ड, पेंटिंग प्रोसेस का एक नोट है, जैसे कि "बैकग्राउंड में सबसे पहले, फिर टेक्स्ट और फिर रेक्टैंगल". अगर आपने JavaScript का इस्तेमाल करके <canvas> एलिमेंट बनाया है, तो इस प्रोसेस के बारे में आपको जानकारी हो सकती है.

पेंट रिकॉर्ड
इमेज 9: लेआउट ट्री में चलता हुआ मुख्य धागा और पेंट के रिकॉर्ड बनाने के लिए,

रेंडरिंग पाइपलाइन को अपडेट करना महंगा है

इमेज 10: DOM+स्टाइल, लेआउट, और पेंट ट्री उसी क्रम में लगाएं जिस क्रम में इन्हें जनरेट किया गया है

रेंडरिंग पाइपलाइन को समझने वाली सबसे अहम बात यह है कि हर चरण में, पिछले ऑपरेशन के नतीजे का इस्तेमाल नया डेटा बनाने के लिए किया जाता है. उदाहरण के लिए, अगर लेआउट ट्री में कुछ बदलाव होता है, तो दस्तावेज़ के जिन हिस्सों पर असर पड़ा है उनके लिए पेंट ऑर्डर फिर से जनरेट करना होगा.

अगर एलिमेंट ऐनिमेट किए जा रहे हैं, तो ब्राउज़र को हर फ़्रेम के बीच में ये कार्रवाइयां करनी होंगी. हमारे ज़्यादातर डिसप्ले एक सेकंड में 60 बार (60 FPS) स्क्रीन को रीफ़्रेश करते हैं. हर फ़्रेम पर चीज़ों को स्क्रीन पर ले जाने पर ऐनिमेशन, इंसानों को ठीक से दिखाई देगा. हालांकि, अगर ऐनिमेशन में फ़्रेम के बीच में फ़्रेम छूट गए हैं, तो पेज "जैंकी" दिखेगा.

गायब फ़्रेम से जेज जैंक
इमेज 11: टाइमलाइन पर दिखने वाले ऐनिमेशन फ़्रेम

भले ही आपकी रेंडरिंग कार्रवाइयां स्क्रीन रीफ़्रेश के साथ ठीक से काम कर रही हों, लेकिन ये कैलकुलेशन मुख्य थ्रेड पर चल रहे हैं. इसका मतलब है कि आपके ऐप्लिकेशन पर JavaScript चलाने पर, इसे ब्लॉक किया जा सकता है.

JavaScript से जैज जैंक
इमेज 12: टाइमलाइन पर ऐनिमेशन फ़्रेम, लेकिन JavaScript का एक फ़्रेम ब्लॉक है

JavaScript की कार्रवाई को छोटे-छोटे हिस्सों में बांटा जा सकता है. साथ ही, requestAnimationFrame() का इस्तेमाल करके, हर फ़्रेम पर चलाने के लिए शेड्यूल किया जा सकता है. इस विषय के बारे में ज़्यादा जानने के लिए, कृपया JavaScript को ऑप्टिमाइज़ करना लेख पढ़ें. मुख्य थ्रेड को ब्लॉक होने से बचाने के लिए, वेब वर्कर में JavaScript भी चलाई जा सकती है.

ऐनिमेशन फ़्रेम का अनुरोध करें
इमेज 13: ऐनिमेशन फ़्रेम के साथ टाइमलाइन पर चलने वाले JavaScript के छोटे-छोटे हिस्से

कंपोज़िटिंग

आप कोई पेज कैसे बनाएंगे?

इमेज 14: सामान्य रास्टरिंग प्रोसेस का ऐनिमेशन

अब ब्राउज़र को दस्तावेज़ के स्ट्रक्चर, हर एलिमेंट की स्टाइल, पेज की ज्यामिति, और पेंट ऑर्डर के बारे में पता चल गया है. ऐसे में, वह पेज कैसे बनाता है? स्क्रीन पर इस जानकारी को पिक्सल में बदलने को रास्टराइज़िंग कहते हैं.

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

कंपोज़िटिंग क्या है

इमेज 15: कंपोज़िट करने की प्रोसेस का ऐनिमेशन

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

लेयर पैनल का इस्तेमाल करके देखा जा सकता है कि DevTools में आपकी वेबसाइट को लेयर में कैसे बांटा गया है.

लेयर में बांटना

यह पता करने के लिए कि कौनसे एलिमेंट को लेयर में शामिल करना चाहिए, लेयर ट्री बनाने के लिए मुख्य थ्रेड, लेआउट ट्री से गुज़रता है. इस हिस्से को DevTools परफ़ॉर्मेंस पैनल में "लेयर ट्री अपडेट करें" कहा जाता है. अगर पेज के कुछ हिस्सों (जैसे कि स्लाइड-इन साइड मेन्यू) में एक भी हिस्सा नहीं दिख रहा है, तो सीएसएस में will-change एट्रिब्यूट का इस्तेमाल करके ब्राउज़र को इस बारे में बताया जा सकता है.

लेयर ट्री
इमेज 16: लेआउट ट्री से गुज़रता हुआ मुख्य थ्रेड, जिससे लेयर ट्री बनता है

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

मुख्य थ्रेड का रास्टर और कंपोज़िट ऑफ़

लेयर ट्री बनने और पेंट ऑर्डर तय होने के बाद, मुख्य थ्रेड उस जानकारी को कंपोज़िटर थ्रेड को असाइन करता है. इसके बाद, कंपोज़िटर थ्रेड हर लेयर को रास्टराइज़ करता है. लेयर, पेज की पूरी लंबाई जैसी बड़ी हो सकती है. इसलिए, कंपोज़िटर थ्रेड उन्हें टाइल में बांट देता है और हर टाइल को रास्टर थ्रेड में भेज देता है. रास्टर थ्रेड, हर टाइल को रास्टराइज़ करते हैं और उन्हें जीपीयू मेमोरी में सेव करते हैं.

रास्टर
इमेज 17: रास्टर थ्रेड, टाइल का बिट मैप बनाते हैं और जीपीयू को भेजते हैं

कंपोज़िटर थ्रेड अलग-अलग रास्टर थ्रेड को प्राथमिकता दे सकता है, ताकि व्यूपोर्ट (या आस-पास) में मौजूद चीज़ों को पहले रास्टर किया जा सके. किसी लेयर में अलग-अलग रिज़ॉल्यूशन के लिए कई टाइल भी होती हैं, ताकि ज़ूम-इन ऐक्शन जैसी चीज़ों को मैनेज किया जा सके.

टाइल के रास्टर हो जाने के बाद, कंपोज़िटर थ्रेड एक कंपोज़िटर फ़्रेम बनाने के लिए, ड्रॉ क्वाड नाम की टाइल की जानकारी इकट्ठा करता है.

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

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

कंपोज़िट
इमेज 18: कंपोज़िटिंग फ़्रेम बनाने वाला कंपोज़िटर थ्रेड. फ़्रेम को ब्राउज़र प्रोसेस में उसके बाद जीपीयू में भेजा जाता है

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

रैप अप करें

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

इस सीरीज़ की अगली और आखिरी पोस्ट में, हम कंपोज़िटर थ्रेड के बारे में ज़्यादा जानकारी देंगे. साथ ही, देखेंगे कि mouse move और click जैसे उपयोगकर्ता का इनपुट आने पर क्या होता है.

क्या आपको यह पोस्ट पसंद आई? अगर आने वाले समय में किसी पोस्ट के बारे में आपका कोई सवाल है या सुझाव है, तो हमें नीचे दिए गए टिप्पणी वाले सेक्शन में या Twitter पर @kosamari से जवाब देने में खुशी होगी.

अगला: इनपुट, कंपोज़िटर पर आ रहा है