इनपुट, कंपोज़िटर को मिलने वाला है
यह 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 एक ऐसा टूल है जो किसी भी वेबसाइट की ऑडिट करता है. साथ ही, आपको यह रिपोर्ट देता है कि क्या सही तरीके से किया जा रहा है और किसमें सुधार की ज़रूरत है. ऑडिट की सूची को पढ़ने से आपको यह भी पता चलता है कि ब्राउज़र किस तरह की चीज़ों का ध्यान रखता है.
परफ़ॉर्मेंस मेज़र करने का तरीका जानें
अलग-अलग साइटों के लिए, परफ़ॉर्मेंस में बदलाव अलग-अलग हो सकते हैं. इसलिए, यह ज़रूरी है कि आप अपनी साइट की परफ़ॉर्मेंस का आकलन करें और यह तय करें कि आपकी साइट के लिए कौनसा बदलाव सबसे सही है. Chrome DevTools टीम ने अपनी साइट की परफ़ॉर्मेंस को मेज़र करने के तरीके के बारे में कुछ ट्यूटोरियल बनाए हैं.
अपनी साइट पर सुविधा से जुड़ी नीति जोड़ना
अगर आपको एक और कदम उठाना है, तो सुविधा से जुड़ी नीति, वेब प्लैटफ़ॉर्म की एक नई सुविधा है. यह आपके प्रोजेक्ट को बनाते समय, आपके लिए एक सुरक्षा कवच की तरह काम कर सकती है. सुविधा से जुड़ी नीति चालू करने से, यह पक्का होता है कि आपका ऐप्लिकेशन सही तरीके से काम करेगा. साथ ही, इससे आपको गलतियां करने से भी रोका जा सकता है.
उदाहरण के लिए, अगर आपको यह पक्का करना है कि आपका ऐप्लिकेशन पार्सिंग को कभी ब्लॉक न करे, तो अपने ऐप्लिकेशन को सिंक्रोनस स्क्रिप्ट नीति पर चलाया जा सकता है. sync-script: 'none'
चालू होने पर, पार्स करने से रोकने वाले JavaScript को रन होने से रोका जाएगा. इससे आपके किसी भी कोड को पार्स करने से रोका जा सकता है. साथ ही, ब्राउज़र को पार्स करने की प्रोसेस रोकने की ज़रूरत नहीं पड़ती.
आखिर में खास जानकारी
जब मैंने वेबसाइटें बनाना शुरू किया, तब मैंने बस इस बात का ध्यान रखा कि मैं अपना कोड कैसे लिखूं और बेहतर तरीके से कैसे काम करूं. ये बातें ज़रूरी हैं, लेकिन हमें यह भी सोचना चाहिए कि ब्राउज़र, लिखे गए कोड को कैसे लेता है. आधुनिक ब्राउज़र, उपयोगकर्ताओं को बेहतर वेब अनुभव देने के लिए, लगातार काम कर रहे हैं. अपने कोड को व्यवस्थित करके, ब्राउज़र को बेहतर बनाने से, आपके उपयोगकर्ता अनुभव को भी बेहतर बनाने में मदद मिलती है. मुझे उम्मीद है कि ब्राउज़र का इस्तेमाल बेहतर तरीके से करने की दौड़ में आप भी मेरे साथ होंगे!
इस सीरीज़ के शुरुआती ड्राफ़्ट की समीक्षा करने वाले सभी लोगों का धन्यवाद. इनमें ये लोग शामिल हैं: एलेक्ज़ रॉसैल, पॉल आयरिश, मेगिन केर्नी, एरिक बिडलमैन, मैथियास बीन्स, अड्डी ओसमानी, किनुको यासुदा, नास्को ओस्कॉव, और चैरी रीस.
क्या आपको यह सीरीज़ पसंद आई? अगर आगे की पोस्ट के बारे में आपका कोई सवाल या सुझाव है, तो हमें नीचे टिप्पणी वाले सेक्शन या Twitter पर @kosamari में आपका जवाब जानकर खुशी होगी.