เพิ่มประสิทธิภาพ 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 ที่ร่วมรีวิว