API เฟรมภาพเคลื่อนไหวแบบยาว

Long Animation Frames API (Lo-Af ออกเสียง LoAF) เป็นการอัปเดต Long Tasks API เพื่อให้เข้าใจการอัปเดตอินเทอร์เฟซผู้ใช้ (UI) ที่ช้าได้ดียิ่งขึ้น วิธีนี้มีประโยชน์ในการระบุเฟรมภาพเคลื่อนไหวที่ช้าซึ่งมีแนวโน้มที่จะส่งผลต่อเมตริกการโต้ตอบกับ Next Paint (INP) ของเมตริก Core Web Vitals ซึ่งวัดการตอบสนอง หรือเพื่อระบุการกระตุกอื่นๆ ของ UI ที่ส่งผลต่อความราบรื่น

สถานะของ API

การรองรับเบราว์เซอร์

  • Chrome: 123
  • ขอบ: 123
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

หลังจากช่วงทดลองใช้จากต้นทางจาก Chrome 116 เป็น Chrome 122 ทาง LoAF API ได้จัดส่งจาก Chrome 123

ความเป็นมา: Long Tasks API

การรองรับเบราว์เซอร์

  • Chrome: 58
  • ขอบ: 79
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

Long Animation Frames API เป็นอีกทางเลือกหนึ่งของ Long Tasks API ซึ่งมีให้ใช้งานใน Chrome มาสักระยะหนึ่งแล้ว (ตั้งแต่ Chrome 58) Long Task API จะให้คุณตรวจสอบงานที่ใช้เวลานานซึ่งเป็นงานที่มีการใช้เทรดหลักเป็นเวลาตั้งแต่ 50 มิลลิวินาทีขึ้นไป ตามที่ชื่อระบุไว้ คุณสามารถตรวจสอบงานที่ใช้เวลานานได้โดยใช้อินเทอร์เฟซ PerformanceLongTaskTiming ที่มี PeformanceObserver ดังนี้

const observer = new PerformanceObserver((list) => {
  console.log(list.getEntries());
});

observer.observe({ type: 'longtask', buffered: true });

งานที่ใช้เวลานานอาจก่อให้เกิดปัญหาเกี่ยวกับการตอบสนอง หากผู้ใช้พยายามโต้ตอบกับหน้าเว็บ เช่น คลิกที่ปุ่มหรือเปิดเมนู แต่เทรดหลักจัดการกับงานที่ใช้เวลานานอยู่แล้ว การโต้ตอบของผู้ใช้จะล่าช้าโดยรอให้งานนั้นเสร็จสิ้น

เรามักจะแนะนำให้แบ่งงานที่ใช้เวลานานเพื่อปรับปรุงการตอบสนอง หากงานที่ใช้เวลานานถูกแบ่งออกเป็นชุดงานเล็กๆ หลายงาน ก็อาจช่วยให้ระบบดำเนินงานที่สำคัญระหว่างงานได้มากขึ้นเพื่อหลีกเลี่ยงความล่าช้าอย่างมากในการตอบกลับการโต้ตอบ

ดังนั้นเมื่อพยายามปรับปรุงการตอบสนอง ความพยายามแรกจึงมักจะเรียกใช้การติดตามประสิทธิภาพและพิจารณางานที่ใช้เวลานาน ซึ่งอาจดำเนินการผ่านเครื่องมือตรวจสอบที่ทำงานในห้องทดลอง เช่น Lighthouse (ซึ่งมีการตรวจสอบหลีกเลี่ยงงานในเทรดหลักที่ใช้เวลานาน) หรือโดยการดูงานที่ใช้เวลานานในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

การทดสอบในห้องทดลองมักเป็นจุดเริ่มต้นที่ไม่ดีในการระบุปัญหาด้านการตอบสนอง เนื่องจากเครื่องมือเหล่านี้อาจไม่รวมการโต้ตอบ แต่จริงๆ แล้วก็เป็นเพียงกลุ่มเล็กๆ ในการโต้ตอบที่เป็นไปได้ โดยหลักการแล้ว คุณควรวัดสาเหตุของการโต้ตอบที่ช้าในฟิลด์

ข้อบกพร่องของ Long Tasks API

การวัดงานที่ใช้เวลานานในภาคสนามโดยใช้ Performance Observer จะค่อนข้างมีประโยชน์เท่านั้น แต่ในความเป็นจริงแล้ว ระบบก็ไม่ได้ให้ข้อมูลมากนักนอกเหนือจากข้อเท็จจริงที่ว่างานหนึ่งเกิดขึ้นแล้ว และใช้เวลานานเท่าใด

เครื่องมือตรวจสอบผู้ใช้จริง (RUM) มักใช้รูปแบบนี้เพื่อระบุจำนวนหรือระยะเวลาของงานที่ใช้เวลานาน หรือระบุว่าหน้าใดเป็นหน้าที่ของงานนั้น แต่ไม่มีรายละเอียดสำคัญว่าสิ่งใดทำให้เกิดงานที่ใช้เวลานาน จึงเป็นการใช้งานที่จำกัด Long Tasks API มีเฉพาะรูปแบบการระบุแหล่งที่มาพื้นฐาน ซึ่งดีที่สุดจะให้ข้อมูลคอนเทนเนอร์ที่มีงานที่ใช้เวลานานเกิดขึ้นเท่านั้น (เอกสารระดับบนสุดหรือ <iframe>) แต่จะไม่ระบุสคริปต์หรือฟังก์ชันที่เรียกใช้รูปแบบดังกล่าว ดังที่แสดงในรายการทั่วไป

