เพิ่มประสิทธิภาพ First Input Delay

วิธีตอบสนองการโต้ตอบของผู้ใช้ให้เร็วขึ้น

แอดดี้ ออสมานี
แอดดี ออสมานี
ฮูเซน จอร์เดห์
ฮูสเซน จอร์เดห์

ฉันคลิกแล้ว แต่ไม่มีอะไรเกิดขึ้น! เหตุใดฉันจึงไม่สามารถโต้ตอบกับเพจนี้ได้ 😢

First Contentful Paint (FCP) และ Largest Contentful Paint (LCP) เป็นเมตริกที่วัดระยะเวลาที่เนื้อหาใช้ในการแสดงผล (ลงสี) ในหน้าหนึ่งๆ แม้ว่าจะมีความสำคัญ แต่เวลาการแสดงผลจะไม่บันทึกการตอบสนองของการโหลด หรือความเร็วที่หน้าเว็บตอบสนองต่อการโต้ตอบของผู้ใช้

First Input Delay (FID) เป็นเมตริก Core Web Vitals ที่บันทึกความประทับใจแรกของผู้ใช้เกี่ยวกับการโต้ตอบและการตอบสนองของเว็บไซต์ โดยวัดระยะเวลาตั้งแต่ที่ผู้ใช้โต้ตอบกับหน้าเว็บเป็นครั้งแรกจนถึงเวลาที่เบราว์เซอร์ตอบสนองต่อการโต้ตอบนั้นได้จริง FID เป็นเมตริกภาคสนามและจำลองในสภาพแวดล้อมของห้องทดลองไม่ได้ คุณต้องมีการโต้ตอบของผู้ใช้จริงเพื่อวัดความล่าช้าของการตอบกลับ

ค่า fidid ที่ดีคือ 2.5 วินาที ค่าที่ต่ำมากกว่า 4.0 วินาที และต้องมีการปรับปรุงในด้านอื่นๆ

เพื่อช่วยคาดการณ์ FID ในห้องทดลอง เราขอแนะนำให้ใช้เวลาในการบล็อกทั้งหมด (TBT) โดยจะวัดผลแตกต่างกันไป แต่การปรับปรุง TBT มักจะสอดคล้องกับการปรับปรุง FID

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

การเรียกใช้ JavaScript เป็นจำนวนมาก

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

แยกงานที่ใช้เวลานาน

หากคุณได้พยายามลดจำนวน JavaScript ที่โหลดในหน้าเดียวแล้ว การแบ่งโค้ดที่ทำงานเป็นเวลานานออกเป็นงานแบบไม่พร้อมกันขนาดเล็กก็อาจมีประโยชน์

งานที่ใช้เวลานานคือช่วงเวลาดำเนินการกับ JavaScript ที่ผู้ใช้อาจพบว่า UI ไม่ตอบสนอง โค้ดที่บล็อกเทรดหลักเป็นเวลา 50 มิลลิวินาทีขึ้นไปอาจมีลักษณะเป็นงานแบบยาว งานที่ใช้เวลานานเป็นสัญญาณของการขยายตัวของ JavaScript ที่เป็นไปได้ (การโหลดและเรียกใช้มากกว่าที่ผู้ใช้อาจต้องการในตอนนี้) การแยกงานที่ใช้เวลานานจะช่วยลดความล่าช้าในการป้อนข้อมูลในเว็บไซต์ได้

งานที่ใช้เวลานานในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome แสดงภาพงานที่ใช้เวลานานในแผงประสิทธิภาพ

FID ควรดีขึ้นอย่างเห็นได้ชัดเมื่อใช้แนวทางปฏิบัติแนะนำ เช่น การแยกโค้ดและการแบ่งงานที่ใช้เวลานาน แม้ว่า TBT จะไม่ใช่เมตริกภาคสนาม แต่เครื่องมือนี้มีประโยชน์สำหรับการตรวจสอบความคืบหน้าในการปรับปรุงทั้ง Time To Interactive (TTI) และ FID ในท้ายที่สุด

เพิ่มประสิทธิภาพหน้าเว็บเพื่อความพร้อมในการโต้ตอบ

มีสาเหตุที่พบบ่อยหลายประการที่ทำให้คะแนน FID และ TBT ต่ำในเว็บแอปที่ต้องอาศัย JavaScript เป็นอย่างมากมีดังนี้

การดำเนินการสคริปต์ของบุคคลที่หนึ่งอาจทำให้ความพร้อมในการโต้ตอบล่าช้า

  • การขยายขนาด JavaScript, เวลาดำเนินการที่หนัก และการแบ่งส่วนที่ไม่มีประสิทธิภาพจะทำให้หน้าเว็บตอบสนองต่อข้อมูลจากผู้ใช้ได้ช้าลง รวมถึงส่งผลต่อ FID, TBT และ TTI ด้วย การโหลดโค้ดและฟีเจอร์แบบโปรเกรสซีฟ จะช่วยกระจายงานนี้และเพิ่มความพร้อมในการโต้ตอบ
  • แอปที่แสดงผลฝั่งเซิร์ฟเวอร์อาจดูเหมือนได้รับการลงพิกเซลบนหน้าจออย่างรวดเร็ว แต่ระวังการโต้ตอบของผู้ใช้ที่ถูกบล็อกโดยการเรียกใช้สคริปต์ขนาดใหญ่ (เช่น เติมข้อมูลใหม่เพื่อปรับ Listener เหตุการณ์) ซึ่งอาจใช้เวลาหลายร้อยมิลลิวินาที หรือบางครั้งอาจถึงวินาที หากใช้การแยกโค้ดตามเส้นทาง ลองเปลี่ยนตรรกะฝั่งเซิร์ฟเวอร์มากขึ้นหรือสร้างเนื้อหาแบบคงที่มากขึ้นในช่วงสร้าง

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

