การตอบสนองต่อการโต้ตอบที่ไม่ดีทำให้เกิดความประทับใจที่ไม่ดีว่าหน้าเว็บช้าหรือถึงขั้นใช้งานไม่ได้เลย Interaction to Next Paint (INP) เป็นเมตริกที่อิงตาม Event Timing API โดยจะวัดการโต้ตอบที่แย่ที่สุด (ไม่รวมค่าผิดปกติบางค่า) เพื่อวัดการตอบสนองของหน้าเว็บ
การระบุสาเหตุของปัญหาหน้าเว็บไม่ตอบสนองอาจเป็นเรื่องยาก โดยเฉพาะอย่างยิ่งเมื่อขึ้นอยู่กับการโต้ตอบของผู้ใช้และสภาพแวดล้อม เช่น ความสามารถของอุปกรณ์และสภาพเครือข่าย ซึ่งทำให้วิเคราะห์ได้ยากกว่าเมื่อเทียบกับสถานการณ์ที่ทำซ้ำและคาดการณ์ได้มากกว่า เช่น การโหลดหน้าเว็บ ข้อมูลจากห้องปฏิบัติการจะจำลองสถานการณ์ของผู้ใช้จริงเพียงส่วนเล็กๆ เท่านั้น ดังนั้นการวัดสาเหตุที่ทำให้ INP ช้าในภาคสนามจึงเป็นสิ่งสำคัญ
Event Timing API ช่วยให้สามารถแบ่งระยะเวลา INP ออกเป็น 3 ส่วนย่อย ได้แก่ ความล่าช้าของอินพุต (การประมวลผลที่เกิดขึ้นแล้วเมื่อเกิดการโต้ตอบ) ระยะเวลาการประมวลผล (ความล่าช้าอันเป็นผลโดยตรงจากการโต้ตอบ) และความล่าช้าในการนำเสนอ (ความล่าช้าที่เกิดจากการแสดงผลเฟรมถัดไปหลังจากการโต้ตอบ) ซึ่งจะช่วยระบุว่าปัญหาอยู่ในโค้ดอื่นๆ, โค้ด JavaScript ของการโต้ตอบ หรือการอัปเดตการแสดงผลการประมวลผลของเบราว์เซอร์ตามลำดับ แทนที่จะข้ามไปยังโค้ดการโต้ตอบโดยตรง
คุณสามารถรวบรวมข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับ JavaScript, การคำนวณสไตล์ใหม่ และงานเลย์เอาต์ที่ทำให้การโต้ตอบล่าช้า การติดตามประสิทธิภาพแบบเต็มรูปแบบโดยใช้ JS Self-Profiling API เป็นโซลูชันที่ใช้ทรัพยากรมากซึ่งอาจทำให้เกิดปัญหาด้านประสิทธิภาพ Long Animation Frames API เป็น API ที่มีขนาดเล็กซึ่งสามารถใช้ในภาคสนามเพื่อระบุ JavaScript ที่ทำงานช้า และแยกความแตกต่างระหว่างการคำนวณสไตล์ใหม่และต้นทุนเลย์เอาต์ระหว่างการโต้ตอบ INP
- สไตล์และเลย์เอาต์ที่บังคับใช้ในระดับสคริปต์ (
forcedStyleDurationและforcedLayoutDuration): รายงานการคำนวณสไตล์ใหม่แบบซิงโครนัส (เช่น การเรียกใช้getComputedStyle()หลังจากการเปลี่ยนแปลง DOM) และเลย์เอาต์/การจัดเรียงใหม่ที่บังคับใช้ (เช่น การอ่านgetBoundingClientRect()หรือoffsetWidthหลังจากการเปลี่ยนแปลง) ภายในสคริปต์ที่ทำงานอยู่ระหว่างความล่าช้าของอินพุตหรือระยะเวลาการประมวลผล - สไตล์และเลย์เอาต์การแสดงผลระดับเฟรม (
styleDurationและlayoutDuration): รายงานเวลาที่ใช้ในการคำนวณสไตล์ใหม่เทียบกับการอัปเดตเลย์เอาต์ระหว่างการอัปเดตการแสดงผลของเฟรม ซึ่งช่วยอธิบายความล่าช้าในการนำเสนอที่สูง
การแยกความแตกต่างระหว่างการคํานวณสไตล์ใหม่กับเลย์เอาต์เป็นสิ่งสําคัญเนื่องจากมีสาเหตุของปัญหาและการแก้ไขที่แตกต่างกัน กล่าวคือ ระยะเวลาการคํานวณสไตล์ที่สูงบ่งชี้ถึงการจับคู่ตัวเลือก CSS ที่มีค่าใช้จ่ายสูงหรือการทำให้สไตล์ไม่ถูกต้องในวงกว้าง (แก้ไขโดยการลดความซับซ้อนของตัวเลือกหรือลดขอบเขตของกฎ) ในขณะที่ระยะเวลาการจัดเลย์เอาต์ที่สูงบ่งชี้ถึงการคํานวณเรขาคณิตที่มีค่าใช้จ่ายสูงหรือการจัดเลย์เอาต์แบบซิงโครนัสที่ไม่มีประสิทธิภาพ (แก้ไขโดยการจัดกลุ่มการอ่าน DOM ก่อนการเขียน ลดความซับซ้อนของโครงสร้าง DOM หรือใช้การกักกัน CSS)
วิธีการนำไปใช้งาน
การคำนวณ INP จาก Event Timing API แบบข้อมูลดิบนั้นซับซ้อนและมีรายละเอียดปลีกย่อยหลายอย่าง เราขอแนะนำให้คุณใช้เครื่องมือหรือไลบรารี RUM เพื่อรวบรวมข้อมูลนี้
web-vitals เป็นไลบรารีโอเพนซอร์สจาก Google ที่คำนวณ Core Web Vitals รวมถึง INP และยังมีส่วนย่อยและข้อมูลเฟรมของภาพเคลื่อนไหวที่ใช้เวลานานสำหรับการโต้ตอบ INP ด้วย
รับการระบุแหล่งที่มาสำหรับการโต้ตอบ INP โดยใช้ไลบรารี web-vitals
ไลบรารี web-vitals เป็นไลบรารีขนาดเล็กที่ใช้ในการวัด Core Web Vitals และเมตริกประสิทธิภาพอื่นๆ คุณสามารถใช้ฟังก์ชัน onINP() เพื่อระบุการโต้ตอบที่ช้าที่สุด และรวมข้อมูลเกี่ยวกับส่วนย่อยของ INP, สคริปต์ที่ดำเนินการระหว่างการโต้ตอบ รวมถึงระยะเวลาของสไตล์และเลย์เอาต์โดยใช้ Long Animation Frames API
// Use the attribution build to get Long Animation Frame data
// alongside the INP metric value.
import { onINP } from 'web-vitals/attribution';
onINP((metric) => {
const { attribution } = metric;
const longestScript = attribution.longestScript;
// Sum rendering-phase style and layout durations across all LoAF entries
// intersecting the INP interaction (primarily explains presentationDelay).
let renderStyleDuration = 0;
let renderLayoutDuration = 0;
for (const entry of attribution.longAnimationFrameEntries) {
renderStyleDuration += entry.styleDuration ?? 0;
renderLayoutDuration += entry.layoutDuration ?? 0;
}
// Beacon script, style, and layout attribution for the INP interaction,
// so you can identify the root cause in production.
navigator.sendBeacon(
'/analytics',
JSON.stringify({
name: 'INP',
value: metric.value,
// These fields give the INP subparts:
inputDelay: attribution.inputDelay,
presentationDelay: attribution.presentationDelay,
processingDuration: attribution.processingDuration,
interactionTarget: attribution.interactionTarget,
// These fields identify which script function was responsible
// for the longest processing during the INP interaction.
invokerType: longestScript?.entry?.invokerType,
sourceURL: longestScript?.entry?.sourceURL,
sourceFunctionName: longestScript?.entry?.sourceFunctionName,
sourceCharPosition: longestScript?.entry?.sourceCharPosition,
// subpart indicates which phase (input delay, processing, or
// presentation delay) the longest script overlapped with most.
subpart: longestScript?.subpart,
intersectingDuration: longestScript?.intersectingDuration,
// Synchronous style and layout work forced inside the longest script
// (with forcedStyleAndLayoutDuration as a combined fallback):
forcedStyleDuration: longestScript?.entry?.forcedStyleDuration,
forcedLayoutDuration: longestScript?.entry?.forcedLayoutDuration,
forcedStyleAndLayoutDuration: longestScript?.entry?.forcedStyleAndLayoutDuration,
// Rendering-phase style and layout work across the interaction's frames
// (with totalStyleAndLayoutDuration as a combined fallback):
renderStyleDuration,
renderLayoutDuration,
totalStyleAndLayoutDuration: attribution.totalStyleAndLayoutDuration
})
);
});
แนวทางปฏิบัติแนะนำ
- ควรใช้ส่วนย่อยของ INP ในตอนแรกเพื่อระบุว่าความล่าช้าเกิดจาก JavaScript ที่ทำงานอยู่แล้ว (ความล่าช้าของอินพุต) JavaScript ของตัวแฮนเดิลเหตุการณ์สำหรับการโต้ตอบ (ระยะเวลาการประมวลผล) หรือการแสดงผลที่ตามมา (ความล่าช้าในการนำเสนอ)
- ควรพยายามระบุ JavaScript ที่บล็อกมากที่สุดเป็นรายละเอียดเพิ่มเติม โดยเฉพาะอย่างยิ่งสำหรับความล่าช้าของอินพุตและระยะเวลาการประมวลผล
- ควรแยกความแตกต่างระหว่างการคำนวณสไตล์ใหม่ (
styleDuration,forcedStyleDuration) และเลย์เอาต์ (layoutDuration,forcedLayoutDuration) เมื่อวิเคราะห์ระยะเวลาการประมวลผลที่สูงหรือความล่าช้าในการนำเสนอ โดยเวลาในการคำนวณสไตล์ที่สูงบ่งชี้ถึงตัวเลือก CSS ที่มีค่าใช้จ่ายสูงหรือการทำให้เป็นโมฆะในวงกว้าง ส่วนเวลาในการจัดเลย์เอาต์ที่สูงบ่งชี้ถึงคอขวดของเรขาคณิต DOM หรือการจัดเลย์เอาต์แบบซิงโครนัสที่ไม่มีประสิทธิภาพ - ควรใช้ Long Animation Frames API เพื่อให้รายละเอียดเพิ่มเติมนี้แทนทางเลือกอื่นๆ เช่น JS Self-Profiling API ซึ่งมีค่าใช้จ่ายเพิ่มเติมเกี่ยวกับรันไทม์ที่สูงกว่า
- ควรใช้ไลบรารี
web-vitalsหากไม่มีโซลูชัน RUM อื่นๆ โดยสามารถระบุการโต้ตอบ INP และมีข้อมูลเกี่ยวกับส่วนย่อยและสคริปต์ที่ดำเนินการระหว่างการโต้ตอบ (โดยใช้ Long Animation Frames API) - ควรส่งข้อมูลที่จำเป็นกลับไปยังบริการวิเคราะห์แทนที่จะบันทึกไว้ในเครื่องเท่านั้น
การรองรับเบราว์เซอร์และกลยุทธ์สำรอง
Event Timing API พร้อมใช้งานในเบราว์เซอร์ที่ทันสมัยส่วนใหญ่ และจำเป็นสำหรับการคำนวณ INP และส่วนย่อยของ INP สำหรับเบราว์เซอร์ที่ไม่รองรับ API นี้ ระบบจะวัด INP ไม่ได้
Long Animation Frames API จะให้รายละเอียดเพิ่มเติม (ไม่บังคับ) คุณจึงใช้ได้อย่างปลอดภัยโดยไม่ต้องมีโฆษณาสำรอง ในกรณีส่วนใหญ่ โอกาสในการปรับปรุงประสิทธิภาพที่ระบุจะใช้กับเบราว์เซอร์อื่นๆ ได้ด้วย
หากเป้าหมายพื้นฐานรองรับ Long Animation Frames API (long-animation-frames) แต่ไม่รองรับพร็อพเพอร์ตี้ระยะเวลาของสไตล์และเลย์เอาต์แยกกัน (styleDuration และ layoutDuration ใน PerformanceLongAnimationFrameTiming หรือ forcedStyleDuration และ forcedLayoutDuration ใน PerformanceScriptTiming) ให้เปลี่ยนไปใช้เวลาของสไตล์และเลย์เอาต์รวมกัน ดังนี้
- ใช้
script.forcedStyleAndLayoutDurationในPerformanceScriptTimingสำหรับการทำงานของสไตล์และเลย์เอาต์ที่บังคับแบบซิงโครนัสภายในสคริปต์ - ใช้
metric.attribution.totalStyleAndLayoutDurationในweb-vitals/attribution(หรือคำนวณ(entry.paintTime || entry.startTime + entry.duration) - entry.styleAndLayoutStartในแต่ละรายการPerformanceLongAnimationFrameTiming) สำหรับงานสไตล์และเลย์เอาต์แบบผสม