{
  "name": "unknown",
  "entryType": "longtask",
  "startTime": 31.799999997019768,
  "duration": 136,
  "attribution": [
    {
      "name": "unknown",
      "entryType": "taskattribution",
      "startTime": 0,
      "duration": 0,
      "containerType": "window",
      "containerSrc": "",
      "containerId": "",
      "containerName": ""
    }
  ]
}

นอกจากนี้ Long Tasks API ยังเป็นมุมมองที่ไม่สมบูรณ์ เนื่องจากอาจยกเว้นงานที่สำคัญบางอย่างด้วย การอัปเดตบางอย่าง เช่น การแสดงผล จะเกิดขึ้นในงานแยกต่างหากซึ่งควรรวมอยู่กับการดำเนินการก่อนหน้าซึ่งทำให้การอัปเดตนั้นวัด "งานทั้งหมด" ได้อย่างแม่นยำ สำหรับการโต้ตอบนั้น โปรดดูรายละเอียดข้อจำกัดของการพึ่งพางานเพิ่มเติมที่หัวข้อหัวข้อ "งานสำคัญที่ขาดช่วงใด" ของคำอธิบาย

ปัญหาสุดท้ายคือการวัดงานที่ใช้เวลานานจะรายงานเฉพาะงานเดี่ยวๆ ที่ใช้เวลานานกว่าขีดจำกัด 50 มิลลิวินาทีเท่านั้น เฟรมภาพเคลื่อนไหวอาจประกอบด้วยงานหลายๆ รายการที่มีขนาดเล็กกว่าขีดจำกัด 50 มิลลิวินาทีนี้ แต่ก็ยังบล็อกความสามารถในการแสดงผลของเบราว์เซอร์รวมกันอยู่

API เฟรมภาพเคลื่อนไหวแบบยาว

การรองรับเบราว์เซอร์

  • Chrome: 123
  • ขอบ: 123
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

Long Animation Frames API (LoAF) เป็น API ใหม่ที่พยายามแก้ไขจุดบกพร่องบางอย่างของ Long Tasks API เพื่อให้นักพัฒนาซอฟต์แวร์ได้รับข้อมูลเชิงลึกที่นำไปใช้ได้จริงมากขึ้นเพื่อช่วยแก้ไขปัญหาด้านการตอบสนองและปรับปรุง INP

การตอบสนองที่ดีหมายถึงหน้าเว็บตอบสนองต่อการโต้ตอบกับหน้าเว็บอย่างรวดเร็ว ซึ่งรวมถึงความสามารถในการระบายสีการอัปเดตที่ผู้ใช้ต้องการอย่างทันท่วงที และหลีกเลี่ยงการบล็อกการอัปเดตเหล่านี้ไม่ให้เกิดขึ้น สำหรับ INP เราขอแนะนำให้ตอบกลับไม่เกิน 200 มิลลิวินาที แต่สำหรับการอัปเดตอื่นๆ (เช่น ภาพเคลื่อนไหว) แม้จะยาวเกินไปก็ตาม

Long Animation Frames API เป็นอีกทางเลือกหนึ่งในการวัดงานการบล็อก ลองวัดเฟรมภาพเคลื่อนไหวขนาดยาวแทนการวัดงานแต่ละงานไปพร้อมๆ กับที่ Long Animation Frames API เป็นชื่อแนะนำ เฟรมภาพเคลื่อนไหวที่ยาวคือเวลาที่การอัปเดตการแสดงผลล่าช้าไปเกินกว่า 50 มิลลิวินาที (เท่ากับเกณฑ์ของ Long Tasks API)

เฟรมภาพเคลื่อนไหวแบบยาวสังเกตได้ในลักษณะที่คล้ายกันกับงานที่ใช้เวลานานโดยใช้ PerformanceObserver แต่จะดูประเภท long-animation-frame แทน ดังนี้

const observer = new PerformanceObserver((list) => {
  console.log(list.getEntries());
});

observer.observe({ type: 'long-animation-frame', buffered: true });

คุณจะค้นหาเฟรมภาพเคลื่อนไหวขนาดยาวก่อนหน้าจากไทม์ไลน์ประสิทธิภาพได้ด้วย โดยทำดังนี้

const loafs = performance.getEntriesByType('long-animation-frame');

อย่างไรก็ตาม จะมี maxBufferSize สําหรับรายการประสิทธิภาพ เมื่อเลิกใช้รายการที่ใหม่กว่า ดังนั้นแนวทาง PerformanceObserver จึงเป็นวิธีการที่แนะนํา ขนาดบัฟเฟอร์ long-animation-frame ตั้งไว้ที่ 200 เท่ากับของ long-tasks

ข้อดีของการดูที่กรอบแทนที่จะเป็นงาน

ข้อดีที่สำคัญของการดูสิ่งนี้จากมุมมองเฟรมแทนที่จะเป็นมุมมองของงานคือ ภาพเคลื่อนไหวขนาดยาวสามารถสร้างจากงานจำนวนเท่าใดก็ได้ที่สะสมเป็นเฟรมภาพเคลื่อนไหวที่ยาว วิธีนี้เป็นการแก้ไขปัญหาสุดท้ายที่กล่าวไว้ก่อนหน้านี้ ซึ่งก็คือผลรวมของงานที่บล็อกการแสดงผลจำนวนน้อยก่อนที่เฟรมภาพเคลื่อนไหวอาจไม่แสดงโดย Long Tasks API