คะแนน TBT ที่เพิ่มขึ้นใน Lighthouse หลังเพิ่มประสิทธิภาพสคริปต์ของบุคคลที่หนึ่ง

การดึงข้อมูลอาจส่งผลกระทบด้านต่างๆ ของความพร้อมในการโต้ตอบ

  • การรอการแสดง Waterfall ของการดึงข้อมูลแบบ Cascading (เช่น JavaScript และการดึงข้อมูลสําหรับคอมโพเนนต์) อาจส่งผลต่อเวลาในการตอบสนองของการโต้ตอบ ตั้งเป้าไปที่การลดการพึ่งพาการดึงข้อมูลแบบต่อเรียงกันให้น้อยที่สุด
  • พื้นที่เก็บข้อมูลแบบอินไลน์ขนาดใหญ่อาจใช้เวลาในการแยกวิเคราะห์ HTML และส่งผลต่อเมตริกการแสดงผลและการโต้ตอบ ตั้งเป้าที่จะลดปริมาณข้อมูลที่ต้องประมวลผลภายหลังในฝั่งไคลเอ็นต์

การดำเนินการสคริปต์ของบุคคลที่สามอาจทำให้เวลาในการตอบสนองของการโต้ตอบช้าลงด้วย

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

ใช้ Web Worker

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

ลองใช้ไลบรารีต่อไปนี้เพื่อให้ใช้ Web Worker บนเว็บไซต์ของคุณได้ง่ายขึ้น

  • Comlink: คลังตัวช่วยที่สรุปข้อมูลจาก postMessage และช่วยให้ใช้งานได้ง่ายขึ้น
  • Workway: ผู้ส่งออก Web Worker สำหรับวัตถุประสงค์ทั่วไป
  • Workerize: ย้ายโมดูลไปยัง Web Worker

ลดเวลาในการดำเนินการกับ JavaScript

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

หากต้องการลดจำนวน JavaScript ที่ดำเนินการในหน้าเว็บ ให้ทำดังนี้

  • เลื่อน JavaScript ที่ไม่ได้ใช้
  • ลดจำนวนโพลีฟิลที่ไม่ได้ใช้

เลื่อน JavaScript ที่ไม่ได้ใช้

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

แท็บการครอบคลุมในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome จะบอกได้ว่าหน้าเว็บไม่มีการใช้ JavaScript มากน้อยเพียงใด

แท็บความครอบคลุม

วิธีลด JavaScript ที่ไม่ได้ใช้

  • โค้ดแบ่งชุดเป็นหลายๆ ส่วน
  • เลื่อน JavaScript ที่ไม่สำคัญรวมถึงสคริปต์ของบุคคลที่สามโดยใช้ async หรือ defer

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

import('module.js').then((module) => {
  // Do something with the module.
});

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

นอกจากการรองรับเบราว์เซอร์โดยทั่วไปแล้ว ไวยากรณ์การนำเข้าแบบไดนามิกยังใช้กับระบบบิลด์ต่างๆ ได้อีกด้วย

  • หากใช้ Webpack, Rollup หรือ Parcel เป็นกลุ่มโมดูล ให้ใช้ประโยชน์จากการรองรับการนำเข้าแบบไดนามิกของบริษัทดังกล่าว
  • เฟรมเวิร์กฝั่งไคลเอ็นต์ เช่น React, Angular และ Vue มีบทคัดย่อเพื่อให้การโหลดแบบ Lazy Loading ที่ระดับคอมโพเนนต์ทำได้ง่ายขึ้น

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

<script defer src="…"></script>
<script async src="…"></script>

สคริปต์ของบุคคลที่สามทั้งหมดควรโหลดด้วย defer หรือ async โดยค่าเริ่มต้น เว้นแต่จะมีเหตุผลที่เฉพาะเจาะจง

ลดจำนวนโพลีฟิลที่ไม่ได้ใช้

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

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

วิธีเพิ่มประสิทธิภาพการใช้งาน Polyfill ในเว็บไซต์

  • หากคุณใช้ Babel เป็นตัวเปลี่ยนรูปแบบ ให้ใช้ @babel/preset-env เพื่อรวมเฉพาะ Polyfill ที่จำเป็นสำหรับเบราว์เซอร์ที่คุณวางแผนจะกำหนดเป้าหมาย สำหรับ Babel 7.9 ให้เปิดใช้ตัวเลือก bugfixes เพื่อตัดแผ่นโพลีฟิลที่ไม่จำเป็นเพิ่มเติม
  • ใช้รูปแบบโมดูล/ไม่มีโมดูลเพื่อส่งแพ็กเกจ 2 แพ็กเกจแยกกัน (@babel/preset-env รองรับแพ็กเกจนี้ผ่าน target.esmodules ด้วย)

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>
    

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

เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์

มีเครื่องมือจำนวนมากที่ใช้วัดและแก้ไขข้อบกพร่อง FID ดังนี้

ขอขอบคุณ Philip Walton, Kayce Basques, Ilya Grigorik และ Annie Sullivan ที่ร่วมรีวิว