Lazy loading เป็นเทคนิคหนึ่งในการทำให้เว็บแสดงผลได้ไวขึ้น หลักการก็คือ แทนที่จะส่ง request ไปเรียกไฟล์ assets ทั้งหมดที่ใช้ในเพจพร้อมกันตั้งแต่ตอนโหลด ก็เปลี่ยนเป็นการส่ง request ออกไปเมื่อ “จำเป็น” เท่านั้น
สำหรับไฟล์ JavaScript/CSS ก็ส่ง request ออกไปก็ต่อเมื่อจะได้ใช้งาน ส่วนไฟล์รูปภาพ ก็คือการส่ง request ออกไปก็ต่อเมื่อต้องแสดงผลบนหน้าจอ
การใช้ lazy loading กับไฟล์จำพวกรูปภาพ เป็นเทคนิคที่นำมาใช้ได้ง่าย และส่งผลดีอย่างเห็นได้ชัด ถ้าในภาษานักลงทุนก็อาจจะบอกว่า ลงทุนน้อย แต่ได้ผลตอบแทนค่อนข้างดี (แต่ก็ยังมีความเสี่ยงนะ)
สำหรับบล็อกนี้ ผมใช้ JavaScript library ชื่อว่า LazyLoad เพื่อ lazy load รูปภาพ สำหรับบางโพสต์ที่มีรูปเยอะๆ อยากจะมาแชร์บันทึกครับผม
นอกจาก LazyLoad แล้วก็ยังมี library อีกตัวชื่อว่า lazysizes ที่ดูเหมือนจะได้รับความนิยมเหมือนกัน (ดูจากจำนวนดาวใน GitHub) แต่ผมยังไม่เคยใช้ครับ
LazyLoad
หลักการของ LazyLoad คือจะโหลด asset เมื่อมันเข้ามาอยู่ใน viewport หรือเมื่อเรา scroll ลงไปถึง viewport นั่นเอง
asset ที่รองรับคือ รูปภาพ วิดีโอ และ content ใน iframe
วิธีการใช้งาน ใน readme ของ repo เขียนไว้ละเอียดดีมาก มีตัวอย่างให้ดูหลายๆ use case ที่ผมเลือกใช้เป็น Async script + auto initilization
ใส่ code เหล่านี้ไว้ส่วนล่างสุดของ HTML ก่อนปิด </body>
<script>
window.lazyLoadOptions = {
elements_selector: '.lazy'
}
</script>
<script async src="/js/lazyload.min.js"></script>
</body>
ส่วน tag <img>
ก็ต้องเปลี่ยนจาก src
attribute เป็น data-src
<img class="lazy" data-src="/path/to/image" alt="alt">
เมื่อรูปนี้เข้ามาอยู่ใน viewport LazyLoad จะทำการเปลี่ยน attribute data-src
ให้เป็น src
และก็จะทำให้ browser ส่ง request ออกไปโดยอัตโนมัติ
ต้องทำงานได้โดยที่ไม่มี JavaScript
แน่นอนว่าการใช้ library LazyLoad นั้น ต้องใช้ JavaScript
สำหรับ browser ที่ไม่มี JavaScript หรือ user ไม่ได้เปิด JavaScript ไว้
รูปนั้นก็จะไม่ขึ้นเลย เพราะ browser มองว่าไม่มี attribute src
วิธีแก้ก็คือต้องใส่ fallback ใน tag <noscript>
ด้วย tag <img>
ธรรมดาแบบนี้
<img class="lazy" data-src="/path/to/image" alt="alt">
<noscript>
<img src="/path/to/image" alt="alt">
</noscript>
วิธีนี้ทำให้รูปใน content แสดงผลได้ตามปกติไม่ว่าจะเปิด JavaScript ไว้หรือไม่ เพียงแต่ก็จะไม่ได้ประโยชน์จาก lazy load เท่านั้นเอง (ก็ยังดีกว่ารูปไม่ขึ้นเลย)
(ทดสอบการปิด JavaScript ใน Chrome DevTools โดยการเปิด command palette (CMD + Shift + P) แล้วหา disable javascript
แล้ว refresh)
โชคดีที่มี shortcode ใน Hugo
ผมเลยสร้าง shortcode อีกอันสำหรับใส่รูปที่ต้องการใช้ lazy load ใน content ได้
ไม่ต้องไปตามใส่ tag <noscript>
ให้กับทุกรูป
{{< picture-lazy src="/path/to/image" alt="test" />
วัดผล
วัดผลโดยใช้แท็บ Audits (Lighthouse) ใน Chrome DevTools จากโพสต์: Deploy blog อัตโนมัติด้วย Netlify ที่มีรูปภาพในโพสต์เยอะๆ หลายๆ ครั้ง
ผลออกมา แต่ละครั้งได้ค่าไม่เท่ากัน แต่มีแนวโน้มไปทางเดียวกันคือ
- คะแนน performance แบบใช้ LazyLoad จะเยอะกว่า
- ดูจาก screenshot ที่ Lighthouse บันทึกไว้ แบบใช้ LazyLoad จะเริ่ม render content ได้ไวกว่า
ก่อน
หลัง
นอกจากนั้นคือ ช่วยประหยัด bandwidth สำหรับ user ที่ใช้ 3g/4g ไม่ต้องเสียเวลาและค่าเน็ตมือถือ รอโหลดรูปทั้งหมดก่อนที่จะเริ่มอ่านบทความได้
สำหรับผมถือว่าเป็นการ ลงทุนน้อย แต่ได้ผลตอบแทนค่อนข้างดี
แต่อย่างไรก็ตาม ถ้าจะใช้ในเว็บ production จริงจัง ก็ยังมีเรื่องอื่นให้ต้องคำนึงถึงอยู่ด้วย ตามไปดูได้ในส่วน Tips & Tricks ของ LazyLoad ได้ครับ