ประโยชน์อีกข้อหนึ่งของมุมมองทางเลือกนี้ในงานยาวคือ ความสามารถในการแสดงรายละเอียดเวลาของทั้งเฟรม LoAF จะมีรายละเอียดเพิ่มเติมของส่วนต่างๆ ของระยะเวลาของเฟรม แทนที่จะใส่แค่ startTime และ duration อย่างเช่น Long Tasks API เท่านั้น

  • startTime: เวลาเริ่มต้นของเฟรมภาพเคลื่อนไหวที่ยาวซึ่งสัมพันธ์กับเวลาเริ่มต้นของการนำทาง
  • duration: ระยะเวลาของเฟรมภาพเคลื่อนไหวที่ยาว (ไม่รวมเวลานำเสนอ)
  • renderStart: เวลาเริ่มต้นของรอบการแสดงผล ซึ่งรวมถึง requestAnimationFrame Callback, การคำนวณรูปแบบและเลย์เอาต์, ปรับขนาดตัวสังเกตการณ์ และ Callback ผู้สังเกตการณ์ทางแยก
  • styleAndLayoutStart: จุดเริ่มต้นของระยะเวลาที่นำไปใช้ในการคำนวณรูปแบบและเลย์เอาต์
  • firstUIEventTimestamp: เวลาที่เกิดเหตุการณ์ UI ครั้งแรก (เมาส์/แป้นพิมพ์ และอื่นๆ) ที่ต้องจัดการในช่วงระยะเวลาของเฟรมนี้
  • blockingDuration: ระยะเวลาเป็นมิลลิวินาทีที่เฟรมภาพเคลื่อนไหวถูกบล็อก

การประทับเวลาเหล่านี้ช่วยให้แบ่งเฟรมภาพเคลื่อนไหวขนาดยาวออกเป็นช่วงเวลาได้

ช่วงเวลา การคำนวณ
เวลาเริ่มต้น startTime
เวลาสิ้นสุด startTime + duration
ระยะเวลาการทำงาน renderStart ? renderStart - startTime : duration
ระยะเวลาการแสดงผล renderStart ? (startTime + duration) - renderStart: 0
แสดงผล: ระยะเวลาก่อนเลย์เอาต์ styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0
แสดงผล: รูปแบบและระยะเวลาของเลย์เอาต์ styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับแต่ละช่วงเวลา โปรดดูคำอธิบาย ซึ่งจะให้รายละเอียดอย่างละเอียดว่ากิจกรรมใดส่งผลให้เกิดเฟรมภาพเคลื่อนไหวขนาดยาว

การระบุแหล่งที่มาที่ดียิ่งขึ้น

รายการประเภท long-animation-frame มีข้อมูลการระบุแหล่งที่มาที่ดีขึ้นของแต่ละสคริปต์ที่ส่งผลต่อเฟรมภาพเคลื่อนไหวที่ใช้เวลานาน

