कंपोजिटर में इनपुट आ रहा है
यह Chrome के बारे में चार ब्लॉग पोस्ट की सीरीज़ का आखिरी लेख है. इसमें यह जांच की गई है कि Chrome, वेबसाइट दिखाने के लिए हमारे कोड को कैसे मैनेज करता है. पिछली पोस्ट में, हमने रेंडरिंग की प्रोसेस और कंपोजिटर के बारे में जाना था. इस पोस्ट में, हम यह देखेंगे कि उपयोगकर्ता के इनपुट आने पर, कंपोजिटर कैसे आसानी से इंटरैक्ट कर रहा है.
ब्राउज़र के नज़रिए से इनपुट इवेंट
"इनपुट इवेंट" सुनने पर, हो सकता है कि आपके मन में सिर्फ़ टेक्स्टबॉक्स में टाइप करने या माउस क्लिक करने का ख्याल आए. हालांकि, ब्राउज़र के हिसाब से, इनपुट का मतलब उपयोगकर्ता का कोई भी जेस्चर होता है. माउस व्हील स्क्रोल एक इनपुट इवेंट है. साथ ही, टच या माउस ओवर भी एक इनपुट इवेंट है.
जब स्क्रीन पर उपयोगकर्ता की कोई हरकत होती है, जैसे कि टच करना, तो ब्राउज़र प्रोसेस को सबसे पहले वह हरकत मिलती है. हालांकि, ब्राउज़र प्रोसेस को सिर्फ़ इस बात की जानकारी होती है कि जेस्चर कहां हुआ था. ऐसा इसलिए, क्योंकि टैब में मौजूद कॉन्टेंट को रेंडर करने की प्रोसेस मैनेज करती है. इसलिए, ब्राउज़र प्रोसेस, इवेंट टाइप (जैसे कि touchstart
) और उसके निर्देशों को रेंडरर प्रोसेस को भेजती है. रेंडरर प्रोसेस, इवेंट टारगेट ढूंढकर और अटैच किए गए इवेंट लिसनर चलाकर, इवेंट को सही तरीके से मैनेज करती है.
कंपोजिटर को इनपुट इवेंट मिलते हैं
पिछली पोस्ट में, हमने देखा था कि रेस्टर लेयर को कॉम्पोज़ करके, कॉम्पोज़र कैसे स्क्रीन को आसानी से स्क्रोल कर सकता है. अगर पेज में कोई इनपुट इवेंट लिसनर अटैच नहीं है, तो कंपोजिट थ्रेड, मुख्य थ्रेड से पूरी तरह से अलग एक नया कंपोजिट फ़्रेम बना सकता है. लेकिन अगर पेज पर कुछ इवेंट Listener अटैच किए गए थे, तो क्या होगा? कंपोजिटर थ्रेड को कैसे पता चलेगा कि इवेंट को मैनेज करने की ज़रूरत है या नहीं?
धीरे स्क्रोल किए जा सकने वाले रीजन को समझना
JavaScript चलाना, मुख्य थ्रेड का काम है. इसलिए, जब कोई पेज कॉम्पोज़ किया जाता है, तो कॉम्पोज़र थ्रेड, पेज के उस हिस्से को "तेज़ी से स्क्रोल नहीं किया जा सकने वाला क्षेत्र" के तौर पर मार्क करता है जिसमें इवेंट हैंडलर अटैच होते हैं. इस जानकारी की मदद से, अगर इवेंट उस क्षेत्र में होता है, तो कंपोजिटर थ्रेड यह पक्का कर सकता है कि वह मुख्य थ्रेड पर इनपुट इवेंट भेजे. अगर इनपुट इवेंट इस क्षेत्र से बाहर से आता है, तो मुख्य थ्रेड के इंतज़ार किए बिना, कंपोजिटर थ्रेड नया फ़्रेम कंपोज करता रहता है.
इवेंट हैंडलर लिखते समय सावधानी बरतें
वेब डेवलपमेंट में, इवेंट मैनेज करने का एक सामान्य तरीका इवेंट डीलेगेशन है. इवेंट बबल होने की वजह से, सबसे ऊपर मौजूद एलिमेंट में एक इवेंट हैंडलर अटैच किया जा सकता है. साथ ही, इवेंट टारगेट के आधार पर टास्क सौंपे जा सकते हैं. आपने ऐसा कोड देखा या लिखा हो सकता है.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
आपको सभी एलिमेंट के लिए सिर्फ़ एक इवेंट हैंडलर लिखना होता है. इसलिए, इस इवेंट के डिलीगेशन पैटर्न को इस्तेमाल करना आसान है. हालांकि, अगर इस कोड को ब्राउज़र के नज़रिए से देखा जाए, तो अब पूरा पेज, तेज़ी से स्क्रोल न किए जा सकने वाले हिस्से के तौर पर मार्क हो जाता है. इसका मतलब है कि भले ही आपका ऐप्लिकेशन, पेज के कुछ हिस्सों से मिलने वाले इनपुट पर ध्यान न देता हो, फिर भी कॉम्पोज़र थ्रेड को मुख्य थ्रेड के साथ कम्यूनिकेट करना होता है. साथ ही, हर बार इनपुट इवेंट आने पर, उसके इंतज़ार में रहना होता है. इसलिए, कॉम्पोज़र की स्मूद स्क्रोलिंग की सुविधा काम नहीं करती.
ऐसा होने से रोकने के लिए, अपने इवेंट लिसनर में passive: true
विकल्प पास किए जा सकते हैं. इससे ब्राउज़र को यह पता चलता है कि आपको अब भी मुख्य थ्रेड में इवेंट सुनना है,
लेकिन कंपोजिटर नए फ़्रेम को भी कंपोज कर सकता है.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
देखें कि इवेंट को रद्द किया जा सकता है या नहीं
मान लें कि आपके पास एक पेज में एक बॉक्स है और आपको स्क्रोल करने की दिशा को सिर्फ़ हॉरिज़ॉन्टल स्क्रोल तक सीमित रखना है.
अपने पॉइंटर इवेंट में passive: true
विकल्प का इस्तेमाल करने का मतलब है कि पेज को आसानी से स्क्रोल किया जा सकता है. हालांकि, हो सकता है कि स्क्रोल की दिशा को सीमित करने के लिए, preventDefault
का इस्तेमाल करने से पहले वर्टिकल स्क्रोल शुरू हो गया हो. event.cancelable
तरीके का इस्तेमाल करके, इसकी जांच की जा सकती है.
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
इसके अलावा, इवेंट हैंडलर को पूरी तरह से हटाने के लिए, touch-action
जैसे सीएसएस नियम का इस्तेमाल किया जा सकता है.
#area {
touch-action: pan-x;
}
इवेंट टारगेट ढूंढना
जब कंपोजिटर थ्रेड, मुख्य थ्रेड को कोई इनपुट इवेंट भेजता है, तो सबसे पहले इवेंट टारगेट ढूंढने के लिए हिट जांच की जाती है. हिट टेस्ट, रेंडरिंग प्रोसेस में जनरेट किए गए पेंट रिकॉर्ड डेटा का इस्तेमाल करता है. इससे यह पता चलता है कि इवेंट जिस पॉइंट के निर्देशांक पर हुआ है उसके नीचे क्या है.
मुख्य थ्रेड में इवेंट डिस्पैच को कम करना
पिछली पोस्ट में, हमने बताया था कि हमारा सामान्य डिसप्ले, स्क्रीन को एक सेकंड में 60 बार रीफ़्रेश करता है. साथ ही, हमने यह भी बताया था कि स्मूद ऐनिमेशन के लिए, हमें इस गति को कैसे बनाए रखना चाहिए. इनपुट के लिए, आम तौर पर कोई टच-स्क्रीन डिवाइस, हर सेकंड में 60 से 120 बार टच इवेंट डिलीवर करता है. वहीं, कोई सामान्य माउस, हर सेकंड में 100 बार इवेंट डिलीवर करता है. इनपुट इवेंट की फ़िडेलिटी, हमारी स्क्रीन के रीफ़्रेश होने की दर से ज़्यादा है.
अगर touchmove
जैसे लगातार होने वाले इवेंट को मुख्य थ्रेड पर हर सेकंड 120 बार भेजा गया, तो स्क्रीन के रीफ़्रेश होने की स्पीड की तुलना में, हिट टेस्ट और JavaScript के एक्सीक्यूशन की संख्या ज़्यादा हो सकती है.
मुख्य थ्रेड पर ज़्यादा कॉल को कम करने के लिए, Chrome लगातार होने वाले इवेंट (जैसे कि wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) को एक साथ जोड़ता है और अगले requestAnimationFrame
से ठीक पहले तक डिस्पैच करने में देरी करता है.
keydown
, keyup
, mouseup
, mousedown
, touchstart
, और touchend
जैसे अलग-अलग इवेंट तुरंत भेज दिए जाते हैं.
इंटर-फ़्रेम इवेंट पाने के लिए, getCoalescedEvents
का इस्तेमाल करें
ज़्यादातर वेब ऐप्लिकेशन के लिए, उपयोगकर्ता को बेहतर अनुभव देने के लिए, एक साथ होने वाले इवेंट काफ़ी होते हैं.
हालांकि, अगर आपको ड्रॉइंग ऐप्लिकेशन बनाने हैं और touchmove
निर्देशांक के आधार पर कोई पाथ बनाना है, तो हो सकता है कि बीच के निर्देशांक न दिखें. ऐसा इसलिए होता है, ताकि एक ही लेवल पर लाइन खींची जा सके. ऐसे में, एक साथ होने वाले इवेंट के बारे में जानकारी पाने के लिए, पॉइंटर इवेंट में getCoalescedEvents
तरीके का इस्तेमाल किया जा सकता है.
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
अगले चरण
इस सीरीज़ में, हमने वेब ब्राउज़र के काम करने के तरीके के बारे में बताया है. अगर आपने कभी इस बारे में नहीं सोचा है कि DevTools आपके इवेंट हैंडलर पर {passive: true}
जोड़ने का सुझाव क्यों देता है या आपको अपने स्क्रिप्ट टैग में async
एट्रिब्यूट क्यों लिखना चाहिए, तो हमें उम्मीद है कि इस सीरीज़ से आपको इस बारे में कुछ जानकारी मिलेगी कि वेब पर तेज़ और आसान अनुभव देने के लिए, ब्राउज़र को इस जानकारी की ज़रूरत क्यों है.
Lighthouse का इस्तेमाल करना
अगर आपको अपने कोड को ब्राउज़र के हिसाब से बनाना है, लेकिन आपको नहीं पता कि कहां से शुरू करें, तो Lighthouse एक ऐसा टूल है जो किसी भी वेबसाइट की ऑडिट करता है. साथ ही, आपको यह रिपोर्ट देता है कि क्या सही तरीके से किया जा रहा है और किसमें सुधार की ज़रूरत है. ऑडिट की सूची को पढ़ने से, आपको यह भी पता चलता है कि ब्राउज़र किस तरह की चीज़ों पर ध्यान देता है.
परफ़ॉर्मेंस मेज़र करने का तरीका जानें
अलग-अलग साइटों के लिए, परफ़ॉर्मेंस में बदलाव अलग-अलग हो सकते हैं. इसलिए, यह ज़रूरी है कि आप अपनी साइट की परफ़ॉर्मेंस का आकलन करें और यह तय करें कि आपकी साइट के लिए कौनसा बदलाव सबसे सही है. Chrome DevTools टीम ने अपनी साइट की परफ़ॉर्मेंस को मेज़र करने के तरीके के बारे में कुछ ट्यूटोरियल बनाए हैं.
अपनी साइट पर सुविधा से जुड़ी नीति जोड़ना
अगर आपको और भी ज़्यादा सुरक्षा चाहिए, तो सुविधा से जुड़ी नीति, वेब प्लैटफ़ॉर्म की एक नई सुविधा है. यह सुविधा, प्रोजेक्ट बनाते समय आपके लिए सुरक्षा कवच की तरह काम कर सकती है. सुविधा से जुड़ी नीति चालू करने से, यह पक्का होता है कि आपका ऐप्लिकेशन सही तरीके से काम करेगा. साथ ही, इससे आपको गलतियां करने से भी रोका जा सकता है.
उदाहरण के लिए, अगर आपको यह पक्का करना है कि आपका ऐप्लिकेशन पार्सिंग को कभी ब्लॉक न करे, तो अपने ऐप्लिकेशन को सिंक्रोनस स्क्रिप्ट नीति पर चलाया जा सकता है. sync-script: 'none'
चालू होने पर, पार्स करने से रोकने वाले JavaScript को रन होने से रोका जाएगा. इससे आपके किसी भी कोड को पार्स करने से रोका जा सकता है. साथ ही, ब्राउज़र को पार्स करने की प्रोसेस रोकने की ज़रूरत नहीं पड़ती.
आखिर में खास जानकारी
जब मैंने वेबसाइटें बनाना शुरू किया, तब मुझे सिर्फ़ इस बात की ज़्यादा चिंता थी कि मैं अपना कोड कैसे लिखूं और मुझे ज़्यादा बेहतर तरीके से काम करने में क्या मदद करेगा. ये बातें ज़रूरी हैं, लेकिन हमें यह भी सोचना चाहिए कि ब्राउज़र, लिखे गए कोड को कैसे लेता है. आधुनिक ब्राउज़र, उपयोगकर्ताओं को बेहतर वेब अनुभव देने के लिए, लगातार काम कर रहे हैं. अपने कोड को व्यवस्थित करके, ब्राउज़र को बेहतर बनाने से, आपके उपयोगकर्ता अनुभव को भी बेहतर बनाने में मदद मिलती है. हमें उम्मीद है कि आप ब्राउज़र के साथ अच्छा बर्ताव करने की इस कोशिश में हमारे साथ शामिल होंगे!
इस सीरीज़ के शुरुआती ड्राफ़्ट की समीक्षा करने वाले सभी लोगों का धन्यवाद. इनमें ये लोग शामिल हैं: एलेक्ज़ रॉसैल, पॉल आयरिश, मेगिन केर्नी, एरिक बिडलमैन, मैथियास बीन्स, अड्डी ओसमानी, किनुको यासुदा, नास्को ओस्कॉव, और चैरी रीस.
क्या आपको यह सीरीज़ पसंद आई? अगर आने वाले समय में पोस्ट के लिए आपका कोई सवाल या सुझाव है, तो यहां दिए गए टिप्पणी वाले सेक्शन में या Twitter पर @kosamari पर हमें बताएं.