ดูว่าเครื่องมือสแกนการโหลดล่วงหน้าของเบราว์เซอร์คืออะไร ช่วยเพิ่มประสิทธิภาพได้อย่างไร และคุณจะหลีกเลี่ยงได้อย่างไร
แง่มุมหนึ่งของการเพิ่มประสิทธิภาพความเร็วของหน้าเว็บที่มักถูกมองข้ามคือการทำความเข้าใจเกี่ยวกับกลไกภายในของเบราว์เซอร์ เบราว์เซอร์ทำการเพิ่มประสิทธิภาพบางอย่างเพื่อปรับปรุงประสิทธิภาพในแบบที่เราในฐานะนักพัฒนาซอฟต์แวร์ทำไม่ได้ แต่จะทำได้ก็ต่อเมื่อการเพิ่มประสิทธิภาพเหล่านั้นไม่ถูกขัดขวางโดยไม่ตั้งใจ
การเพิ่มประสิทธิภาพเบราว์เซอร์ภายในอย่างหนึ่งที่ควรทำความเข้าใจคือเครื่องมือสแกนการโหลดล่วงหน้าของเบราว์เซอร์ โพสต์นี้จะอธิบายวิธีการทำงานของเครื่องมือสแกนการโหลดล่วงหน้า และที่สำคัญกว่านั้นคือวิธีหลีกเลี่ยงไม่ให้เครื่องมือสแกนการโหลดล่วงหน้าทำงานได้ไม่เต็มประสิทธิภาพ
เครื่องสแกนแอปที่โหลดไว้ล่วงหน้าคืออะไร
เบราว์เซอร์ทุกตัวมีโปรแกรมแยกวิเคราะห์ HTML หลักที่แยกวิเคราะห์มาร์กอัปดิบและประมวลผลเป็นโมเดลออบเจ็กต์ ทั้งหมดนี้จะดำเนินไปอย่างราบรื่นจนกว่าโปรแกรมแยกวิเคราะห์จะหยุดชั่วคราวเมื่อพบทรัพยากรที่บล็อก เช่น สไตล์ชีตที่โหลดด้วยองค์ประกอบ <link> หรือสคริปต์ที่โหลดด้วยองค์ประกอบ <script> โดยไม่มีแอตทริบิวต์ async หรือ defer
<link> สำหรับไฟล์ CSS ภายนอก ซึ่งจะบล็อกเบราว์เซอร์ไม่ให้แยกวิเคราะห์ส่วนที่เหลือของเอกสาร หรือแม้แต่แสดงผลส่วนใดส่วนหนึ่ง จนกว่าจะดาวน์โหลดและแยกวิเคราะห์ CSS
ในกรณีของไฟล์ CSS ระบบจะบล็อกการแสดงผลเพื่อป้องกันการแสดงเนื้อหาที่ไม่มีการจัดรูปแบบ (FOUC) ซึ่งเป็นกรณีที่ผู้ใช้เห็นหน้าเว็บเวอร์ชันที่ไม่มีการจัดรูปแบบเป็นเวลาสั้นๆ ก่อนที่จะมีการใช้รูปแบบกับหน้าเว็บ
นอกจากนี้ เบราว์เซอร์ยังบล็อกการแยกวิเคราะห์และการแสดงผลของหน้าเมื่อพบองค์ประกอบ <script> ที่ไม่มีแอตทริบิวต์ defer หรือ async
สาเหตุคือเบราว์เซอร์ไม่สามารถทราบได้อย่างแน่ชัดว่าสคริปต์หนึ่งๆ จะแก้ไข DOM หรือไม่ในขณะที่โปรแกรมแยกวิเคราะห์ HTML หลักยังคงทำงานอยู่ ด้วยเหตุนี้ การโหลด JavaScript ที่ส่วนท้ายของเอกสารจึงเป็นแนวทางปฏิบัติที่พบบ่อย เพื่อให้ผลกระทบของการแยกวิเคราะห์และการแสดงผลที่ถูกบล็อกมีผลเพียงเล็กน้อย
ซึ่งเป็นเหตุผลที่ดีว่าทำไมเบราว์เซอร์ควรบล็อกทั้งการแยกวิเคราะห์และการแสดงผล อย่างไรก็ตาม การบล็อกขั้นตอนสำคัญเหล่านี้เป็นสิ่งที่ไม่พึงประสงค์ เนื่องจากอาจทำให้การแสดงผลล่าช้าโดยการชะลอการค้นพบทรัพยากรที่สำคัญอื่นๆ โชคดีที่เบราว์เซอร์พยายามอย่างเต็มที่เพื่อลดปัญหาเหล่านี้ด้วยวิธีใช้โปรแกรมแยกวิเคราะห์ HTML สำรองที่เรียกว่าเครื่องมือสแกนการโหลดล่วงหน้า
<body> ได้ แต่เครื่องมือสแกนการโหลดล่วงหน้าจะดูมาร์กอัปดิบล่วงหน้าเพื่อค้นหาทรัพยากรรูปภาพนั้นและเริ่มโหลดก่อนที่ตัวแยกวิเคราะห์ HTML หลักจะเลิกบล็อก
บทบาทของเครื่องมือสแกนการโหลดล่วงหน้าเป็นการคาดเดา ซึ่งหมายความว่าเครื่องมือจะตรวจสอบมาร์กอัปดิบเพื่อค้นหาทรัพยากรที่จะดึงข้อมูลอย่างฉวยโอกาสก่อนที่โปรแกรมแยกวิเคราะห์ HTML หลักจะค้นพบ
วิธีดูว่าเครื่องมือสแกนการโหลดล่วงหน้าทำงานอยู่หรือไม่
เครื่องมือสแกนการโหลดล่วงหน้ามีอยู่เนื่องจากการแสดงผลและการแยกวิเคราะห์ที่ถูกบล็อก หากไม่มีปัญหาด้านประสิทธิภาพ 2 ประการนี้ เครื่องมือสแกนการโหลดล่วงหน้าก็คงไม่มีประโยชน์มากนัก กุญแจสำคัญในการพิจารณาว่าหน้าเว็บได้รับประโยชน์จากเครื่องมือสแกนการโหลดล่วงหน้าหรือไม่นั้นขึ้นอยู่กับปรากฏการณ์การบล็อกเหล่านี้ โดยคุณสามารถเพิ่มความล่าช้าเทียมสำหรับคำขอเพื่อดูว่าเครื่องมือสแกนการโหลดล่วงหน้าทำงานที่ใด
ดูหน้านี้ซึ่งมีข้อความและรูปภาพพื้นฐานพร้อมสไตล์ชีตเป็นตัวอย่าง เนื่องจากไฟล์ CSS บล็อกทั้งการแสดงผลและการแยกวิเคราะห์ คุณจึงสร้างความล่าช้าเทียม 2 วินาทีสำหรับสไตล์ชีตผ่านบริการพร็อกซี ความล่าช้านี้ช่วยให้เห็นได้ง่ายขึ้นใน Waterfall ของเครือข่ายว่าเครื่องมือสแกนการโหลดล่วงหน้าทำงานอยู่ที่ใด
ดังที่เห็นใน Waterfall เครื่องมือสแกนการโหลดล่วงหน้าจะค้นพบองค์ประกอบ <img> แม้ว่าการแสดงผลและการแยกวิเคราะห์เอกสารจะถูกบล็อก หากไม่มีการเพิ่มประสิทธิภาพนี้ เบราว์เซอร์จะไม่สามารถดึงข้อมูลอย่างฉวยโอกาสในช่วงที่ถูกบล็อก และคำขอทรัพยากรจำนวนมากขึ้นจะเกิดขึ้นต่อเนื่องกันแทนที่จะเกิดขึ้นพร้อมกัน
เมื่อผ่านตัวอย่างง่ายๆ ไปแล้ว เรามาดูรูปแบบที่เกิดขึ้นจริงซึ่งอาจทำให้สแกนเนอร์การโหลดล่วงหน้าทำงานไม่ได้ และวิธีแก้ไขกัน
แทรกสคริปต์ async รายการแล้ว
สมมติว่าคุณมี HTML ใน <head> ซึ่งมี JavaScript ในบรรทัดดังนี้
<script>
const scriptEl = document.createElement('script');
scriptEl.src = '/yall.min.js';
document.head.appendChild(scriptEl);
</script>
สคริปต์ที่แทรกจะเป็น async โดยค่าเริ่มต้น ดังนั้นเมื่อแทรกสคริปต์นี้ สคริปต์จะทำงานเหมือนกับว่ามีการใช้แอตทริบิวต์ async กับสคริปต์ ซึ่งหมายความว่าสคริปต์จะทำงานโดยเร็วที่สุดและไม่บล็อกการแสดงผล ฟังดูดีใช่ไหม อย่างไรก็ตาม หากคุณคิดว่า <script> ในบรรทัดนี้อยู่หลังองค์ประกอบ <link> ที่โหลดไฟล์ CSS ภายนอก คุณจะได้ผลลัพธ์ที่ไม่เหมาะสม ดังนี้
async ที่แทรกไว้ เครื่องมือสแกนการโหลดล่วงหน้าไม่พบสคริปต์ในระหว่างระยะการบล็อกการแสดงผล เนื่องจากมีการแทรกสคริปต์ในฝั่งไคลเอ็นต์
มาดูสิ่งที่เกิดขึ้นกัน
- ที่ 0 วินาที ระบบจะขอเอกสารหลัก
- ที่ 1.4 วินาที ไบต์แรกของคำขอการนำทางจะมาถึง
- ที่ 2.0 วินาที ระบบจะขอ CSS และรูปภาพ
- เนื่องจากโปรแกรมแยกวิเคราะห์ถูกบล็อกไม่ให้โหลดสไตล์ชีต และ JavaScript ในบรรทัดที่แทรกสคริปต์
asyncจะทำงานหลังจากสไตล์ชีตนั้นที่ 2.6 วินาที ฟังก์ชันการทำงานที่สคริปต์มีให้จึงไม่พร้อมใช้งานโดยเร็วที่สุดเท่าที่จะเป็นไปได้
ซึ่งไม่เหมาะสมเนื่องจากคำขอสคริปต์จะเกิดขึ้นหลังจากที่สไตล์ชีตดาวน์โหลดเสร็จแล้วเท่านั้น ซึ่งจะทำให้สคริปต์ทำงานช้าลงโดยเร็วที่สุด ในทางตรงกันข้าม เนื่องจากองค์ประกอบ <img> ค้นพบได้ในมาร์กอัปที่เซิร์ฟเวอร์จัดเตรียมไว้ เครื่องมือสแกนการโหลดล่วงหน้าจึงค้นพบองค์ประกอบดังกล่าว
แล้วจะเกิดอะไรขึ้นหากคุณใช้แท็ก <script> ปกติกับแอตทริบิวต์ async แทนที่จะแทรกสคริปต์ลงใน DOM
<script src="/yall.min.js" async></script>
ผลลัพธ์ที่ได้มีดังนี้
async <script> เดียว เครื่องมือสแกนการโหลดล่วงหน้าจะค้นพบสคริปต์ในระหว่างระยะการบล็อกการแสดงผล และโหลดสคริปต์พร้อมกันกับ CSS
คุณอาจอยากแนะนำว่าปัญหาเหล่านี้สามารถแก้ไขได้โดยใช้ rel=preload วิธีนี้ใช้ได้ผลอย่างแน่นอน แต่อาจมีผลข้างเคียงบางอย่าง เพราะเหตุใดจึงต้องใช้ rel=preload เพื่อแก้ไขปัญหาที่หลีกเลี่ยงได้โดยไม่แทรกองค์ประกอบ <script> ลงใน DOM
async ที่แทรกไว้ แต่สคริปต์ async จะโหลดไว้ล่วงหน้าเพื่อให้แน่ใจว่าจะค้นพบได้เร็วขึ้น
การโหลดล่วงหน้าจะ "แก้ไข" ปัญหาที่นี่ แต่จะทำให้เกิดปัญหาใหม่ นั่นคือสคริปต์ async ในการสาธิต 2 รายการแรก แม้ว่าจะโหลดใน <head> แต่ก็โหลดที่ลำดับความสำคัญ "ต่ำ" ส่วนสไตล์ชีตจะโหลดที่ลำดับความสำคัญ "สูงสุด" ในการสาธิตครั้งสุดท้ายที่มีการโหลดสคริปต์ async ไว้ล่วงหน้า สไตล์ชีตจะยังคงโหลดที่ลำดับความสำคัญ "สูงสุด" แต่ลำดับความสำคัญของสคริปต์ได้รับการเลื่อนเป็น "สูง"
เมื่อลำดับความสำคัญของทรัพยากรเพิ่มขึ้น เบราว์เซอร์จะจัดสรรแบนด์วิดท์ให้มากขึ้น ซึ่งหมายความว่าแม้สไตล์ชีตจะมีลำดับความสำคัญสูงสุด แต่ลำดับความสำคัญที่เพิ่มขึ้นของสคริปต์อาจทำให้เกิดการแย่งแบนด์วิดท์ ซึ่งอาจเป็นปัจจัยที่ทำให้การเชื่อมต่อช้า หรือในกรณีที่ทรัพยากรมีขนาดค่อนข้างใหญ่
คำตอบนั้นตรงไปตรงมา นั่นคือหากจำเป็นต้องใช้สคริปต์ระหว่างการเริ่มต้น อย่าขัดขวางเครื่องมือสแกนการโหลดล่วงหน้าด้วยการแทรกสคริปต์ลงใน DOM ทดสอบตามความจำเป็นด้วยการวางองค์ประกอบ <script> รวมถึงแอตทริบิวต์ต่างๆ เช่น defer และ async
การโหลดแบบ Lazy Loading ด้วย JavaScript
การโหลดแบบ Lazy Loading เป็นวิธีที่ยอดเยี่ยมในการประหยัดอินเทอร์เน็ต ซึ่งมักใช้กับรูปภาพ อย่างไรก็ตาม บางครั้งระบบอาจใช้การโหลดแบบ Lazy Loading กับรูปภาพที่อยู่ "ครึ่งหน้าบน" อย่างไม่ถูกต้อง
ซึ่งอาจทำให้เกิดปัญหาเกี่ยวกับโอกาสในการถูกค้นพบทรัพยากรเมื่อเกี่ยวข้องกับเครื่องมือสแกนการโหลดล่วงหน้า และอาจทำให้ระยะเวลาที่ใช้ในการค้นหาการอ้างอิงรูปภาพ ดาวน์โหลด ถอดรหัส และแสดงรูปภาพล่าช้าโดยไม่จำเป็น ลองดูมาร์กอัปรูปภาพนี้เป็นตัวอย่าง
<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">
การใช้คำนำหน้า data- เป็นรูปแบบที่พบบ่อยในเครื่องมือโหลดแบบ Lazy Load ที่ทำงานด้วย JavaScript เมื่อเลื่อนรูปภาพเข้าไปในวิวพอร์ต ตัวโหลดแบบ Lazy Load จะตัดคำนำหน้า data- ออก ซึ่งหมายความว่าในตัวอย่างก่อนหน้านี้ data-src จะกลายเป็น src การอัปเดตนี้จะแจ้งให้เบราว์เซอร์ดึงข้อมูลทรัพยากร
รูปแบบนี้จะไม่เป็นปัญหาจนกว่าจะนำไปใช้กับรูปภาพที่อยู่ในวิวพอร์ตระหว่างการเริ่มต้นระบบ เนื่องจากเครื่องมือสแกนการโหลดล่วงหน้าไม่ได้อ่านแอตทริบิวต์ data-src ในลักษณะเดียวกับที่อ่านแอตทริบิวต์ src (หรือ srcset) จึงไม่พบการอ้างอิงรูปภาพก่อนหน้านี้ ที่แย่ไปกว่านั้นคือรูปภาพจะโหลดล่าช้าจนกว่าจะหลังจากที่ JavaScript ของตัวโหลดแบบ Lazy Loading ดาวน์โหลด คอมไพล์ และดำเนินการ
รูปภาพอาจเป็นองค์ประกอบที่เป็นไปได้สำหรับ Largest Contentful Paint (LCP) ทั้งนี้ขึ้นอยู่กับขนาดของรูปภาพ ซึ่งอาจขึ้นอยู่กับขนาดของวิวพอร์ต เมื่อเครื่องมือสแกนการโหลดล่วงหน้าไม่สามารถดึงข้อมูลทรัพยากรรูปภาพล่วงหน้าได้(อาจเป็นช่วงที่สไตล์ชีตของหน้าบล็อกการแสดงผล) LCP จะได้รับผลกระทบ
วิธีแก้ปัญหาคือเปลี่ยนมาร์กอัปรูปภาพดังนี้
<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">
นี่เป็นรูปแบบที่เหมาะสมที่สุดสำหรับรูปภาพที่อยู่ในวิวพอร์ตระหว่างการเริ่มต้นระบบ เนื่องจากเครื่องมือสแกนการโหลดล่วงหน้าจะค้นพบและดึงข้อมูลทรัพยากรรูปภาพได้เร็วขึ้น
ผลลัพธ์ในตัวอย่างที่เข้าใจง่ายนี้คือ LCP ดีขึ้น 100 มิลลิวินาทีในการเชื่อมต่อที่ช้า ซึ่งอาจดูเหมือนไม่ใช่การปรับปรุงที่ยิ่งใหญ่ แต่ก็ถือว่าเป็นการปรับปรุงที่สำคัญเมื่อพิจารณาว่าโซลูชันนี้เป็นการแก้ไขมาร์กอัปอย่างรวดเร็ว และหน้าเว็บส่วนใหญ่มีความซับซ้อนมากกว่าตัวอย่างชุดนี้ ซึ่งหมายความว่าผู้สมัคร LCP อาจต้องแย่งแบนด์วิดท์กับทรัพยากรอื่นๆ อีกหลายรายการ ดังนั้นการเพิ่มประสิทธิภาพเช่นนี้จึงมีความสำคัญมากขึ้นเรื่อยๆ
ภาพพื้นหลัง CSS
โปรดทราบว่าเครื่องมือสแกนการโหลดล่วงหน้าของเบราว์เซอร์จะสแกนมาร์กอัป แต่จะไม่สแกนทรัพยากรประเภทอื่นๆ เช่น CSS ซึ่งอาจเกี่ยวข้องกับการดึงข้อมูลรูปภาพที่อ้างอิงโดยพร็อพเพอร์ตี้ background-image
เช่นเดียวกับ HTML เบราว์เซอร์จะประมวลผล CSS เป็นออบเจ็กต์โมเดลของตัวเอง ซึ่งเรียกว่า CSSOM หากพบทรัพยากรภายนอกขณะสร้าง CSSOM ระบบจะขอทรัพยากรเหล่านั้น ณ เวลาที่พบ ไม่ใช่โดยเครื่องมือสแกนการโหลดล่วงหน้า
สมมติว่าตัวเลือก LCP ของหน้าเว็บเป็นองค์ประกอบที่มีพร็อพเพอร์ตี้ CSS background-image สิ่งที่จะเกิดขึ้นเมื่อโหลดทรัพยากรมีดังนี้
background-image (แถวที่ 3) รูปภาพที่ขอจะไม่เริ่มดึงข้อมูลจนกว่าโปรแกรมแยกวิเคราะห์ CSS จะพบรูปภาพนั้น
ในกรณีนี้ เครื่องมือสแกนการโหลดล่วงหน้าไม่ได้ถูกขัดขวาง แต่ไม่มีส่วนเกี่ยวข้อง อย่างไรก็ตาม หากผู้สมัคร LCP ในหน้าเว็บมาจากพร็อพเพอร์ตี้ CSS background-image คุณจะต้องโหลดรูปภาพนั้นล่วงหน้า ดังนี้
<!-- Make sure this is in the <head> below any
stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">
คำแนะนำ rel=preload นั้นมีขนาดเล็ก แต่ช่วยให้เบราว์เซอร์ค้นพบรูปภาพได้เร็วกว่าที่ควรจะเป็น
background-image (แถวที่ 3) คำแนะนำ rel=preload ช่วยให้เบราว์เซอร์ค้นพบรูปภาพได้เร็วขึ้นประมาณ 250 มิลลิวินาทีเมื่อเทียบกับตอนที่ไม่มีคำแนะนำ
เมื่อใช้คำแนะนำ rel=preload ระบบจะค้นพบตัวเลือก LCP ได้เร็วขึ้น ซึ่งจะช่วยลดเวลา LCP แม้ว่าคำแนะนำดังกล่าวจะช่วยแก้ไขปัญหานี้ได้ แต่ตัวเลือกที่ดีกว่าอาจเป็นการประเมินว่าผู้สมัคร LCP รูปภาพต้องโหลดจาก CSS หรือไม่ เมื่อใช้แท็ก <img> คุณจะควบคุมการโหลดรูปภาพที่เหมาะกับวิวพอร์ตได้มากขึ้น ขณะเดียวกันก็อนุญาตให้เครื่องมือสแกนการโหลดล่วงหน้าค้นพบรูปภาพได้
การแทรกทรัพยากรในบรรทัดมากเกินไป
การแทรกในบรรทัดคือแนวทางปฏิบัติที่วางทรัพยากรไว้ภายใน HTML คุณสามารถแทรกสไตล์ชีตในองค์ประกอบ <style>, สคริปต์ในองค์ประกอบ <script> และทรัพยากรอื่นๆ เกือบทั้งหมดโดยใช้การเข้ารหัส base64
การแทรกทรัพยากรในบรรทัดอาจเร็วกว่าการดาวน์โหลดเนื่องจากไม่มีการส่งคำขอแยกต่างหากสำหรับทรัพยากร ซึ่งจะอยู่ในเอกสารและโหลดได้ทันที แต่ก็มีข้อเสียที่สำคัญดังนี้
- หากคุณไม่ได้แคช HTML และแคชไม่ได้หากการตอบกลับ HTML เป็นแบบไดนามิก ระบบจะไม่แคชทรัพยากรที่แทรกในบรรทัด ซึ่งจะส่งผลต่อประสิทธิภาพเนื่องจากทรัพยากรที่แทรกในบรรทัดจะนำมาใช้ซ้ำไม่ได้
- แม้ว่าคุณจะแคช HTML ได้ แต่ทรัพยากรที่แทรกในบรรทัดจะไม่แชร์ระหว่างเอกสาร ซึ่งจะลดประสิทธิภาพการแคชเมื่อเทียบกับไฟล์ภายนอกที่แคชและนำมาใช้ซ้ำได้ทั่วทั้งต้นทาง
- หากคุณแทรกโค้ดมากเกินไป คุณจะทำให้เครื่องมือสแกนการโหลดล่วงหน้าค้นพบทรัพยากรในเอกสารช้าลง เนื่องจากต้องใช้เวลาดาวน์โหลดเนื้อหาที่แทรกโค้ดเพิ่มเติมนั้นนานขึ้น
ลองดูหน้านี้เป็นตัวอย่าง ในบางกรณี ตัวเลือก LCP คือรูปภาพที่ด้านบนของหน้า และ CSS อยู่ในไฟล์แยกต่างหากที่โหลดโดยองค์ประกอบ <link> นอกจากนี้ หน้าเว็บยังใช้แบบอักษรบนเว็บ 4 แบบซึ่งมีการขอเป็นไฟล์แยกต่างหากจากทรัพยากร CSS
<img> แต่เครื่องมือสแกนการโหลดล่วงหน้าจะค้นพบรูปภาพดังกล่าวเนื่องจาก CSS และแบบอักษรที่จำเป็นสำหรับการโหลดหน้าเว็บจะโหลดในทรัพยากรแยกต่างหาก ซึ่งจะไม่ทำให้เครื่องมือสแกนการโหลดล่วงหน้าทำงานล่าช้า
แล้วจะเกิดอะไรขึ้นหาก CSS และแบบอักษรทั้งหมดฝังอยู่ในบรรทัดเป็นทรัพยากร Base64
<img> แต่การแทรก CSS และทรัพยากรแบบอักษร 4 รายการในบรรทัดใน `` ทำให้เครื่องมือสแกนการโหลดล่วงหน้าค้นพบรูปภาพล่าช้าจนกว่าจะดาวน์โหลดทรัพยากรเหล่านั้นจนเสร็จสมบูรณ์
ผลกระทบของการแทรกในบรรทัดส่งผลเสียต่อ LCP ในตัวอย่างนี้ และต่อประสิทธิภาพโดยทั่วไป หน้าเวอร์ชันที่ไม่ได้แทรกอะไรเลยจะแสดงรูปภาพ LCP ในเวลาประมาณ 3.5 วินาที หน้าเว็บที่รวมทุกอย่างไว้ในบรรทัดเดียวกันจะไม่แสดงรูปภาพ LCP จนกว่าจะผ่านไป 7 วินาที
ยังมีปัจจัยอื่นๆ ที่เกี่ยวข้องมากกว่าแค่เครื่องมือสแกนการโหลดล่วงหน้า การแทรกฟอนต์ในบรรทัดไม่ใช่กลยุทธ์ที่ดีเนื่องจาก base64 เป็นรูปแบบที่ไม่มีประสิทธิภาพสำหรับทรัพยากรไบนารี อีกปัจจัยหนึ่งคือระบบจะไม่ดาวน์โหลดทรัพยากรแบบอักษรภายนอก เว้นแต่ CSSOM จะพิจารณาว่าจำเป็น เมื่อฟอนต์เหล่านั้นฝังในบรรทัดเป็น base64 ระบบจะดาวน์โหลดฟอนต์เหล่านั้นไม่ว่าจะจำเป็นสำหรับหน้าปัจจุบันหรือไม่ก็ตาม
การโหลดล่วงหน้าจะช่วยปรับปรุงสิ่งต่างๆ ที่นี่ได้ไหม ได้เลย คุณสามารถโหลดรูปภาพ LCP ล่วงหน้าและลดเวลา LCP ได้ แต่การทำให้ HTML ที่อาจแคชไม่ได้มีขนาดใหญ่เกินไปด้วยทรัพยากรที่ฝังในบรรทัดจะส่งผลเสียต่อประสิทธิภาพด้านอื่นๆ First Contentful Paint (FCP) ก็ได้รับผลกระทบจากรูปแบบนี้เช่นกัน ในหน้าเวอร์ชันที่ไม่มีการแทรกในบรรทัด FCP จะอยู่ที่ประมาณ 2.7 วินาที ในเวอร์ชันที่ทุกอย่างอยู่ในบรรทัดเดียวกัน FCP จะอยู่ที่ประมาณ 5.8 วินาที
โปรดระมัดระวังอย่างยิ่งเมื่อแทรกสิ่งต่างๆ ลงใน HTML โดยเฉพาะทรัพยากรที่เข้ารหัส Base64 โดยทั่วไปเราไม่แนะนำให้ทำเช่นนี้ ยกเว้นในกรณีที่ทรัพยากรมีขนาดเล็กมาก ใช้การแทรกในบรรทัดให้น้อยที่สุด เพราะการแทรกในบรรทัดมากเกินไปอาจทำให้เกิดปัญหาได้
การแสดงผลมาร์กอัปด้วย JavaScript ฝั่งไคลเอ็นต์
ไม่ต้องสงสัยเลยว่า JavaScript ส่งผลต่อ Page Speed อย่างแน่นอน นักพัฒนาซอฟต์แวร์ไม่เพียงแต่ต้องพึ่งพา JavaScript เพื่อให้เกิดการโต้ตอบเท่านั้น แต่ยังมีแนวโน้มที่จะต้องพึ่งพา JavaScript เพื่อแสดงเนื้อหาด้วย ซึ่งจะช่วยให้นักพัฒนาแอปได้รับประสบการณ์ที่ดีขึ้นในบางด้าน แต่ประโยชน์ที่นักพัฒนาแอปได้รับอาจไม่ได้ส่งผลดีต่อผู้ใช้เสมอไป
รูปแบบหนึ่งที่อาจทำให้เครื่องมือสแกนการโหลดล่วงหน้าทำงานไม่ได้คือการแสดงผลมาร์กอัปด้วย JavaScript ฝั่งไคลเอ็นต์
เมื่อเพย์โหลดมาร์กอัปอยู่ใน JavaScript และแสดงผลโดย JavaScript ทั้งหมดในเบราว์เซอร์ ทรัพยากรใดๆ ในมาร์กอัปนั้นจะมองไม่เห็นสำหรับเครื่องมือสแกนการโหลดล่วงหน้า ซึ่งจะทำให้การค้นพบทรัพยากรที่สำคัญล่าช้า และส่งผลต่อ LCP อย่างแน่นอน ในกรณีของตัวอย่างเหล่านี้ คำขอรูปภาพ LCP จะล่าช้าอย่างมากเมื่อเทียบกับประสบการณ์การใช้งานที่แสดงผลฝั่งเซิร์ฟเวอร์ที่เทียบเท่ากันซึ่งไม่ต้องใช้ JavaScript เพื่อให้ปรากฏ
ซึ่งอาจเบี่ยงเบนไปจากจุดมุ่งหมายของบทความนี้เล็กน้อย แต่ผลของการแสดงผลมาร์กอัปในฝั่งไคลเอ็นต์นั้นมีมากกว่าการเอาชนะเครื่องมือสแกนการโหลดล่วงหน้า ประการแรก การใช้ JavaScript เพื่อขับเคลื่อนประสบการณ์ที่ไม่จำเป็นต้องใช้ JavaScript จะทำให้เกิดเวลาในการประมวลผลที่ไม่จำเป็น ซึ่งอาจส่งผลต่อ Interaction to Next Paint (INP) การแสดงผลมาร์กอัปจำนวนมากในไคลเอ็นต์มีแนวโน้มที่จะสร้างงานที่ใช้เวลานานมากกว่าเมื่อเทียบกับมาร์กอัปจำนวนเดียวกันที่เซิร์ฟเวอร์ส่ง สาเหตุของปัญหานี้ (นอกเหนือจากการประมวลผลเพิ่มเติมที่ JavaScript เกี่ยวข้อง) คือเบราว์เซอร์จะสตรีมมาร์กอัปจากเซิร์ฟเวอร์และแบ่งการแสดงผลออกเป็นส่วนๆ ในลักษณะที่มีแนวโน้มที่จะจำกัดงานที่ใช้เวลานาน ในทางกลับกัน มาร์กอัปที่แสดงผลฝั่งไคลเอ็นต์จะได้รับการจัดการเป็นงานเดียวแบบรวมศูนย์ ซึ่งอาจส่งผลต่อ INP ของหน้าเว็บ
วิธีแก้ไขสำหรับสถานการณ์นี้ขึ้นอยู่กับคำตอบของคำถามที่ว่า มีเหตุผลใดที่เซิร์ฟเวอร์ไม่สามารถให้มาร์กอัปของหน้าเว็บได้ แทนที่จะแสดงผลในฝั่งไคลเอ็นต์ หากคำตอบคือ "ไม่" คุณควรพิจารณาใช้การแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) หรือมาร์กอัปที่สร้างขึ้นแบบคงที่หากเป็นไปได้ เนื่องจากจะช่วยให้เครื่องมือสแกนการโหลดล่วงหน้าค้นพบและดึงข้อมูลทรัพยากรที่สำคัญล่วงหน้าได้
หากหน้าเว็บต้องใช้ JavaScript เพื่อแนบฟังก์ชันการทำงานกับมาร์กอัปบางส่วนของหน้า คุณยังคงทำได้ด้วย SSR ไม่ว่าจะใช้ Vanilla JavaScript หรือ Hydration เพื่อให้ได้ผลลัพธ์ที่ดีที่สุดจากทั้ง 2 วิธี
ช่วยให้เครื่องมือสแกนการโหลดล่วงหน้าช่วยคุณได้
เครื่องมือสแกนการโหลดล่วงหน้าเป็นการเพิ่มประสิทธิภาพเบราว์เซอร์ที่มีประสิทธิภาพสูง ซึ่งช่วยให้หน้าเว็บโหลดเร็วขึ้นในระหว่างการเริ่มต้นระบบ การหลีกเลี่ยงรูปแบบที่ขัดขวางความสามารถในการค้นพบทรัพยากรที่สำคัญล่วงหน้าไม่เพียงแต่ทำให้การพัฒนาของคุณง่ายขึ้นเท่านั้น แต่ยังสร้างประสบการณ์ของผู้ใช้ที่ดีขึ้นซึ่งจะให้ผลลัพธ์ที่ดีขึ้นในเมตริกหลายรายการ รวมถึง Web Vitals บางรายการด้วย
สรุปประเด็นสำคัญจากโพสต์นี้มีดังนี้
- เครื่องมือสแกนการโหลดล่วงหน้าของเบราว์เซอร์คือโปรแกรมแยกวิเคราะห์ HTML รองที่สแกนก่อนโปรแกรมหลักหากถูกบล็อกเพื่อค้นหาทรัพยากรที่สามารถดึงข้อมูลได้เร็วขึ้น
- เครื่องมือสแกนการโหลดล่วงหน้าไม่สามารถค้นพบทรัพยากรที่ไม่ได้อยู่ในมาร์กอัปที่เซิร์ฟเวอร์ระบุไว้ในคำขอการนำทางเริ่มต้น วิธีที่อาจทำให้เครื่องมือสแกนการโหลดล่วงหน้าทำงานไม่ได้มีดังนี้ (แต่ไม่จำกัดเพียงเท่านี้)
- การแทรกทรัพยากรลงใน DOM ด้วย JavaScript ไม่ว่าจะเป็นสคริปต์ รูปภาพ สไตล์ชีต หรือสิ่งอื่นๆ ที่ควรอยู่ในเพย์โหลดมาร์กอัปเริ่มต้นจากเซิร์ฟเวอร์
- การโหลดแบบ Lazy Loading รูปภาพหรือ iframe ในครึ่งหน้าบนโดยใช้โซลูชัน JavaScript
- การแสดงผลมาร์กอัปในไคลเอ็นต์ที่อาจมีการอ้างอิงถึงทรัพยากรย่อยของเอกสารโดยใช้ JavaScript
- เครื่องมือสแกนการโหลดล่วงหน้าจะสแกนเฉพาะ HTML เท่านั้น แต่จะไม่ตรวจสอบเนื้อหาของทรัพยากรอื่นๆ โดยเฉพาะ CSS ที่อาจมีการอ้างอิงถึงเนื้อหาที่สำคัญ รวมถึงรายการที่เป็นไปได้สำหรับ LCP
หากคุณไม่สามารถหลีกเลี่ยงรูปแบบที่ส่งผลเสียต่อความสามารถของเครื่องมือสแกนการโหลดล่วงหน้าในการเร่งประสิทธิภาพการโหลดได้ไม่ว่าด้วยเหตุผลใดก็ตาม ให้พิจารณาใช้คำแนะนำทรัพยากร rel=preload หากคุณใช้ rel=preload ให้ทดสอบในเครื่องมือ Lab เพื่อให้แน่ใจว่าได้ผลลัพธ์ตามที่ต้องการ สุดท้ายนี้ อย่าโหลดทรัพยากรล่วงหน้ามากเกินไป เพราะเมื่อคุณจัดลำดับความสำคัญของทุกอย่าง ก็จะไม่มีอะไรสำคัญเลย
แหล่งข้อมูล
- "สคริปต์แบบไม่พร้อมกัน" ที่มีการแทรกสคริปต์ถือว่าเป็นอันตราย
- วิธีที่ตัวโหลดล่วงหน้าของเบราว์เซอร์ทำให้หน้าเว็บโหลดเร็วขึ้น
- โหลดเนื้อหาที่สำคัญไว้ล่วงหน้าเพื่อปรับปรุงความเร็วในการโหลด
- สร้างการเชื่อมต่อเครือข่ายตั้งแต่เนิ่นๆ เพื่อปรับปรุงความเร็วหน้าเว็บที่รับรู้
- การเพิ่มประสิทธิภาพ Largest Contentful Paint