ในทำนองเดียวกับ Long Tasks API ข้อมูลนี้จะอยู่ในอาร์เรย์ของรายการการระบุแหล่งที่มา ซึ่งมีรายละเอียดดังต่อไปนี้

  • ทั้ง name และ EntryType จะแสดงผล script
  • invoker ที่สื่อความหมาย ซึ่งระบุวิธีเรียกใช้สคริปต์ (เช่น 'IMG#id.onload', 'Window.requestAnimationFrame' หรือ 'Response.json.then')
  • invokerType ของจุดแรกเข้าของสคริปต์:
    • user-callback: Callback ที่รู้จักซึ่งลงทะเบียนจาก API ของแพลตฟอร์มเว็บ (เช่น setTimeout, requestAnimationFrame)
    • event-listener: Listener เหตุการณ์แพลตฟอร์ม (เช่น click, load, keyup)
    • resolve-promise: ผู้จัดการคำมั่นสัญญาของแพลตฟอร์ม (เช่น fetch() โปรดทราบว่าในกรณีที่เป็นสัญญา เครื่องจัดการทั้งหมดของสัญญาเดียวกันจะปนกันเป็น "สคริปต์" เดียว").
    • reject-promise: ตาม resolve-promise แต่สำหรับการปฏิเสธ
    • classic-script: การประเมินสคริปต์ (เช่น <script> หรือ import())
    • module-script: เหมือนกับ classic-script แต่สำหรับสคริปต์โมดูล
  • แยกข้อมูลเวลาสำหรับสคริปต์นั้น:
    • startTime: เวลาที่เรียกใช้ฟังก์ชันรายการ
    • duration: ระยะเวลาระหว่าง startTime ถึงเมื่อคิว Microtask ลำดับถัดไปประมวลผลเสร็จ
    • executionStart: เวลาหลังจากการคอมไพล์
    • forcedStyleAndLayoutDuration: เวลาทั้งหมดที่ใช้ในการประมวลผลเลย์เอาต์และสไตล์แบบบังคับภายในฟังก์ชันนี้ (ดูการจํากัด)
    • pauseDuration: เวลาทั้งหมดที่ใช้ใน "การหยุดชั่วคราว" การดำเนินการแบบซิงโครนัส (การแจ้งเตือน, XHR แบบซิงโครนัส)
  • รายละเอียดแหล่งที่มาของสคริปต์:
    • sourceURL: ชื่อทรัพยากรของสคริปต์ (หรือเว้นว่างไว้หากไม่พบ)
    • sourceFunctionName: ชื่อฟังก์ชันของสคริปต์ หากมี (หรือเว้นว่างไว้หากไม่พบ)
    • sourceCharPosition: ตำแหน่งของอักขระสคริปต์ (หากมี) (หรือ -1 หากไม่พบ)
  • windowAttribution: คอนเทนเนอร์ (เอกสารระดับบนสุดหรือ <iframe>) ที่เกิดเฟรมของภาพเคลื่อนไหวแบบยาว
  • window: การอ้างอิงไปยังหน้าต่างต้นทางเดียวกัน

ในกรณีที่ระบุไว้ รายการต้นฉบับจะช่วยให้นักพัฒนาซอฟต์แวร์ทราบอย่างแน่ชัดว่าสคริปต์แต่ละรายการในเฟรมภาพเคลื่อนไหวขนาดยาวมีการเรียกอย่างไร จนถึงตำแหน่งอักขระในสคริปต์การเรียกใช้ ซึ่งจะให้ตำแหน่งที่แน่นอนในทรัพยากร JavaScript ที่ทำให้เกิดเฟรมภาพเคลื่อนไหวยาว

ตัวอย่างรายการประสิทธิภาพ long-animation-frame

ตัวอย่างรายการประสิทธิภาพ long-animation-frame ที่สมบูรณ์ ซึ่งมีสคริปต์เดียว มีดังนี้

{
  "blockingDuration": 0,
  "duration": 60,
  "entryType": "long-animation-frame",
  "firstUIEventTimestamp": 11801.099999999627,
  "name": "long-animation-frame",
  "renderStart": 11858.800000000745,
  "scripts": [
    {
      "duration": 45,
      "entryType": "script",
      "executionStart": 11803.199999999255,
      "forcedStyleAndLayoutDuration": 0,
      "invoker": "DOMWindow.onclick",
      "invokerType": "event-listener",
      "name": "script",
      "pauseDuration": 0,
      "sourceURL": "https://web.dev/js/index-ffde4443.js",
      "sourceFunctionName": "myClickHandler",
      "sourceCharPosition": 17796,
      "startTime": 11803.199999999255,
      "window": [Window object],
      "windowAttribution": "self"
    }
  ],
  "startTime": 11802.400000000373,
  "styleAndLayoutStart": 11858.800000000745
}

ดังที่เห็นได้จากข้อมูลนี้ ทำให้เว็บไซต์มีข้อมูลจำนวนมากผิดปกติเพื่อให้เข้าใจสาเหตุของการอัปเดตการแสดงผลช้า

ใช้ Long Animation Frames API ในช่องดังกล่าว

แม้ว่าเครื่องมืออย่าง Chrome DevTools และ Lighthouse จะมีประโยชน์สำหรับการค้นหาและทำให้เกิดปัญหาซ้ำ แต่เป็นเครื่องมือในห้องทดลองที่อาจพลาดแง่มุมที่สำคัญของประสบการณ์ของผู้ใช้ที่มีเฉพาะข้อมูลภาคสนามเท่านั้น

Long Animation Frames API ออกแบบมาเพื่อใช้ในฟิลด์เพื่อรวบรวมข้อมูลบริบทที่สำคัญสำหรับการโต้ตอบของผู้ใช้ที่ Long Tasks API ทำไม่ได้ ซึ่งจะช่วยให้คุณระบุและจำลองปัญหาเกี่ยวกับการโต้ตอบที่คุณอาจไม่พบ

ฟีเจอร์ที่ตรวจพบการรองรับ Long Animation Frames API

คุณใช้โค้ดต่อไปนี้เพื่อทดสอบว่าระบบรองรับ API หรือไม่

if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
  // Monitor LoAFs
}

กรณีการใช้งานที่ชัดเจนที่สุดสำหรับ Long Animation Frames API คือการช่วยวิเคราะห์และแก้ไขปัญหา Interaction to Next Paint (INP) และนั่นเป็นเหตุผลหลักอย่างหนึ่งที่ทีม Chrome พัฒนา API นี้ INP ที่ดีคือตอบสนองการโต้ตอบทั้งหมดภายในไม่เกิน 200 มิลลิวินาทีตั้งแต่การโต้ตอบจนกว่าการแสดงผลเฟรมจะแสดง และเนื่องจาก Long Animation Frames API วัดเฟรมทั้งหมดที่ใช้เวลา 50 มิลลิวินาทีขึ้นไป, INP ที่มีปัญหาส่วนใหญ่ควรมีข้อมูล LoAF เพื่อช่วยคุณวินิจฉัยการโต้ตอบเหล่านั้น

"INP LoAF" คือ LoAF ซึ่งมีการโต้ตอบ INP ดังที่แสดงในแผนภาพต่อไปนี้

วันที่ ตัวอย่างของเฟรมภาพเคลื่อนไหวขนาดยาวในหน้าเว็บโดยไฮไลต์ INP LoAF
หน้าเว็บอาจมี LoAF จำนวนมาก ซึ่งหนึ่งในนั้นเกี่ยวข้องกับการโต้ตอบของ INP

