วิธีตอบสนองการโต้ตอบของผู้ใช้ให้เร็วขึ้น
ฉันคลิกแล้ว แต่ไม่มีอะไรเกิดขึ้น! เหตุใดฉันจึงไม่สามารถโต้ตอบกับเพจนี้ได้ 😢
First Contentful Paint (FCP) และ Largest Contentful Paint (LCP) เป็นเมตริกที่วัดระยะเวลาที่เนื้อหาใช้ในการแสดงผล (ลงสี) ในหน้าหนึ่งๆ แม้ว่าจะมีความสำคัญ แต่เวลาการแสดงผลจะไม่บันทึกการตอบสนองของการโหลด หรือความเร็วที่หน้าเว็บตอบสนองต่อการโต้ตอบของผู้ใช้
First Input Delay (FID) เป็นเมตริก Core Web Vitals ที่บันทึกความประทับใจแรกของผู้ใช้เกี่ยวกับการโต้ตอบและการตอบสนองของเว็บไซต์ โดยวัดระยะเวลาตั้งแต่ที่ผู้ใช้โต้ตอบกับหน้าเว็บเป็นครั้งแรกจนถึงเวลาที่เบราว์เซอร์ตอบสนองต่อการโต้ตอบนั้นได้จริง FID เป็นเมตริกภาคสนามและจำลองในสภาพแวดล้อมของห้องทดลองไม่ได้ คุณต้องมีการโต้ตอบของผู้ใช้จริงเพื่อวัดความล่าช้าของการตอบกลับ
เพื่อช่วยคาดการณ์ FID ในห้องทดลอง เราขอแนะนำให้ใช้เวลาในการบล็อกทั้งหมด (TBT) โดยจะวัดผลแตกต่างกันไป แต่การปรับปรุง TBT มักจะสอดคล้องกับการปรับปรุง FID
สาเหตุหลักของ FID ที่ต่ำคือการเรียกใช้ JavaScript อย่างหนัก การเพิ่มประสิทธิภาพวิธีแยกวิเคราะห์ คอมไพล์ และเรียกใช้ JavaScript ในหน้าเว็บจะลด FID โดยตรง
การเรียกใช้ JavaScript เป็นจำนวนมาก
เบราว์เซอร์จะตอบสนองต่อข้อมูลส่วนใหญ่ของผู้ใช้ไม่ได้ขณะเรียกใช้ JavaScript ในเทรดหลัก กล่าวคือ เบราว์เซอร์จะไม่สามารถตอบสนองต่อการโต้ตอบของผู้ใช้ในขณะที่เทรดหลักไม่ว่าง หากต้องการปรับปรุงประสิทธิภาพ โปรดทำดังนี้
- แบ่งงานที่ใช้เวลานาน
- เพิ่มประสิทธิภาพหน้าเว็บเพื่อความพร้อมในการโต้ตอบ
- ใช้ Web Worker
- ลดเวลาในการดำเนินการกับ JavaScript
แยกงานที่ใช้เวลานาน
หากคุณได้พยายามลดจำนวน JavaScript ที่โหลดในหน้าเดียวแล้ว การแบ่งโค้ดที่ทำงานเป็นเวลานานออกเป็นงานแบบไม่พร้อมกันขนาดเล็กก็อาจมีประโยชน์
งานที่ใช้เวลานานคือช่วงเวลาดำเนินการกับ JavaScript ที่ผู้ใช้อาจพบว่า UI ไม่ตอบสนอง โค้ดที่บล็อกเทรดหลักเป็นเวลา 50 มิลลิวินาทีขึ้นไปอาจมีลักษณะเป็นงานแบบยาว งานที่ใช้เวลานานเป็นสัญญาณของการขยายตัวของ JavaScript ที่เป็นไปได้ (การโหลดและเรียกใช้มากกว่าที่ผู้ใช้อาจต้องการในตอนนี้) การแยกงานที่ใช้เวลานานจะช่วยลดความล่าช้าในการป้อนข้อมูลในเว็บไซต์ได้
FID ควรดีขึ้นอย่างเห็นได้ชัดเมื่อใช้แนวทางปฏิบัติแนะนำ เช่น การแยกโค้ดและการแบ่งงานที่ใช้เวลานาน แม้ว่า TBT จะไม่ใช่เมตริกภาคสนาม แต่เครื่องมือนี้มีประโยชน์สำหรับการตรวจสอบความคืบหน้าในการปรับปรุงทั้ง Time To Interactive (TTI) และ FID ในท้ายที่สุด
เพิ่มประสิทธิภาพหน้าเว็บเพื่อความพร้อมในการโต้ตอบ
มีสาเหตุที่พบบ่อยหลายประการที่ทำให้คะแนน FID และ TBT ต่ำในเว็บแอปที่ต้องอาศัย JavaScript เป็นอย่างมากมีดังนี้
การดำเนินการสคริปต์ของบุคคลที่หนึ่งอาจทำให้ความพร้อมในการโต้ตอบล่าช้า
- การขยายขนาด JavaScript, เวลาดำเนินการที่หนัก และการแบ่งส่วนที่ไม่มีประสิทธิภาพจะทำให้หน้าเว็บตอบสนองต่อข้อมูลจากผู้ใช้ได้ช้าลง รวมถึงส่งผลต่อ FID, TBT และ TTI ด้วย การโหลดโค้ดและฟีเจอร์แบบโปรเกรสซีฟ จะช่วยกระจายงานนี้และเพิ่มความพร้อมในการโต้ตอบ
- แอปที่แสดงผลฝั่งเซิร์ฟเวอร์อาจดูเหมือนได้รับการลงพิกเซลบนหน้าจออย่างรวดเร็ว แต่ระวังการโต้ตอบของผู้ใช้ที่ถูกบล็อกโดยการเรียกใช้สคริปต์ขนาดใหญ่ (เช่น เติมข้อมูลใหม่เพื่อปรับ Listener เหตุการ���์) ซึ่งอาจใช้เวลาหลายร้อยมิลลิวินาที หรือบางครั้งอาจถึงวินาที หากใช้การแยกโค้ดตามเส้นทาง ลองเปลี่ยนตรรกะฝั่งเซิร์ฟเวอร์มากขึ้นหรือสร้างเนื้อหาแบบคงที่มากขึ้นในช่วงสร้าง
ด้านล่างนี้คือคะแนน TBT ก่อนและหลังการเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่หนึ่งสำหรับแอปพลิเคชัน การย้ายการโหลดสคริปต์ราคาแพง (และการดำเนินการ) สำหรับคอมโพเนนต์ที่ไม่จำเป็นออกไปนอกเส้นทางที่สำคัญจะทำให้ผู้ใช้โต้ตอบกับหน้าเว็บได้เร็วขึ้นมาก
การดึงข้อมูลอาจส่งผลกระทบด้านต่างๆ ของความพร้อมในการโต้ตอบ
- การรอการแสดง 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 ดังนี้
Lighthouse 6.0 ไม่มีการสนับสนุนสำหรับ FID เนื่องจากเป็นเมตริกฟิลด์ แต่จะใช้เวลาในการบล็อกทั้งหมด (TBT) เป็นพร็อกซีได้ การเพิ่มประสิทธิภาพที่ปรับปรุง TBT ควรปรับปรุง FID ในภาคสนามด้วย
ร��ยงานประสบการณ์ของผู้ใช้ Chrome แสดงค่า FID ในชีวิตจริงที่รวบรวมที่ระดับต้นทาง
ขอขอบคุณ Philip Walton, Kayce Basques, Ilya Grigorik และ Annie Sullivan ที่ร่วมรีวิว