लेआउट में होने वाली समस्याओं की पहचान करने और उन्हें ठीक करने के लिए, WebPageTest का इस्तेमाल करने का तरीका.
मैंने पिछली पोस्ट में, WebPageTest में कुल लेआउट शिफ़्ट (सीएलएस) को मेज़र करने के बारे में लिखा था. सीएलएस, सभी लेआउट शिफ़्ट का एग्रीगेशन होता है. इसलिए, इस पोस्ट में मैंने सोचा कि किसी पेज पर हर लेआउट शिफ़्ट की बारीकी से जांच करना और इस बारे में जानना दिलचस्प होगा कि पेज में अस्थिरता की वजह क्या हो सकती है. साथ ही, समस्या को ठीक करने की कोशिश भी की जा सकती है.
लेआउट शिफ़्ट को मेज़र करना
लेआउट में होने वाले बदलावों से जुड़े एपीआई का इस्तेमाल करके, हमें किसी पेज पर होने वाले सभी लेआउट शिफ़्ट इवेंट की सूची मिल सकती है:
new Promise(resolve => {
new PerformanceObserver(list => {
resolve(list.getEntries().filter(entry => !entry.hadRecentInput));
}).observe({type: "layout-shift", buffered: true});
}).then(console.log);
इससे लेआउट शिफ़्ट का एक कलेक्शन बनता है, जिसमें इनपुट इवेंट नहीं होते:
[
{
"name": "",
"entryType": "layout-shift",
"startTime": 210.78500000294298,
"duration": 0,
"value": 0.0001045969445437389,
"hadRecentInput": false,
"lastInputTime": 0
}
]
इस उदाहरण में, 210 मिलीसेकंड में 0.01% की एक बहुत छोटी सी बदलाव हुआ.
बदलाव के समय और गंभीरता को जानने से, यह पता लगाने में मदद मिलती है कि बदलाव की वजह क्या हो सकती है. ज़्यादा टेस्टिंग करने के लिए, लैब एनवायरमेंट के तौर पर WebPageTest पर वापस जाएं.
WebPageTest में लेआउट में हुए बदलावों को मेज़र करना
WebPageTest में सीएलएस को मेज़र करने की तरह, अलग-अलग लेआउट शिफ़्ट को मेज़र करने के लिए भी कस्टम मेट्रिक की ज़रूरत होगी. Chrome 77 के स्टेबल वर्शन के रिलीज़ होने के बाद, यह प्रोसेस आसान हो गई है. लेआउट में होने वाले बदलावों से जुड़ा एपीआई डिफ़ॉल्ट रूप से चालू होता है. इसलिए, Chrome 77 में किसी भी वेबसाइट पर उस JS स्निपेट को चलाया जा सकता है और तुरंत नतीजे मिल सकते हैं. WebPageTest में, डिफ़ॉल्ट Chrome ब्राउज़र का इस्तेमाल किया जा सकता है. इसके लिए, आपको कमांड-लाइन फ़्लैग या Canary का इस्तेमाल करने की ज़रूरत नहीं है.
इसलिए, WebPageTest के लिए कस्टम मेट्रिक बनाने के लिए, उस स्क्रिप्ट में बदलाव करते हैं:
[LayoutShifts]
return new Promise(resolve => {
new PerformanceObserver(list => {
resolve(JSON.stringify(list.getEntries().filter(entry => !entry.hadRecentInput)));
}).observe({type: "layout-shift", buffered: true});
});
इस स्क्रिप्ट में मौजूद प्रॉमिस, ऐरे के बजाय उसके JSON वर्शन को दिखाता है. इसकी वजह यह है कि कस्टम मेट्रिक सिर्फ़ स्ट्रिंग या संख्याओं जैसे प्राइमिटिव डेटा टाइप जनरेट कर सकती हैं.
जांच के लिए, मैं ismyhostfastyet.com वेबसाइट का इस्तेमाल करूंगा. मैंने यह वेबसाइट, वेब होस्ट की लोडिंग की असल परफ़ॉर्मेंस की तुलना करने के लिए बनाई है.
लेआउट में होने वाले बदलावों की वजहों का पता लगाना
नतीजों में, हमें LayoutShifts कस्टम मेट्रिक की यह वैल्यू दिखती है:
[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3087.2349999990547,
"duration": 0,
"value": 0.3422101449275362,
"hadRecentInput": false,
"lastInputTime": 0
}
]
खास जानकारी के लिए, 3087 मिलीसेकंड में 34.2% का एक लेआउट शिफ़्ट हुआ है. समस्या की पहचान करने के लिए, WebPageTest के फ़िल्मस्ट्रिप व्यू का इस्तेमाल करें.
फ़िल्मस्ट्रिप में ~3 सेकंड के मार्क पर स्क्रोल करने से, हमें पता चलता है कि लेआउट में 34% बदलाव होने की वजह क्या है: रंगीन टेबल. वेबसाइट, JSON फ़ाइल को असिंक्रोनस तरीके से फ़ेच करती है. इसके बाद, उसे टेबल में रेंडर करती है. टेबल शुरू में खाली होती है. इसलिए, नतीजे लोड होने पर उसे भरने के लिए इंतज़ार करने पर, डेटा में बदलाव होता है.
बस यही नहीं. जब पेज ~4.3 सेकंड में पूरी तरह से दिखने लगता है, तो हमें पता चलता है कि पेज का <h1>
"क्या मेरा होस्ट अब भी तेज़ है?" अचानक से दिखता है. ऐसा इसलिए होता है, क्योंकि साइट किसी वेब फ़ॉन्ट का इस्तेमाल करती है और उसने रेंडरिंग को ऑप्टिमाइज़ करने के लिए कोई कदम नहीं उठाया है. ऐसा होने पर, लेआउट में कोई बदलाव नहीं होता. हालांकि, टाइटल पढ़ने के लिए इतना इंतज़ार करना, उपयोगकर्ता अनुभव के लिहाज़ से खराब है.
लेआउट में होने वाली गड़बड़ियों को ठीक करना
अब हमें पता है कि असींक्रोनस तरीके से जनरेट की गई टेबल की वजह से, व्यूपोर्ट का एक तिहाई हिस्सा शिफ़्ट हो रहा है. अब इसे ठीक करने का समय आ गया है. जब तक JSON के नतीजे लोड नहीं हो जाते, तब तक हमें टेबल के कॉन्टेंट के बारे में नहीं पता होता. हालांकि, हम टेबल में किसी तरह का प्लेसहोल्डर डेटा डाल सकते हैं, ताकि डीओएम रेंडर होने पर लेआउट अप-टू-डेट रहे.
प्लेसहोल्डर डेटा जनरेट करने का कोड यहां दिया गया है:
function getRandomFiller(maxLength) {
var filler = '█';
var len = Math.ceil(Math.random() * maxLength);
return new Array(len).fill(filler).join('');
}
function getRandomDistribution() {
var fast = Math.random();
var avg = (1 - fast) * Math.random();
var slow = 1 - (fast + avg);
return [fast, avg, slow];
}
// Temporary placeholder data.
window.data = [];
for (var i = 0; i < 36; i++) {
var [fast, avg, slow] = getRandomDistribution();
window.data.push({
platform: getRandomFiller(10),
client: getRandomFiller(5),
n: getRandomFiller(1),
fast,
avg,
slow
});
}
updateResultsTable(sortResults(window.data, 'fast'));
प्लेसहोल्डर डेटा को क्रम से लगाने से पहले, उसे रैंडम तरीके से जनरेट किया जाता है. इसमें "█" वर्ण को कई बार दोहराया गया है, ताकि टेक्स्ट के लिए विज़ुअल प्लेसहोल्डर बनाए जा सकें. साथ ही, तीन मुख्य वैल्यू को रैंडम तौर पर जनरेट किया गया है. मैंने टेबल से सभी रंग हटाने के लिए कुछ स्टाइल भी जोड़े हैं, ताकि यह साफ़ तौर पर पता चल सके कि डेटा अभी तक पूरी तरह से लोड नहीं हुआ है.
लेआउट के स्थिर रहने के लिए, इस्तेमाल किए गए प्लेसहोल्डर के दिखने का कोई फ़र्क़ नहीं पड़ता. प्लेसहोल्डर का मकसद, उपयोगकर्ताओं को यह भरोसा दिलाना है कि कॉन्टेंट आ रहा है और पेज काम कर रहा है.
JSON डेटा लोड होने के दौरान प्लेसहोल्डर इस तरह दिखते हैं:
वेब फ़ॉन्ट से जुड़ी समस्या को हल करना काफ़ी आसान है. साइट पर Google फ़ॉन्ट का इस्तेमाल किया जा रहा है. इसलिए, हमें सीएसएस अनुरोध में सिर्फ़ display=swap
प्रॉपर्टी को पास करना होगा. बस इतना ही। Fonts API, फ़ॉन्ट डिक्लेरेशन में font-display: swap
स्टाइल जोड़ देगा. इससे ब्राउज़र, टेक्स्ट को फ़ॉलबैक फ़ॉन्ट में तुरंत रेंडर कर पाएगा. यहां ठीक किए गए मार्कअप का उदाहरण दिया गया है:
<link href="https://fonts.googleapis.com/css?family=Chivo:900&display=swap" rel="stylesheet">
ऑप्टिमाइज़ेशन की पुष्टि करना
WebPageTest की मदद से पेज को फिर से चलाने के बाद, हम पहले और बाद की तुलना जनरेट कर सकते हैं. इससे, हमें अंतर को विज़ुअलाइज़ करने और लेआउट में होने वाले बदलावों की नई डिग्री को मेज़र करने में मदद मिलती है:
[
{
"name": "",
"entryType": "layout-shift",
"startTime": 3070.9349999997357,
"duration": 0,
"value": 0.000050272187989256116,
"hadRecentInput": false,
"lastInputTime": 0
}
]
कस्टम मेट्रिक के मुताबिक, अब भी 3071 मिलीसेकंड (लगभग पहले जैसा ही समय) में लेआउट शिफ़्ट हो रहा है. हालांकि, शिफ़्ट की गंभीरता काफ़ी कम है: 0.005%. मुझे यह मंज़ूर है.
फ़िल्मस्ट्रिप से यह भी पता चलता है कि <h1>
फ़ॉन्ट, सिस्टम फ़ॉन्ट पर तुरंत स्विच हो रहा है, ताकि उपयोगकर्ता उसे जल्दी पढ़ सकें.
नतीजा
जटिल वेबसाइटों में, इस उदाहरण के मुकाबले ज़्यादा लेआउट शिफ़्ट हो सकते हैं. हालांकि, समस्या को ठीक करने की प्रोसेस अब भी वही है: WebPageTest में लेआउट में होने वाले बदलावों की मेट्रिक जोड़ें, समस्या की पहचान करने के लिए विज़ुअल लोडिंग फ़िल्मस्ट्रिप के साथ नतीजों का क्रॉस-रेफ़रंस करें, और स्क्रीन के रियल एस्टेट को रिज़र्व करने के लिए प्लेसहोल्डर का इस्तेमाल करके समस्या को ठीक करें.
(एक और बात) असल उपयोगकर्ताओं को लेआउट में होने वाली अस्थिरता का आकलन करना
किसी पेज को ऑप्टिमाइज़ करने से पहले और बाद में, उस पर WebPageTest चलाकर मेट्रिक में हुए सुधार को देखना अच्छा लगता है. हालांकि, असल में यह मायने रखता है कि उपयोगकर्ता अनुभव बेहतर हो रहा है या नहीं. क्या इसलिए हम साइट को बेहतर बनाने की कोशिश कर रहे हैं?
इसलिए, अगर हम वेब की परफ़ॉर्मेंस की अपनी पारंपरिक मेट्रिक के साथ-साथ, असल उपयोगकर्ताओं के लेआउट में होने वाले बदलावों को मेज़र करना शुरू करें, तो यह बहुत अच्छा होगा. यह ऑप्टिमाइज़ेशन फ़ीडबैक लूप का एक अहम हिस्सा है. फ़ील्ड से मिलने वाले डेटा से हमें पता चलता है कि समस्याएं कहां हैं और क्या हमारे सुधारों से कोई फ़ायदा हुआ है.
अपने लेआउट में होने वाले बदलावों का डेटा इकट्ठा करने के अलावा, Chrome UX रिपोर्ट देखें. इसमें लाखों वेबसाइटों पर उपयोगकर्ताओं के अनुभव से जुड़ा क्युम्युलेटिव लेआउट शिफ़्ट डेटा शामिल होता है. इसकी मदद से, यह पता लगाया जा सकता है कि आपकी (या आपके प्रतिस्पर्धियों की) परफ़ॉर्मेंस कैसी है. इसके अलावा, इसका इस्तेमाल करके यह भी पता लगाया जा सकता है कि वेब पर लेआउट की स्थिति कैसी है.