ในบางกรณี เหตุการณ์ INP อาจครอบคลุม LoAF 2 ส่วน โดยปกติแล้วหากการโต้ตอบเกิดขึ้นหลังจากที่เฟรมเริ่มส่วนการแสดงภาพของเฟรมก่อนหน้า และตัวแฮนเดิลเหตุการณ์ที่ประมวลผลในเฟรมถัดไป มีดังนี้

วันที่ ตัวอย่างของเฟรมภาพเคลื่อนไหวขนาดยาวในหน้าเว็บโดยไฮไลต์ INP LoAF
หน้าเว็บอาจมี LoAF จำนวนมาก ซึ่งหนึ่งในนั้นเกี่ยวข้องกับการโต้ตอบของ INP

และในบางกรณีที่มีโอกาสเกิดขึ้นได้น้อยมาก อาจใช้ LoAF มากกว่า 2 จุด

การบันทึกข้อมูล LoAF ที่เชื่อมโยงกับการโต้ตอบ INP ช่วยให้คุณได้รับข้อมูลเพิ่มเติมเกี่ยวกับการโต้ตอบ INP เพื่อช่วยในการวิเคราะห์ ซึ่งจะมีประโยชน์อย่างยิ่งในการทำความเข้าใจเกี่ยวกับความล่าช้าของอินพุต เนื่องจากคุณจะดูได้ว่าสคริปต์อื่นๆ ใดกำลังทำงานอยู่ในเฟรมนั้น

นอกจากนี้ คุณควรทำความเข้าใจเกี่ยวกับระยะเวลาการประมวลผลและความล่าช้าของการนำเสนอที่ไม่ได้อธิบายด้วย หากตัวแฮนเดิลเหตุการณ์ไม่ได้สร้างค่าที่เห็นอีกครั้งเนื่องจากสคริปต์อื่นๆ อาจทำงานให้กับผู้ใช้ซึ่งอาจไม่ได้รวมอยู่ในการทดสอบของคุณเอง

ไม่มี API โดยตรงที่จะลิงก์รายการ INP กับรายการหรือ LoAF ที่เกี่ยวข้อง แต่จะทําได้ในโค้ดโดยการเปรียบเทียบเวลาเริ่มต้นและเวลาสิ้นสุดของแต่ละรายการ (ดูสคริปต์ตัวอย่าง WhyNp)

ไลบรารี web-vitals ประกอบด้วย LoAF ทั้งหมดที่ทับซ้อนกันในพร็อพเพอร์ตี้ longAnimationFramesEntries ของอินเทอร์เฟซการระบุแหล่งที่มา INP จากเวอร์ชัน 4

เมื่อลิงก์รายการหรือข้อมูลใน LoAF แล้ว คุณสามารถรวมข้อมูลด้วยการระบุแหล่งที่มา INP ออบเจ็กต์ scripts มีข้อมูลที่เป็นประโยชน์มากที่สุดอยู่บางส่วนเนื่องจากสามารถแสดงสิ่งอื่นๆ ที่ทำงานอยู่ในเฟรมเหล่านั้น ดังนั้นการบีคอนกลับมาที่บริการข้อมูลวิเคราะห์จึงช่วยให้คุณเข้าใจมากขึ้นถึงสาเหตุที่การโต้ตอบล่าช้า

การรายงาน LoAF สำหรับการโต้ตอบ INP เป็นวิธีที่ดีในการค้นหาปัญหาการโต้ตอบที่เร่งด่วนที่สุดในหน้าเว็บ ผู้ใช้แต่ละรายอาจโต้ตอบกับหน้าเว็บของคุณแตกต่างกันและมีข้อมูลการระบุแหล่งที่มา INP ในปริมาณที่เพียงพอ ปัญหาที่อาจเกิดขึ้นจำนวนหนึ่งจะรวมอยู่ในข้อมูลการระบุแหล่งที่มา INP ซึ่งจะช่วยให้คุณจัดเรียงสคริปต์ตามปริมาณเพื่อดูว่าสคริปต์ใดสัมพันธ์กับ INP ที่ช้า

รายงานข้อมูลภาพเคลื่อนไหวแบบยาวเพิ่มเติมกลับไปยังปลายทาง Analytics

ข้อเสียอย่างหนึ่งในการดูเฉพาะ INP LoAF ก็คือคุณอาจพลาดการปรับปรุงในด้านอื่นๆ ที่อาจทำให้เกิดปัญหา INP ในอนาคต ซึ่งอาจนำไปสู่ความรู้สึกว่าตัวเองต้องไล่ตามปัญหาที่คุณแก้ไขปัญหา INP ซึ่งคาดว่าจะได้รับการปรับปรุงครั้งใหญ่ แต่การพบการโต้ตอบที่ช้าที่สุดในลำดับถัดไปก็ดีกว่าเพียงเล็กน้อยเท่านั้น ดังนั้น INP ของคุณจึงไม่ดีขึ้นมากนัก

ดังนั้นแทนที่จะเน้นดูที่ INP LoAF เพียงอย่างเดียว คุณอาจต้องการพิจารณา LoAF ทั้งหมดตลอดอายุการใช้งานหน้าเว็บ

วันที่ หน้าเว็บที่มี LoAF จำนวนมาก ซึ่งบางส่วนเกิดขึ้นระหว่างการโต้ตอบแม้ว่าจะไม่ใช่การโต้ตอบ INP ก็ตาม
การดู LoAF ทั้งหมดจะช่วยระบุปัญหา INP ในอนาคตได้

