एक नया JavaScript API, जो लोड होने की परफ़ॉर्मेंस और इनपुट रिस्पॉन्स के बीच के उतार-चढ़ाव से बचने में आपकी मदद कर सकता है.
तेज़ी से लोड करना मुश्किल है. फ़िलहाल, अपने कॉन्टेंट को रेंडर करने के लिए JS का इस्तेमाल करने वाली साइटों को, लोड करने में लगने वाले समय और इनपुट के रिस्पॉन्सिव होने के बीच एक समझौता करना पड़ता है: या तो डिसप्ले के लिए ज़रूरी सभी काम एक साथ करें (लोड करने में लगने वाला समय कम, इनपुट के रिस्पॉन्सिव होने में ज़्यादा समय), या इनपुट और पेंट के रिस्पॉन्सिव बने रहने के लिए, काम को छोटे-छोटे टास्क में बांटें (लोड करने में लगने वाला समय ज़्यादा, इनपुट के रिस्पॉन्सिव होने में कम समय).
इस तरह के समझौते की ज़रूरत को खत्म करने के लिए, Facebook ने Chromium में isInputPending()
एपीआई का सुझाव दिया और उसे लागू किया. इससे, बिना किसी समझौते के रिस्पॉन्सिवनेस को बेहतर बनाया जा सकता है. ऑरिजिन ट्रायल के सुझावों और राय के आधार पर, हमने एपीआई में कई अपडेट किए हैं. हमें यह बताते हुए खुशी हो रही है कि एपीआई अब Chromium 87 में डिफ़ॉल्ट रूप से शिप हो रहा है!
ब्राउज़र के साथ काम करना
isInputPending()
यह सुविधा, Chromium कोड वाले ब्राउज़र के वर्शन 87 से शुरू की गई है.
किसी भी दूसरे ब्राउज़र ने एपीआई को भेजने की ज़रूरत का सिग्नल नहीं दिया है.
बैकग्राउंड
आज के JS नेटवर्क में ज़्यादातर काम, एक ही थ्रेड पर होता है: मुख्य थ्रेड. इससे डेवलपर को बेहतर तरीके से स्क्रिप्ट को लागू करने का मॉडल मिलता है. हालांकि, अगर स्क्रिप्ट लंबे समय तक चलती है, तो उपयोगकर्ता अनुभव (खास तौर पर रिस्पॉन्सिवनेस) पर काफ़ी असर पड़ सकता है. उदाहरण के लिए, अगर कोई इनपुट इवेंट ट्रिगर होने के दौरान पेज बहुत ज़्यादा काम कर रहा है, तो पेज तब तक क्लिक इनपुट इवेंट को हैंडल नहीं करेगा, जब तक वह काम पूरा नहीं हो जाता.
इस समस्या को हल करने का सबसे सही तरीका यह है कि JavaScript को छोटे-छोटे ब्लॉक में बांट दिया जाए. पेज लोड होने के दौरान, वह थोड़ा सा JavaScript चला सकता है. इसके बाद, कंट्रोल को ब्राउज़र को वापस दे देता है. इसके बाद, ब्राउज़र अपनी इनपुट इवेंट सूची की जांच कर सकता है और यह देख सकता है कि पेज को बताने के लिए, कोई ऐसी चीज़ है या नहीं. इसके बाद, ब्राउज़र फिर से JavaScript ब्लॉक चला सकता है, क्योंकि वे जोड़े जाते हैं. इससे मदद मिलती है, लेकिन इससे अन्य समस्याएं भी हो सकती हैं.
जब भी पेज, ब्राउज़र को कंट्रोल वापस देता है, तो ब्राउज़र को अपनी इनपुट इवेंट कतार की जांच करने, इवेंट को प्रोसेस करने, और अगला JavaScript ब्लॉक चुनने में कुछ समय लगता है. ब्राउज़र, इवेंट का जवाब तेज़ी से देता है, लेकिन पेज के लोड होने में ज़्यादा समय लगता है. अगर हम बहुत बार 'नतीजे दिखाएं' विकल्प चुनते हैं, तो पेज बहुत धीरे लोड होता है. अगर हम ज़्यादा संख्या में नतीजे नहीं देते, तो ब्राउज़र को उपयोगकर्ता इवेंट से जवाब देने में ज़्यादा समय लगता है और लोग निराश हो जाते हैं. मज़ेदार नहीं है.
Facebook पर, हम यह देखना चाहते थे कि अगर लोड करने के लिए हम कोई ऐसा नया तरीका अपनाते हैं जो इस समस्या को खत्म कर दे. इस बारे में हमने Chrome पर अपने दोस्तों से बात की और isInputPending()
के लिए प्रस्ताव तैयार किया. वेब पर उपयोगकर्ता के इनपुट के लिए, रुकावट डालने वाले कॉन्सेप्ट का इस्तेमाल करने वाला सबसे पहला एपीआई isInputPending()
एपीआई है. इसकी मदद से, JavaScript को ब्राउज़र पर दिए बिना इनपुट की जांच करने की सुविधा मिलती है.
एपीआई में लोगों की दिलचस्पी को देखते हुए, हमने Chromium में इस सुविधा को लागू करने और उसे उपलब्ध कराने के लिए, Chrome के अपने सहयोगियों के साथ साझेदारी की. Chrome के इंजीनियरों की मदद से, हमने ऑरिजिन ट्रायल के बाद पैच लागू किए. यह एक ऐसा तरीका है जिससे Chrome, एपीआई को पूरी तरह से रिलीज़ करने से पहले, बदलावों की जांच कर सकता है और डेवलपर से सुझाव/राय पा सकता है.
हमने ऑरिजिन ट्रायल और W3C वेब परफ़ॉर्मेंस वर्किंग ग्रुप के अन्य सदस्यों से सुझाव/राय ली है. साथ ही, एपीआई में बदलाव लागू कर दिए हैं.
उदाहरण: एक यील्ड शेड्यूलर
मान लें कि आपको अपना पेज लोड करने के लिए, डिसप्ले को ब्लॉक करने वाला बहुत सारा काम करना है. उदाहरण के लिए, कॉम्पोनेंट से मार्कअप जनरेट करना, प्राइम को फ़ैक्टर करना या सिर्फ़ एक शानदार लोडिंग स्पिनर बनाना. इनमें से हर एक को अलग-अलग वर्क आइटम में बांटा जाता है. शेड्यूलर पैटर्न का इस्तेमाल करके, आइए देखें कि हम किसी processWorkQueue()
फ़ंक्शन में अपने काम को कैसे प्रोसेस कर सकते हैं:
const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
if (performance.now() >= DEADLINE) {
// Yield the event loop if we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
setTimeout()
की मदद से, नए मैक्रोटास्क में बाद में processWorkQueue()
को शुरू करके, हम ब्राउज़र को इनपुट के लिए कुछ हद तक रिस्पॉन्सिव बनाते हैं. इससे, काम फिर से शुरू होने से पहले, ब्राउज़र इवेंट हैंडलर चला सकता है. साथ ही, यह बिना किसी रुकावट के काम करता रहता है. हालांकि, इवेंट लूप को कंट्रोल करने वाले किसी दूसरे काम की वजह से, हो सकता है कि हम लंबे समय तक शेड्यूल न हों या इवेंट के इंतज़ार का समय QUANTUM
मिलीसेकंड तक बढ़ जाए.
यह ठीक है, लेकिन क्या हम इसे बेहतर बना सकते हैं? बिल्कुल!
const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
if (navigator.scheduling.isInputPending() || performance.now() >= DEADLINE) {
// Yield if we have to handle an input event, or we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
navigator.scheduling.isInputPending()
पर कॉल करके, हम इनपुट का तुरंत जवाब दे सकते हैं. साथ ही, यह भी पक्का कर सकते हैं कि डिसप्ले ब्लॉक करने की सुविधा का काम बिना किसी रुकावट के जारी रहे. अगर हमें काम पूरा होने तक, इनपुट (जैसे, पेंटिंग) के अलावा किसी और चीज़ को मैनेज करने में दिलचस्पी नहीं है, तो हम QUANTUM
की लंबाई भी आसानी से बढ़ा सकते हैं.
डिफ़ॉल्ट रूप से, isInputPending()
से "लगातार" इवेंट नहीं लौटाए जाते. इनमें mousemove
, pointermove
, और अन्य शामिल हैं. अगर आपको इनके लिए भी YIELD का इस्तेमाल करना है, तो कोई बात नहीं. isInputPending()
को एक ऑब्जेक्ट देकर,
includeContinuous
को true
पर सेट करें. इसके बाद, हम आगे बढ़ सकते हैं:
const DEADLINE = performance.now() + QUANTUM;
const options = { includeContinuous: true };
while (workQueue.length > 0) {
if (navigator.scheduling.isInputPending(options) || performance.now() >= DEADLINE) {
// Yield if we have to handle an input event (any of them!), or we're out of time.
setTimeout(processWorkQueue);
return;
}
let job = workQueue.shift();
job.execute();
}
हो गया! React जैसे फ़्रेमवर्क, मिलते-जुलते लॉजिक का इस्तेमाल करके, अपनी मुख्य शेड्यूलिंग लाइब्रेरी में isInputPending()
के साथ काम करने की सुविधा जोड़ रहे हैं. उम्मीद है कि इससे इन फ़्रेमवर्क का इस्तेमाल करने वाले डेवलपर, isInputPending()
का फ़ायदा पा सकेंगे. इसके लिए, उन्हें कोड में काफ़ी बदलाव करने की ज़रूरत नहीं पड़ेगी.
हार मानना हमेशा बुरा नहीं होता
ध्यान दें कि हर मामले में कम डेटा इस्तेमाल करना सही नहीं है. इनपुट इवेंट प्रोसेस करने के अलावा, ब्राउज़र पर कंट्रोल वापस पाने की कई वजहें हैं. जैसे, पेज पर रेंडर करना और अन्य स्क्रिप्ट लागू करना.
ऐसे मामले भी हो सकते हैं जिनमें ब्राउज़र, बाकी बचे इनपुट इवेंट को सही तरीके से एट्रिब्यूट न कर पाए. खास तौर पर, क्रॉस-ऑरिजिन iframe के लिए, जटिल क्लिप और मास्क सेट करने से गलत नेगेटिव कॉन्टेंट रिपोर्ट किया जा सकता है. इसका मतलब है कि इन फ़्रेम को टारगेट करने पर, isInputPending()
अचानक से गलत नतीजे दिखा सकता है. ध्यान रखें कि अगर आपकी साइट को बेहतर बनाए गए सबफ़्रेम के साथ इंटरैक्शन की ज़रूरत हो, तो उससे अक्सर अच्छी कमाई हो रही हो.
इवेंट लूप शेयर करने वाले अन्य पेजों का भी ध्यान रखें. Android के लिए Chrome जैसे प्लैटफ़ॉर्म पर, एक से ज़्यादा ऑरिजिन के लिए इवेंट लूप शेयर करना आम बात है. अगर इनपुट को क्रॉस-ऑरिजिन फ़्रेम पर भेजा जाता है, तो isInputPending()
कभी भी true
नहीं दिखाएगा. इसलिए, बैकग्राउंड में चल रहे पेज, फ़ोरग्राउंड में चल रहे पेजों के रिस्पॉन्स में रुकावट डाल सकते हैं. Page Visibility API का इस्तेमाल करके, बैकग्राउंड में काम करते समय, ज़्यादा बार कम करने, स्थगित करने या 'वीडियो चलाने के लिए अनुरोध करें' सुविधा का इस्तेमाल करने की ज़रूरत पड़ सकती है.
हमारा सुझाव है कि आप isInputPending()
का इस्तेमाल सोच-समझकर करें. अगर उपयोगकर्ता को ब्लॉक करने वाला कोई काम नहीं है, तो इवेंट लूप में मौजूद अन्य लोगों के लिए, ज़्यादा बार 'नतीजा दिया गया' फ़ंक्शन का इस्तेमाल करें. लंबे टास्क नुकसान पहुंचा सकते हैं.
सुझाव/राय दें या शिकायत करें
- is-input-pending रिपॉज़िटरी में, स्पेसिफ़िकेशन के बारे में सुझाव/राय दें या शिकायत करें.
- स्पेसिफ़िकेशन के लेखकों में से एक @acomminos से Twitter पर संपर्क करें.
नतीजा
हमें यह बताते हुए खुशी हो रही है कि isInputPending()
लॉन्च हो रहा है और डेवलपर इसका इस्तेमाल आज से कर सकते हैं. इस एपीआई के साथ, Facebook ने पहली बार नया वेब एपीआई बनाया है. साथ ही, इसे आइडिया से लेकर स्टैंडर्ड के प्रस्ताव तक ले गया है, ताकि इसे ब्राउज़र में उपलब्ध कराया जा सके. हम उन सभी लोगों का शुक्रिया अदा करना चाहते हैं जिन्होंने इस तक पहुंचने में हमारी मदद की है. साथ ही, हम Chrome के उन सभी लोगों का खास तौर पर धन्यवाद करते हैं जिन्होंने इस आइडिया को लागू करने और इसे लोगों तक पहुंचाने में हमारी मदद की है!
Unsplash पर Will H McMahan की हीरो फ़ोटो.