ดูวิธีค้นหาการโต้ตอบที่ช้าในข้อมูลภาคสนามของเว็บไซต์เพื่อให้คุณพบโอกาสในการปรับปรุง Interaction to 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 ไม่สามารถบอกคุณได้ว่าอะไรเป็นสาเหตุของปัญหา มีโซลูชันการตรวจสอบผู้ใช้จริง (RUM) มากมายที่ช่วยให้คุณรวบรวมข้อมูลภาคสนามของคุณเองจากผู้ใช้เว็บไซต์เพื่อช่วยตอบคำถามดังกล่าว และตัวเลือกหนึ่งคือการรวบรวมข้อมูลภาคสนามด้วยตนเองโดยใช้ไลบรารี JavaScript ของ Web Vitals
รวบรวมข้อมูลภาคสนามด้วยไลบรารี JavaScript web-vitals
ไลบรารี JavaScript web-vitals เป็นสคริปต์ที่คุณโหลดในเว็บไซต์เพื่อรวบรวมข้อมูลภาคสนามจากผู้ใช้เว็บไซต์ได้ คุณสามารถใช้ไลบรารีนี้เพื่อบันทึกเมตริกต่างๆ รวมถึง 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*
|
เวลาตั้งแต่ที่ Listener เหตุการณ์แรกเริ่มทำงานเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้จนถึงเวลาที่การประมวลผล Listener เหตุการณ์ทั้งหมดเสร็จสิ้น |
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
|
เมื่อเริ่มการแสดงผลเฟรม ซึ่งรวมถึง Callback requestAnimationFrame (และ Callback ResizeObserver หากมี) แต่อาจเกิดขึ้นก่อนที่การทำงานด้านสไตล์/เลย์เอาต์จะเริ่มต้นขึ้น
|
styleAndLayoutStart
|
เมื่อมีการจัดสไตล์/เลย์เอาต์ในเฟรม ซึ่งอาจเป็นประโยชน์ในการพิจารณาความยาวของงานสไตล์/เลย์เอาต์เมื่อพิจารณาการประทับเวลาอื่นๆ ที่มีอยู่ |
scripts
|
อาร์เรย์ของรายการที่มีข้อมูลการระบุแหล่งที่มาของสคริปต์ซึ่งส่งผลต่อ INP ของหน้าเว็บ |
blockingDuration)
ข้อมูลทั้งหมดนี้บอกคุณได้มากมายเกี่ยวกับสาเหตุที่ทำให้การโต้ตอบช้า แต่คุณควรให้ความสนใจเป็นพิเศษกับอาร์เรย์ scripts ที่รายการ LoAF แสดงขึ้นมา
| คีย์ออบเจ็กต์การระบุแหล่งที่มาของสคริปต์ | ข้อมูล |
|---|---|
invoker
|
ผู้เรียกใช้ ซึ่งอาจแตกต่างกันไปตามประเภทผู้เรียกใช้ที่อธิบายไว้ในแถวถัดไป ตัวอย่างของ 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.toSorted((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 เหตุการณ์ที่ลงทะเบียนไว้
- ไฟล์สคริปต์และตำแหน่งอักขระภายในไฟล์ที่มีโค้ดตัวแฮนเดิลเหตุการณ์ที่ใช้เวลานาน
- ชื่อของฟังก์ชัน
ข้อมูลประเภทนี้มีค่ามาก คุณไม่จำเป็นต้องทำงานหนักเพื่อค้นหาว่าการโต้ตอบใดหรือตัวแฮนเดิลเหตุการณ์ใดที่ทำให้ค่าระยะเวลาการประมวลผลสูงอีกต่อไป นอกจากนี้ เนื่องจากสคริปต์ของบุคคลที่สามมักจะลงทะเบียนเครื่องมือจัดการเหตุการณ์ของตนเองได้ คุณจึงระบุได้ว่าโค้ดของคุณเป็นสาเหตุหรือไม่ สำหรับโค้ดที่คุณควบคุมได้ คุณจะต้องพิจารณาการเพิ่มประสิทธิภาพงานที่ใช้เวลานาน
ความล่าช้าของอินพุตที่นาน
แม้ว่าตัวแฮนเดิลเหตุการณ์ที่ทำงานเป็นเวลานานจะเป็นเรื่องปกติ แต่ก็ยังมีส่วนอื่นๆ ของการโต้ตอบที่ต้องพิจารณา ส่วนแรกจะเกิดขึ้นก่อนระยะเวลาการประมวลผล ซึ่งเรียกว่าความล่าช้าของอินพุต ซึ่งเป็นระยะเวลาตั้งแต่ที่ผู้ใช้เริ่มการโต้ตอบจนถึงช่วงเวลาที่ Callback ของตัวแฮนเดิลเหตุการณ์เริ่มทำงาน และเกิดขึ้นเมื่อเทรดหลักกำลังประมวลผลงานอื่นอยู่แล้ว บิลด์การระบุแหล่งที่มาของไลบรารี 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.toSorted((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 ก่อนหน้านี้ หรือแม้แต่ Callback ของเหตุการณ์ที่อยู่ในคิวให้ทำงานก่อนหน้านี้และยังคงประมวลผลอยู่
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.toSorted((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 ของเว็บไซต์ สาเหตุอาจแตกต่างกันไป แต่สาเหตุที่ควรระวังมีดังนี้
การจัดสไตล์และเลย์เอาต์ที่มีค่าใช้จ่ายสูง
ความล่าช้าในการแสดงผลที่นานอาจเกิดจากการคำนวณสไตล์ใหม่และงานเลย์เอาต์ที่มีค่าใช้จ่ายสูง ซึ่งเกิดจากสาเหตุหลายประการ เช่น ตัวเลือก 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.toSorted((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.toSorted((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'
}
});
หากคุณเห็นว่าเวลาส่วนใหญ่ของความล่าช้าในการนำเสนอใช้ไปกับ Callback requestAnimationFrame ให้ตรวจสอบว่างานที่คุณทำใน Callback เหล่านี้จำกัดเฉพาะงานที่ส่งผลให้เกิดการอัปเดตอินเทอร์เฟซผู้ใช้จริง งานอื่นๆ ที่ไม่ได้แตะ DOM หรืออัปเดตสไตล์จะทำให้เฟรมถัดไปแสดงผลล่าช้าโดยไม่จำเป็น ดังนั้นโปรดระมัดระวัง
บทสรุป
ข้อมูลภาคสนามเป็นแหล่งข้อมูลที่ดีที่สุดที่คุณสามารถใช้เพื่อทำความเข้าใจว่าการโต้ตอบใดเป็นปัญหาสำหรับผู้ใช้จริงในภาคสนาม การใช้เครื่องมือเก็บรวบรวมข้อมูลภาคสนาม เช่น ไลบรารี JavaScript ของ web-vitals (หรือผู้ให้บริการ RUM) จะช่วยให้คุณมั่นใจมากขึ้นว่าการโต้ตอบใดมีปัญหามากที่สุด จากนั้นจึงจำลองการโต้ตอบที่มีปัญหาในห้องทดลองเพื่อแก้ไขปัญหาต่อไป