อย่างไรก็ตาม รายการ LoAF แต่ละรายการจะมีข้อมูลจำนวนมาก คุณจึงน่าจะไม่ต้องบีคอนกลับไปทั้งหมด คุณจะต้องจำกัดการวิเคราะห์เฉพาะ LoAF บางส่วนหรือบางข้อมูลแทน

รูปแบบที่แนะนำบางส่วน ได้แก่

รูปแบบใดต่อไปนี้ที่เหมาะกับคุณที่สุด ขึ้นอยู่กับว่าคุณอยู่ได้ไกลแค่ไหนในการเพิ่มประสิทธิภาพ และเฟรมภาพเคลื่อนไหวมีความยาวเท่าใด สำหรับเว็บไซต์ที่ไม่เคยเพิ่มประสิทธิภาพเพื่อการตอบสนองอย่างรวดเร็วมาก่อน อาจมี LoAF จำนวนมากที่คุณอาจต้องการจำกัดให้แสดงเฉพาะ LoAF ที่มีการโต้ตอบ ตั้งค่าเกณฑ์ขั้นสูง หรือดูเฉพาะรายการที่แย่ที่สุดเท่านั้น ขณะแก้ไขปัญหาการตอบสนองที่พบบ่อย คุณสามารถขยายปัญหานี้โดยไม่จำกัดเพียงการโต้ตอบเท่านั้น และด้วยการลดเกณฑ์ หรือมองหารูปแบบบางอย่าง

สังเกตเฟรมของภาพเคลื่อนไหวขนาดยาวที่มีการโต้ตอบ

หากต้องการรับข้อมูลเชิงลึกนอกเหนือจากเฟรมภาพเคลื่อนไหวแบบยาว INP เพียงอย่างเดียว คุณสามารถดู LoAF ทั้งหมดที่มีการโต้ตอบ (ซึ่งตรวจจับได้โดยมีค่า firstUIEventTimestamp)

นี่อาจเป็นวิธีที่ง่ายกว่าในการตรวจสอบ INP LoAF แทนการพยายามหาความสัมพันธ์ทั้ง 2 อย่างนี้ ซึ่งอาจซับซ้อนกว่า ในกรณีส่วนใหญ่ อินสแตนซ์นี้จะรวม INP LoAF สำหรับการเข้าชมครั้งหนึ่งๆ และในบางกรณีที่พบไม่บ่อยเมื่อไม่ได้แสดงการโต้ตอบขนาดยาวที่สำคัญที่ต้องแก้ไข เนื่องจากอาจเป็นการโต้ตอบ INP สำหรับผู้ใช้รายอื่นๆ

โค้ดต่อไปนี้จะบันทึกรายการ LoAF ทั้งหมดที่มีความยาวมากกว่า 150 มิลลิวินาที ซึ่งมีการโต้ตอบเกิดขึ้นระหว่างเฟรม เลือก 150 ในที่นี้เพราะน้อยกว่า 200 มิลลิวินาทีที่ "ดี" เล็กน้อย เกณฑ์ INP คุณจะเลือกค่าที่สูงกว่าหรือต่ำกว่าได้ตามความต้องการ

const REPORTING_THRESHOLD_MS = 150;

const observer = new PerformanceObserver(list => {
    for (const entry of list.getEntries()) {
      if (entry.duration > REPORTING_THRESHOLD_MS &&
        entry.firstUIEventTimestamp > 0
      ) {
        // Example here logs to console, but could also report back to analytics
        console.log(entry);
      }
    }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

สังเกตเฟรมภาพเคลื่อนไหวที่ยาวกว่าเกณฑ์ที่กำหนด

อีกกลยุทธ์หนึ่งคือการตรวจสอบ LoAF ทั้งหมดและบีคอนที่มากกว่าเกณฑ์ที่แน่นอนกลับไปยังปลายทางการวิเคราะห์เพื่อทำการวิเคราะห์ในภายหลัง ดังนี้

const REPORTING_THRESHOLD_MS = 150;

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    if (entry.duration > REPORTING_THRESHOLD_MS) {
      // Example here logs to console, but could also report back to analytics
      console.log(entry);
    }
  }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

เนื่องจากรายการเฟรมภาพเคลื่อนไหวที่ยาวอาจมีขนาดใหญ่พอสมควร นักพัฒนาซอฟต์แวร์จึงควรตัดสินใจว่าจะส่งข้อมูลใดจากรายการไปยัง Analytics ตัวอย่างเช่น เวลาสรุปของรายการและอาจเป็นชื่อสคริปต์ หรือชุดข้อมูลบริบทอื่น ๆ ขั้นต่ำที่ระบบอาจพิจารณาว่าจำเป็น

สังเกตเฟรมภาพเคลื่อนไหวขนาดยาวที่แย่ที่สุด

แทนที่จะกำหนดเกณฑ์มาตรฐาน เว็บไซต์อาจต้องการเก็บข้อมูลในเฟรม (หรือเฟรม) ภาพเคลื่อนไหวที่ยาวที่สุด เพื่อลดปริมาณข้อมูลที่ต้องมีบีคอน ดังนั้น ไม่ว่าประสบการณ์หน้าเว็บจะมีภาพเคลื่อนไหวยาวกี่เฟรม เฉพาะข้อมูลของเฟรมที่แย่ที่สุด 1, 5 หรือเฟรมของภาพเคลื่อนไหวยาวๆ ก็ตามที่จำเป็นจริงๆ จะกลับมานำมาใช้

MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];

