ดูวิธีค้นหาการโต้ตอบที่ช้าในข้อมูลภาคสนามของเว็บไซต์เพื่อให้พบโอกาสในการปรับปรุงการโต้ตอบกับ Next Paint
ข้อมูลภาคสนามคือข้อมูลที่บอกให้คุณทราบว่าผู้ใช้จริงได้รับประสบการณ์การใช้งานเว็บไซต์อย่างไร ซึ่งจะแสดงปัญหาที่คุณไม่เห็นในข้อมูลในห้องทดลองเพียงอย่างเดียว สําหรับ Interaction to Next Paint (INP) ข้อมูลภาคสนามมีความสําคัญในการระบุการโต้ตอบที่ช้า และจะให้เบาะแสที่สําคัญในการช่วยคุณแก้ไขปัญหา
ในคู่มือนี้ คุณจะได้เรียนรู้วิธีประเมิน INP ของเว็บไซต์อย่างรวดเร็วโดยใช้ข้อมูลในช่องจากรายงานประสบการณ์ของผู้ใช้ Chrome (CrUX) เพื่อดูว่าเว็บไซต์มีปัญหาเกี่ยวกับ INP หรือไม่ จากนั้น คุณจะได้เรียนรู้วิธีใช้การบิลด์การระบุแหล่งที่มาของไลบรารี JavaScript ของ Web Vitals และข้อมูลเชิงลึกใหม่จาก Long Animation Frames API (LoAF) เพื่อรวบรวมและตีความข้อมูลภาคสนามสำหรับการโต้ตอบที่ช้าในเว็บไซต์
เริ่มต้นด้วย CrUX เพื่อประเมิน INP ของเว็บไซต์
หากคุณไม่ได้รวบรวมข้อมูลภาคสนามจากผู้ใช้เว็บไซต์ CrUX อาจเป็นจุดเริ่มต้นที่ดี CrUX จะรวบรวมข้อมูลภาคสนามจากผู้ใช้ Chrome จริงที่เลือกส่งข้อมูลการติดตาม
ข้อมูล CrUX จะแสดงในหลายๆ ส่วน โดยขึ้นอยู่กับขอบเขตของข้อมูลที่คุณกําลังมองหา CrUX สามารถให้ข้อมูลเกี่ยวกับ INP และ Core Web Vitals อื่นๆ สําหรับสิ่งต่อไปนี้
- หน้าเว็บแต่ละหน้าและต้นทางทั้งหมดโดยใช้ PageSpeed Insights
- ประเภทของหน้าเว็บ เช่น เว็บไซต์อีคอมเมิร์ซหลายแห่งมีหน้ารายละเอียดผลิตภัณฑ์และหน้าข้อมูลผลิตภัณฑ์ คุณดูข้อมูล CrUX สําหรับหน้าเว็บประเภทที่ไม่ซ้ำกันได้ใน Search Console
คุณสามารถป้อน URL ของเว็บไซต์ใน PageSpeed Insights เพื่อเป็นจุดเริ่มต้น เมื่อป้อน URL ข้อมูลในช่องของ URL นั้น (หากมี) จะแสดงสําหรับเมตริกหลายรายการ รวมถึง INP นอกจากนี้ คุณยังใช้ปุ่มเปิด/ปิดเพื่อตรวจสอบค่า INP สําหรับมิติข้อมูลในอุปกรณ์เคลื่อนที่และเดสก์ท็อปได้ด้วย
ข้อมูลนี้มีประโยชน์เนื่องจากจะบอกให้คุณทราบหากมีปัญหา อย่างไรก็ตาม CrUX ไม่สามารถบอกได้ว่าอะไรคือสาเหตุของปัญหา มีโซลูชัน Real User Monitoring (RUM) มากมายที่จะช่วยคุณรวบรวมข้อมูลภาคสนามของคุณเองจากผู้ใช้เว็บไซต์เพื่อช่วยตอบคำถามดังกล่าว และตัวเลือกหนึ่งคือการรวบรวมข้อมูลภาคสนามด้วยตนเองโดยใช้ไลบรารี JavaScript ของ Web Vitals
รวบรวมข้อมูลภาคสนามด้วยไลบรารี JavaScript ของ web-vitals
web-vitals
ไลบรารี JavaScript คือสคริปต์ที่คุณโหลดลงในเว็บไซต์เพื่อรวบรวมข้อมูลภาคสนามจากผู้ใช้เว็บไซต์ได้ คุณสามารถใช้เพื่อบันทึกเมตริกหลายรายการ รวมถึง INP ในเบราว์เซอร์ที่รองรับ
คุณสามารถใช้บิลด์มาตรฐานของไลบรารี Web Vitals เพื่อรับข้อมูล INP พื้นฐานจากผู้ใช้ในสนามได้ ดังนี้
import {onINP} from 'web-vitals';
onINP(({name, value, rating}) => {
console.log(name); // 'INP'
console.log(value); // 512
console.log(rating); // 'poor'
});
หากต้องการวิเคราะห์ข้อมูลภาคสนามจากผู้ใช้ คุณจะต้องส่งข้อมูลนี้ไปยังที่ใดที่หนึ่ง
import {onINP} from 'web-vitals';
onINP(({name, value, rating}) => {
// Prepare JSON to be sent for collection. Note that
// you can add anything else you'd want to collect here:
const body = JSON.stringify({name, value, rating});
// Use `sendBeacon` to send data to an analytics endpoint.
// For Google Analytics, see https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics.
navigator.sendBeacon('/analytics', body);
});
อย่างไรก็ตาม ข้อมูลนี้เพียงอย่างเดียวไม่ได้บอกอะไรมากกว่า CrUX การสร้างการระบุแหล่งที่มาของไลบรารี Web Vitals จึงเข้ามามีบทบาท
พัฒนาไปอีกขั้นด้วยการสร้างการระบุแหล่งที่มาของไลบรารี Web Vitals
การสร้างการระบุแหล่งที่มาของไลบรารี Web Vitals จะแสดงข้อมูลเพิ่มเติมที่คุณได้รับจากผู้ใช้ในสนามเพื่อช่วยให้คุณแก้ปัญหาการโต้ตอบที่มีปัญหาซึ่งส่งผลต่อ INP ของเว็บไซต์ได้ดียิ่งขึ้น ข้อมูลนี้เข้าถึงได้ผ่านออบเจ็กต์ attribution
ที่แสดงในเมธอด onINP()
ของไลบรารี
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, rating, attribution}) => {
console.log(name); // 'INP'
console.log(value); // 56
console.log(rating); // 'good'
console.log(attribution); // Attribution data object
});
นอกจาก INP ของหน้าเว็บแล้ว การสร้างการระบุแหล่งที่มายังมีข้อมูลจํานวนมากที่คุณสามารถใช้เพื่อช่วยทําความเข้าใจสาเหตุของการโต้ตอบที่ช้า รวมถึงส่วนของการโต้ตอบที่คุณควรมุ่งเน้น ซึ่งจะช่วยตอบคําถามสําคัญ เช่น
- "ผู้ใช้โต้ตอบกับหน้าเว็บขณะที่หน้ากำลังโหลดอยู่หรือไม่"
- "ตัวแฮนเดิลเหตุการณ์ของการโต้ตอบทํางานเป็นเวลานานหรือไม่"
- "โค้ดตัวแฮนเดิลเหตุการณ์การโต้ตอบเริ่มทำงานล่าช้าหรือไม่ หากใช่ มีอะไรเกิดขึ้นอีกในชุดข้อความหลักในเวลานั้น"
- "การโต้ตอบทําให้เกิดงานแสดงผลจํานวนมากที่ทําให้เฟรมถัดไปแสดงผลล่าช้าหรือไม่"
ตารางต่อไปนี้แสดงข้อมูลการระบุแหล่งที่มาพื้นฐานบางส่วนที่คุณได้รับจากคลัง ซึ่งจะช่วยคุณระบุสาเหตุระดับสูงที่ทําให้การโต้ตอบในเว็บไซต์ช้า
attribution คีย์ออบเจ็กต์
|
ข้อมูล |
---|---|
interactionTarget
|
ตัวเลือก CSS ที่ชี้ไปยังองค์ประกอบที่สร้างค่า INP ของหน้า เช่น button#save
|
interactionType
|
ประเภทของการโต้ตอบ ซึ่งอาจเป็นการคลิก การแตะ หรือการป้อนข้อมูลด้วยแป้นพิมพ์ |
inputDelay *
|
ความล่าช้าในการป้อนข้อมูลของการโต้ตอบ |
processingDuration *
|
เวลาตั้งแต่ที่โปรแกรมรับเหตุการณ์รายการแรกเริ่มทํางานเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้จนกว่าการประมวลผลโปรแกรมรับเหตุการณ์ทั้งหมดจะเสร็จสิ้น |
presentationDelay *
|
เวลาหน่วงของการแสดงผลของการโต้ตอบ ซึ่งเริ่มตั้งแต่ที่ตัวแฮนเดิลเหตุการณ์ทำงานเสร็จจนถึงเวลาที่ระบบวาดเฟรมถัดไป |
longAnimationFrameEntries *
|
รายการจาก LoAF ที่เชื่อมโยงกับการโต้ตอบ ดูข้อมูลเพิ่มเติมได้ในหน้าถัดไป |
ตั้งแต่ไลบรารี Web Vitals เวอร์ชัน 4 เป็นต้นไป คุณจะได้รับข้อมูลเชิงลึกที่ละเอียดยิ่งขึ้นเกี่ยวกับการโต้ตอบที่มีปัญหาผ่านข้อมูลที่มีให้พร้อมรายละเอียดของระยะ INP (เวลาตอบสนองต่ออินพุต ระยะเวลาการประมวลผล และความล่าช้าของการแสดงผล) และ Long Animation Frames API (LoAF)
Long Animation Frames API (LoAF)
การแก้ไขข้อบกพร่องของการโต้ตอบโดยใช้ข้อมูลภาคสนามเป็นงานที่ท้าทาย อย่างไรก็ตาม เมื่อใช้ข้อมูลจาก LoAF คุณจะได้รับข้อมูลเชิงลึกที่ดีขึ้นเกี่ยวกับสาเหตุที่ทําให้การโต้ตอบช้า เนื่องจาก LoAF จะแสดงเวลาโดยละเอียดและข้อมูลอื่นๆ ที่คุณสามารถใช้เพื่อระบุสาเหตุที่แน่ชัด และที่สำคัญกว่านั้นคือแหล่งที่มาของปัญหาในโค้ดของเว็บไซต์
บิลด์การระบุแหล่งที่มาของไลบรารี Web Vitals จะแสดงรายการ LoAF หลายรายการภายใต้คีย์ longAnimationFrameEntries
ของออบเจ็กต์ attribution
ตารางต่อไปนี้แสดงข้อมูลสำคัญบางส่วนที่คุณพบได้ในรายการ LoAF แต่ละรายการ
คีย์ออบเจ็กต์รายการ LoAF | ข้อมูล |
---|---|
duration
|
ระยะเวลาของเฟรมภาพเคลื่อนไหวที่ใช้เวลานานจนถึงเวลาที่เลย์เอาต์เสร็จสิ้น แต่ไม่รวมการวาดภาพและการคอมโพส |
blockingDuration
|
ระยะเวลาทั้งหมดในเฟรมที่เบราว์เซอร์ตอบสนองได้ช้าเนื่องจากมีงานที่ต้องใช้เวลานาน เวลาการบล็อกนี้อาจรวมถึงงานที่ใช้เวลานานในการเรียกใช้ JavaScript รวมถึงงานการแสดงผลที่ใช้เวลานานในเฟรมต่อๆ มา |
firstUIEventTimestamp
|
การประทับเวลาที่เหตุการณ์อยู่ในคิวระหว่างเฟรม มีประโยชน์ในการหาจุดเริ่มต้นของการหน่วงเวลาอินพุตของการโต้ตอบ |
startTime
|
การประทับเวลาเริ่มต้นของเฟรม |
renderStart
|
เมื่อเริ่มการเรนเดอร์เฟรม ซึ่งรวมถึงการเรียกกลับ requestAnimationFrame (และการเรียกกลับ ResizeObserver หากมี) แต่อาจเกิดขึ้นก่อนเริ่มงานสไตล์/เลย์เอาต์
|
styleAndLayoutStart
|
เมื่อเกิดการทำงานสไตล์/เลย์เอาต์ในเฟรม มีประโยชน์ในการหาระยะเวลาของงานสไตล์/เลย์เอาต์เมื่อพิจารณาการประทับเวลาอื่นๆ ที่มี |
scripts
|
อาร์เรย์ของรายการที่มีข้อมูลการระบุแหล่งที่มาของสคริปต์ซึ่งส่งผลต่อ INP ของหน้าเว็บ |
ข้อมูลทั้งหมดนี้บอกได้มากมายเกี่ยวกับสิ่งที่ทําให้การโต้ตอบช้า แต่อาร์เรย์ scripts
ที่รายการ LoAF แสดงควรเป็นสิ่งที่น่าสนใจเป็นพิเศษ
คีย์ออบเจ็กต์การระบุแหล่งที่มาของสคริปต์ | ข้อมูล |
---|---|
invoker
|
ผู้เรียกใช้ ซึ่งอาจแตกต่างกันไปตามประเภทตัวเรียกที่อธิบายไว้ในแถวถัดไป ตัวอย่างตัวเรียกใช้อาจเป็นค่าอย่างเช่น 'IMG#id.onload' , 'Window.requestAnimationFrame' หรือ 'Response.json.then' |
invokerType
|
ประเภทของผู้เรียกใช้ อาจเป็น 'user-callback' , 'event-listener' , 'resolve-promise' , 'reject-promise' , 'classic-script' หรือ 'module-script'
|
sourceURL
|
URL ของสคริปต์ที่เป็นต้นทางของเฟรมภาพเคลื่อนไหวที่ใช้เวลานาน |
sourceCharPosition
|
ตำแหน่งอักขระในสคริปต์ที่ระบุโดย sourceURL
|
sourceFunctionName
|
ชื่อของฟังก์ชันในสคริปต์ที่ระบุ |
แต่ละรายการในอาร์เรย์นี้มีข้อมูลที่แสดงในตารางนี้ ซึ่งจะให้ข้อมูลเกี่ยวกับสคริปต์ที่ทำให้เกิดปัญหาการโต้ตอบช้า และสาเหตุที่ทำให้เกิดปัญหา
วัดและระบุสาเหตุที่พบบ่อยของการโต้ตอบที่ช้า
เพื่อช่วยให้คุณทราบวิธีใช้ข้อมูลนี้ คู่มือนี้จะอธิบายวิธีใช้ข้อมูล LoAF ที่แสดงในไลบรารี web-vitals
เพื่อระบุสาเหตุที่ทําให้การโต้ตอบช้า
ระยะเวลาการประมวลผลนาน
ระยะเวลาการประมวลผลของการโต้ตอบคือเวลาที่ใช้ในการเรียกกลับของตัวแฮนเดิลเหตุการณ์ที่ลงทะเบียนของการโต้ตอบให้ทํางานจนเสร็จสมบูรณ์และการดำเนินการอื่นๆ ที่อาจเกิดขึ้นในระหว่างนั้น ไลบรารี Web Vitals จะแสดงระยะเวลาการประมวลผลสูงดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {processingDuration} = attribution; // 512.5
});
คุณอาจคิดว่าสาเหตุหลักที่ทำให้การโต้ตอบช้าคือโค้ดตัวแฮนเดิลเหตุการณ์ใช้เวลาในการเรียกใช้นานเกินไป แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป เมื่อยืนยันแล้วว่าปัญหานี้เกิดขึ้นจากสาเหตุนี้ ให้เจาะลึกเพิ่มเติมด้วยข้อมูล LoAF ดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {processingDuration} = attribution; // 512.5
// Get the longest script from LoAF covering `processingDuration`:
const loaf = attribution.longAnimationFrameEntries.at(-1);
const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];
if (script) {
// Get attribution for the long-running event handler:
const {invokerType} = script; // 'event-listener'
const {invoker} = script; // 'BUTTON#update.onclick'
const {sourceURL} = script; // 'https://example.com/app.js'
const {sourceCharPosition} = script; // 83
const {sourceFunctionName} = script; // 'update'
}
});
ดังที่เห็นในข้อมูลโค้ดด้านบน คุณสามารถทํางานกับข้อมูล LoAF เพื่อติดตามสาเหตุที่แน่ชัดที่อยู่เบื้องหลังการโต้ตอบที่มีค่าระยะเวลาการประมวลผลสูง ซึ่งรวมถึง
- องค์ประกอบและ Listener เหตุการณ์ที่ลงทะเบียนไว้
- ไฟล์สคริปต์และตําแหน่งของอักขระภายในไฟล์ซึ่งมีโค้ดตัวแฮนเดิลเหตุการณ์ที่ทำงานอยู่นาน
- ชื่อของฟังก์ชัน
ข้อมูลประเภทนี้มีคุณค่าอย่างยิ่ง คุณไม่จําเป็นต้องทํางานหนักเพื่อค้นหาว่าการโต้ตอบใดหรือตัวแฮนเดิลเหตุการณ์ใดที่ทำให้เกิดค่าระยะเวลาการประมวลผลสูง นอกจากนี้ เนื่องจากสคริปต์ของบุคคลที่สามมักจะลงทะเบียนตัวแฮนเดิลเหตุการณ์ของตนเอง คุณจึงสามารถระบุได้ว่าโค้ดของคุณเป็นสาเหตุของปัญหาหรือไม่ สําหรับโค้ดที่คุณควบคุมได้ คุณควรดูการเพิ่มประสิทธิภาพงานที่ใช้เวลานาน
ความล่าช้าในการป้อนข้อมูลนาน
แม้ว่าตัวแฮนเดิลเหตุการณ์ที่ทำงานอยู่นานจะพบได้ทั่วไป แต่ก็มีบางส่วนของการโต้ตอบที่ต้องพิจารณาด้วย ส่วนหนึ่งเกิดขึ้นก่อนระยะเวลาการประมวลผล ซึ่งเรียกว่าการหน่วงเวลาอินพุต ระยะเวลานี้นับตั้งแต่ที่ผู้ใช้เริ่มการโต้ตอบจนถึงเวลาที่การเรียกกลับของตัวแฮนเดิลเหตุการณ์เริ่มทํางาน และเกิดขึ้นเมื่อเธรดหลักประมวลผลงานอื่นอยู่แล้ว บิลด์การระบุแหล่งที่มาของไลบรารี Web Vitals สามารถบอกระยะเวลาของเวลาหน่วงของอินพุตสําหรับการโต้ตอบได้ ดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {inputDelay} = attribution; // 125.59439536
});
หากสังเกตเห็นว่าการโต้ตอบบางอย่างมีความล่าช้าในการป้อนข้อมูลสูง คุณจะต้องหาสาเหตุว่าเกิดอะไรขึ้นในหน้าเว็บขณะที่เกิดการโต้ตอบซึ่งทําให้เกิดความล่าช้าในการป้อนข้อมูลนาน และมักสรุปได้ว่าการโต้ตอบเกิดขึ้นขณะที่หน้าเว็บกําลังโหลดหรือหลังจากนั้น
เกิดระหว่างการโหลดหน้าเว็บใช่ไหม
เทรดหลักมักจะทำงานหนักที่สุดเมื่อหน้าเว็บกำลังโหลด ในระหว่างนี้ ระบบจะจัดคิวและประมวลผลงานทุกประเภท และหากผู้ใช้พยายามโต้ตอบกับหน้าเว็บขณะที่ระบบทํางานทั้งหมดนี้อยู่ การโต้ตอบอาจล่าช้า หน้าเว็บที่โหลด JavaScript จำนวนมากอาจเริ่มการคอมไพล์และประเมินสคริปต์ รวมถึงเรียกใช้ฟังก์ชันที่เตรียมหน้าเว็บให้พร้อมสําหรับการโต้ตอบของผู้ใช้ การดำเนินการนี้อาจรบกวนผู้ใช้หากผู้ใช้โต้ตอบขณะที่กิจกรรมนี้เกิดขึ้น และคุณสามารถดูได้ว่าผู้ใช้เว็บไซต์ของคุณโต้ตอบหรือไม่โดยทำดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {inputDelay} = attribution; // 125.59439536
// Get the longest script from the first LoAF entry:
const loaf = attribution.longAnimationFrameEntries[0];
const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];
if (script) {
// Invoker types can describe if script eval blocked the main thread:
const {invokerType} = script; // 'classic-script' | 'module-script'
const {sourceLocation} = script; // 'https://example.com/app.js'
}
});
หากคุณบันทึกข้อมูลนี้ในช่องและเห็นว่าการตอบสนองที่ล่าช้าสูงและประเภทผู้เรียกใช้คือ 'classic-script'
หรือ 'module-script'
แสดงว่าสคริปต์ในเว็บไซต์ใช้เวลานานในการประเมินและบล็อกเธรดหลักนานพอที่จะทำให้เกิดความล่าช้าในการโต้ตอบ คุณสามารถลดเวลาการบล็อกนี้ได้ด้วยการแยกสคริปต์ออกเป็นกลุ่มเล็กๆ เลื่อนการโหลดโค้ดที่ไม่ได้ใช้ในตอนแรกไปโหลดในภายหลัง และตรวจสอบเว็บไซต์เพื่อหาโค้ดที่ไม่ได้ใช้ซึ่งสามารถนำออกได้ทั้งหมด
เกิดหลังจากโหลดหน้าเว็บใช่ไหม
แม้ว่าความล่าช้าในการป้อนข้อมูลมักเกิดขึ้นขณะที่หน้าเว็บกำลังโหลด แต่ความล่าช้าดังกล่าวก็อาจเกิดขึ้นหลังจากหน้าเว็บโหลดเสร็จแล้วเช่นกัน เนื่องด้วยสาเหตุที่แตกต่างออกไป สาเหตุที่พบบ่อยของความล่าช้าในการป้อนข้อมูลหลังจากโหลดหน้าเว็บอาจเป็นโค้ดที่ทํางานเป็นระยะๆ เนื่องจากการเรียกใช้ setInterval
ก่อนหน้านี้ หรือแม้แต่การเรียกเหตุการณ์กลับที่รอคิวให้ทํางานก่อนหน้านี้และยังประมวลผลอยู่
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {inputDelay} = attribution; // 125.59439536
// Get the longest script from the first LoAF entry:
const loaf = attribution.longAnimationFrameEntries[0];
const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];
if (script) {
const {invokerType} = script; // 'user-callback'
const {sourceURL} = script; // 'https://example.com/app.js'
const {sourceCharPosition} = script; // 83
const {sourceFunctionName} = script; // 'update'
}
});
เช่นเดียวกับการแก้ปัญหาค่าระยะเวลาการประมวลผลสูง ความล่าช้าในการป้อนข้อมูลสูงเนื่องจากสาเหตุที่กล่าวถึงก่อนหน้านี้จะให้ข้อมูลการระบุแหล่งที่มาของสคริปต์โดยละเอียด อย่างไรก็ตาม สิ่งที่แตกต่างออกไปคือประเภทตัวเรียกจะเปลี่ยนแปลงตามลักษณะของงานที่ทําให้การโต้ตอบล่าช้า ดังนี้
'user-callback'
ระบุว่างานบล็อกมาจากsetInterval
,setTimeout
หรือแม้แต่requestAnimationFrame
'event-listener'
บ่งบอกว่างานการบล็อกมาจากอินพุตก่อนหน้าที่อยู่ในคิวและยังประมวลผลอยู่'resolve-promise'
และ'reject-promise'
หมายความว่างานการบล็อกมาจากงานที่ทำงานแบบไม่พร้อมกันซึ่งเริ่มต้นขึ้นก่อนหน้านี้ และได้รับการแก้ไขหรือถูกปฏิเสธเมื่อผู้ใช้พยายามโต้ตอบกับหน้าเว็บ ซึ่งทำให้การโต้ตอบล่าช้า
ไม่ว่าในกรณีใด ข้อมูลการระบุแหล่งที่มาของสคริปต์จะช่วยให้คุณทราบจุดที่จะเริ่มต้นค้นหา และช่วยให้ทราบว่าความล่าช้าในการป้อนข้อมูลเกิดจากโค้ดของคุณเองหรือสคริปต์ของบุคคลที่สาม
ความล่าช้าของงานนำเสนอนานมาก
ช่วงเวลาหน่วงของการแสดงผลคือระยะทางสุดท้ายของการโต้ตอบ และจะเริ่มขึ้นเมื่อตัวแฮนเดิลเหตุการณ์ของการโต้ตอบทำงานเสร็จสิ้นจนถึงจุดที่ระบบวาดเฟรมถัดไป ซึ่งเกิดขึ้นเมื่อการทํางานในตัวแฮนเดิลเหตุการณ์เนื่องจากการโต้ตอบเปลี่ยนสถานะภาพอินเทอร์เฟซผู้ใช้ เช่นเดียวกับระยะเวลาการประมวลผลและความล่าช้าในการป้อนข้อมูล คลัง Web Vitals สามารถบอกความล่าช้าของการแสดงผลสําหรับการโต้ตอบได้ ดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {presentationDelay} = attribution; // 113.32307691
});
หากคุณบันทึกข้อมูลนี้และพบว่าการนำเสนอมีความล่าช้าสูงสำหรับการโต้ตอบที่ส่งผลต่อ INP ของเว็บไซต์ สาเหตุอาจแตกต่างกันไป แต่สาเหตุ 2 ข้อที่ควรระวังมีดังนี้
การออกแบบและเลย์เอาต์ที่ราคาแพง
ความล่าช้าในการนำเสนอที่นานอาจเกิดจากการคำนวณสไตล์ใหม่และเลย์เอาต์ที่มีค่าใช้จ่ายสูง ซึ่งอาจเกิดจากสาเหตุหลายประการ เช่น เครื่องมือเลือก CSS ที่ซับซ้อนและDOM ขนาดใหญ่ คุณสามารถวัดระยะเวลาของการทำงานนี้ด้วยการกำหนดเวลา LoAF ที่แสดงในไลบรารี Web Vitals ดังนี้
import {onINP} from 'web-vitals/attribution';
onINP(({name, value, attribution}) => {
const {presentationDelay} = attribution; // 113.32307691
// Get the longest script from the last LoAF entry:
const loaf = attribution.longAnimationFrameEntries.at(-1);
const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];
// Get necessary timings:
const {startTime} = loaf; // 2120.5
const {duration} = loaf; // 1002
// Figure out the ending timestamp of the frame (approximate):
const endTime = startTime + duration; // 3122.5
// Get the start timestamp of the frame's style/layout work:
const {styleAndLayoutStart} = loaf; // 3011.17692309
// Calculate the total style/layout duration:
const styleLayoutDuration = endTime - styleAndLayoutStart; // 111.32307691
if (script) {
// Get attribution for the event handler that triggered
// the long-running style and layout operation:
const {invokerType} = script; // 'event-listener'
const {invoker} = script; // 'BUTTON#update.onclick'
const {sourceURL} = script; // 'https://example.com/app.js'
const {sourceCharPosition} = script; // 83
const {sourceFunctionName} = script; // 'update'
}
});
LoAF จะไม่บอกระยะเวลาของงานสไตล์และเลย์เอาต์สำหรับเฟรมหนึ่งๆ แต่จะให้ข้อมูลว่าเริ่มเมื่อใด เมื่อใช้การประทับเวลาเริ่มต้นนี้ คุณจะใช้ข้อมูลอื่นๆ จาก LoAF เพื่อคํานวณระยะเวลาที่แม่นยําของงานนั้นได้ โดยระบุเวลาสิ้นสุดของเฟรม แล้วลบการประทับเวลาเริ่มต้นของงานสไตล์และเลย์เอาต์ออกจากเวลาดังกล่าว
requestAnimationFrame
callback ที่ทำงานอยู่นาน
สาเหตุหนึ่งที่อาจทําให้เกิดความล่าช้าในการนําเสนอเป็นเวลานานคือมีงานมากเกินไปใน requestAnimationFrame
callback ระบบจะเรียกใช้เนื้อหาของคอลแบ็กนี้หลังจากที่ตัวแฮนเดิลเหตุการณ์ทำงานเสร็จแล้ว แต่ก่อนการประมวลผลสไตล์ใหม่และการจัดวาง
การเรียกกลับเหล่านี้อาจใช้เวลานานมากหากงานที่ทำภายในมีความซับซ้อน หากสงสัยว่าค่าความล่าช้าในการแสดงผลสูงเกิดจากงานที่คุณทํากับ requestAnimationFrame
ให้ใช้ข้อมูล LoAF ที่แสดงโดยไลบรารี Web Vitals เพื่อระบุสถานการณ์ต่อไปนี้
onINP(({name, value, attribution}) => {
const {presentationDelay} = attribution; // 543.1999999880791
// Get the longest script from the last LoAF entry:
const loaf = attribution.longAnimationFrameEntries.at(-1);
const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];
// Get the render start time and when style and layout began:
const {renderStart} = loaf; // 2489
const {styleAndLayoutStart} = loaf; // 2989.5999999940395
// Calculate the `requestAnimationFrame` callback's duration:
const rafDuration = styleAndLayoutStart - renderStart; // 500.59999999403954
if (script) {
// Get attribution for the event handler that triggered
// the long-running requestAnimationFrame callback:
const {invokerType} = script; // 'user-callback'
const {invoker} = script; // 'FrameRequestCallback'
const {sourceURL} = script; // 'https://example.com/app.js'
const {sourceCharPosition} = script; // 83
const {sourceFunctionName} = script; // 'update'
}
});
หากเห็นว่าเวลาในการเลื่อนเวลานำเสนอล่าช้าส่วนใหญ่อยู่ใน requestAnimationFrame
callback ให้ตรวจสอบว่างานที่ทําใน callback เหล่านี้จํากัดอยู่ที่การทํางานที่ทําให้อินเทอร์เฟซผู้ใช้ได้รับการอัปเดตจริง การทำงานอื่นๆ ที่ไม่ได้เกี่ยวข้องกับ DOM หรืออัปเดตสไตล์จะทำให้เกิดภาพเฟรมถัดไปล่าช้าโดยไม่จำเป็น ดังนั้นโปรดระมัดระวัง
บทสรุป
ข้อมูลภาคสนามเป็นแหล่งข้อมูลที่ดีที่สุดที่คุณสามารถใช้เพื่อทำความเข้าใจว่าการโต้ตอบใดทำให้เกิดปัญหาสําหรับผู้ใช้จริงในภาคสนาม การใช้เครื่องมือรวบรวมข้อมูลภาคสนาม เช่น ไลบรารี JavaScript ของ Web Vitals (หรือผู้ให้บริการ RUM) จะช่วยให้คุณมั่นใจมากขึ้นว่าอินเทอร์แอกชันใดมีปัญหามากที่สุด จากนั้นจึงจำลองอินเทอร์แอกชันที่มีปัญหาในห้องทดลอง แล้วจึงดำเนินการแก้ไข
รูปภาพหลักจาก Unsplash โดย Federico Respini