const observer = new PerformanceObserver(list => {
  longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
    (a, b) => b.blockingDuration - a.blockingDuration
  ).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });

นอกจากนี้ยังนำกลยุทธ์เหล่านี้มารวมกันได้ด้วย โดยดูเฉพาะ LoAF ที่แย่ที่สุด 10 อันดับที่มีการโต้ตอบนานกว่า 150 มิลลิวินาที

เวลาที่เหมาะสม (ควรเป็นเหตุการณ์ visibilitychange) กลับไปที่ข้อมูลวิเคราะห์ สำหรับการทดสอบในเครื่อง คุณจะใช้ console.table เป็นระยะได้ดังนี้

console.table(longestBlockingLoAFs);

ระบุรูปแบบที่พบบ่อยในเฟรมภาพเคลื่อนไหวขนาดยาว

อีกกลยุทธ์หนึ่งคือการดูสคริปต์ทั่วไปที่ปรากฏมากที่สุดในรายการเฟรมภาพเคลื่อนไหวขนาดยาว อาจมีการรายงานข้อมูลย้อนกลับในระดับสคริปต์และตำแหน่งของอักขระเพื่อระบุผู้ที่กระทำผิดซ้ำๆ

วิธีนี้อาจทำงานได้ดีสำหรับแพลตฟอร์มที่ปรับแต่งได้ ซึ่งสามารถระบุธีมหรือปลั๊กอินที่ทำให้เกิดปัญหาด้านประสิทธิภาพในเว็บไซต์จำนวนมาก

เวลาในการดำเนินการกับสคริปต์ทั่วไปหรือต้นทางของบุคคลที่สามในเฟรมภาพเคลื่อนไหวขนาดยาวสามารถสรุปและรายงานกลับออกมาเพื่อระบุปัจจัยที่ทำให้เกิดเฟรมภาพเคลื่อนไหวขนาดยาวที่พบได้บ่อยในเว็บไซต์หรือคอลเล็กชันของเว็บไซต์ ตัวอย่างเช่น หากต้องการดู URL

const observer = new PerformanceObserver(list => {
  const allScripts = list.getEntries().flatMap(entry => entry.scripts);
  const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
  const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
      allScripts.filter(script => script.sourceURL === sourceURL)
  ]));
  const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
    sourceURL,
    count: scripts.length,
    totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
  }));
  processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
  // Example here logs to console, but could also report back to analytics
  console.table(processedScripts);
});

observer.observe({type: 'long-animation-frame', buffered: true});

และตัวอย่างของเอาต์พุตนี้คือ

(index) sourceURL count totalDuration
0 'https://example.consent.com/consent.js' 1 840
1 'https://example.com/js/analytics.js' 7 628
2 'https://example.chatapp.com/web-chat.js' 1 5

ใช้ Long Animation Frames API ในเครื่องมือ

API ยังอนุญาตให้ใช้เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์เพิ่มเติมในการแก้ไขข้อบกพร่องในเครื่อง แม้ว่าเครื่องมือบางอย่าง เช่น Lighthouse และ Chrome DevTools สามารถรวบรวมข้อมูลจำนวนมากนี้โดยใช้รายละเอียดการติดตามในระดับต่ำลงได้ แต่การมี API ระดับสูงกว่านี้อาจทำให้เครื่องมืออื่นๆ เข้าถึงข้อมูลนี้ได้

แสดงข้อมูลเฟรมของภาพเคลื่อนไหวขนาดยาวในเครื่องมือสำหรับนักพัฒนาเว็บ

คุณแสดงเฟรมภาพเคลื่อนไหวขนาดยาวในเครื่องมือสำหรับนักพัฒนาเว็บได้โดยใช้ performance.measure() API ซึ่งหลังจากนั้นจะแสดงในแทร็กระยะเวลาของผู้ใช้เครื่องมือสำหรับนักพัฒนาเว็บในการติดตามประสิทธิภาพ เพื่อแสดงให้เห็นว่าควรปรับปรุงประสิทธิภาพด้านใดเป็นพิเศษ

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    performance.measure('LoAF', {
      start: entry.startTime,
      end: entry.startTime + entry.duration,
    });
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });

ในระยะยาว เครื่องมือนี้จะรวมไว้ในเครื่องมือสำหรับนักพัฒนาเว็บด้วยเช่นกัน แต่ข้อมูลโค้ดก่อนหน้านี้จะช่วยให้เครื่องมือแสดงข้อมูลโค้ดได้ในระหว่างนี้

ใช้ข้อมูลเฟรมภาพเคลื่อนไหวยาวในเครื่องมืออื่นๆ ของนักพัฒนาซอฟต์แวร์

ส่วนขยาย Web Vitals แสดงค่าในข้อมูลการแก้ไขข้อบกพร่องของสรุปการบันทึกเพื่อวินิจฉัยปัญหาด้านประสิทธิภาพ

และตอนนี้ยังแสดงข้อมูลเฟรมภาพเคลื่อนไหวขนาดยาวสำหรับการเรียกกลับของ INP แต่ละรายการและการโต้ตอบแต่ละครั้งด้วย

วันที่ การบันทึกคอนโซลของส่วนขยาย Web Vitals
การบันทึกคอนโซลของส่วนขยาย Web Vitals จะแสดงข้อมูล LoAF

ใช้ข้อมูลเฟรมภาพเคลื่อนไหวยาวในเครื่องมือทดสอบอัตโนมัติ

ในทํานองเดียวกัน เครื่องมือทดสอบอัตโนมัติในไปป์ไลน์ CI/CD สามารถแสดงรายละเอียดเกี่ยวกับปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้นได้โดยการวัดเฟรมภาพเคลื่อนไหวขนาดยาวขณะเรียกใช้ชุดทดสอบต่างๆ

คำถามที่พบบ่อย

คำถามที่พบบ่อยบางส่วนเกี่ยวกับ API นี้ ได้แก่

ทำไมไม่ลองขยายหรือทำซ้ำใน Long Tasks API

นี่เป็นอีกทางเลือกหนึ่งของการรายงานการวัดปัญหาการตอบสนองที่อาจเกิดขึ้นได้ที่มีความคล้ายกันแต่ต่างออกไป สิ่งสำคัญคือต้องตรวจสอบว่าเว็บไซต์ที่ใช้ Long Tasks API ที่มีอยู่ยังคงทำงานต่อไปเพื่อหลีกเลี่ยงการหยุดชะงักของ Use Case ที่มีอยู่

แม้ว่า Long Tasks API อาจได้รับประโยชน์จากฟีเจอร์บางอย่างของ LoAF (เช่น รูปแบบการระบุแหล่งที่มาที่ดีกว่า) แต่เราเชื่อว่าการมุ่งเน้นที่เฟรมแทนที่จะเป็นงานมีประโยชน์มากมายที่ทำให้ API นี้แตกต่างจาก Long Tasks API ที่มีอยู่โดยพื้นฐาน

ทำไมฉันจึงไม่มีรายการสคริปต์

กรณีนี้อาจบ่งชี้ว่าเฟรมของภาพเคลื่อนไหวที่ใช้เวลานานไม่ได้เกิดจาก JavaScipt แต่เป็นการแสดงผลที่มีขนาดใหญ่

กรณีนี้อาจเกิดขึ้นเมื่อเฟรมภาพเคลื่อนไหวขนาดยาวเท่ากับเนื่องจาก JavaScript แต่ไม่สามารถระบุการระบุแหล่งที่มาสคริปต์ได้เนื่องจากมีเหตุผลด้านความเป็นส่วนตัวหลายประการดังที่อธิบายไว้ก่อนหน้านี้ (เดิมคือ JavaScript ไม่ได้เป็นเจ้าของหน้าเว็บนั้น)

เหตุใดฉันจึงมีรายการสคริปต์ แต่ไม่มีข้อมูลแหล่งที่มา หรือมีข้อมูลจํากัด

ซึ่งอาจเกิดขึ้นได้จากหลายสาเหตุ รวมถึงไม่มีแหล่งที่มาที่เหมาะสมที่จะชี้ไป

ข้อมูลสคริปต์จะถูกจำกัดสำหรับสคริปต์ no-cors cross-origin ด้วยเช่นกัน แต่จะแก้ไขได้โดยการดึงสคริปต์เหล่านั้นโดยใช้ CORS โดยเพิ่ม crossOrigin = "anonymous" ในการเรียกใช้ <script>

เช่น สคริปต์ Google Tag Manager เริ่มต้นที่จะเพิ่มในหน้าเว็บ

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->

สามารถเพิ่มประสิทธิภาพเพื่อเพิ่ม j.crossOrigin = "anonymous" เพื่อให้ระบุรายละเอียดการระบุแหล่งที่มาทั้งหมดสำหรับ GTM ได้

ฟีเจอร์นี้จะมาแทนที่ Long Tasks API ไหม

แม้เราจะเชื่อว่า Long Animation Frames API เป็น API ที่ดีกว่าและสมบูรณ์กว่าสำหรับการวัดผลงานที่ใช้เวลานาน แต่ขณะนี้ยังไม่มีแผนที่จะเลิกใช้งาน Long Tasks API

ต้องการความคิดเห็น

คุณส่งความคิดเห็นได้ที่รายการปัญหาเกี่ยวกับ GitHub หรือโปรดส่งข้อบกพร่องในการใช้งาน API ของ Chrome ในเครื่องมือติดตามปัญหาของ Chrome

บทสรุป

Long Animation Frames API เป็น API ใหม่ที่น่าตื่นเต้นซึ่งมีข้อได้เปรียบมากมายเหนือกว่า Long Tasks API เดิม

เครื่องมือนี้เป็นเครื่องมือหลักในการจัดการปัญหาการตอบสนองตามที่ INP วัดได้ INP เป็นเมตริกที่ท้าทายในการเพิ่มประสิทธิภาพและ API นี้เป็นวิธีหนึ่งที่ทีม Chrome ต้องการช่วยให้การระบุและแก้ไขปัญหาต่างๆ ง่ายขึ้นสำหรับนักพัฒนาซอฟต์แวร์

ขอบเขตของ Long Animation Frames API ขยายไปมากกว่าแค่ INP เท่านั้น และยังช่วยระบุสาเหตุอื่นๆ ที่ทำให้การอัปเดตช้าได้ด้วย ซึ่งอาจส่งผลต่อความลื่นไหลโดยรวมสำหรับประสบการณ์ของผู้ใช้เว็บไซต์

กิตติกรรมประกาศ

ภาพขนาดย่อโดย Henry Be ในเรื่อง Unsplash