แม้ว่าการโหลดแบบ Lazy Loading รูปภาพและวิดีโอจะให้ผลดีด้านประสิทธิภาพและวัดผลได้ แต่คุณไม่ควรมองข้าม ถ้าคุณเข้าใจผิด คุณอาจได้รับ ผลที่ตามมาโดยไม่เจตนา ดังนั้น คุณจึงควรตระหนักถึงข้อกังวลต่างๆ ต่อไปนี้
คำนึงถึงเส้นแบ่ง
การโหลดทรัพยากรสื่อทุกรายการในหน้าเว็บด้วย JavaScript ถึงจะห้ามใจยาก แต่คุณก็ต้องอดใจรอ ตำแหน่งที่อยู่ครึ่งหน้าบนไม่ควรถูกโหลดแบบ Lazy Loading ทรัพยากรดังกล่าวควรถือเป็นเนื้อหาสำคัญ และควรโหลดตามปกติ
การโหลดแบบ Lazy Loading จะทำให้การโหลดทรัพยากรล่าช้าลงจนกว่า DOM จะมีการโต้ตอบเมื่อสคริปต์โหลดเสร็จแล้วและเริ่มต้นการดำเนินการ สำหรับรูปภาพที่อยู่ครึ่งหน้าล่างก็ทำได้ แต่ทรัพยากรสำคัญในครึ่งหน้าบนควรโหลดด้วยองค์ประกอบ <img>
มาตรฐานเพื่อให้แสดงได้โดยเร็วที่สุด
แน่นอนว่าตำแหน่งครึ่งหน้าบนจะไม่ชัดเจนนักในปัจจุบันเมื่อมีการเข้าชมเว็บไซต์บน หน้าจอขนาดต่างๆ มากมาย ตำแหน่งครึ่งหน้าบนของแล็ปท็อปอาจวางอยู่ด้านล่างบนอุปกรณ์เคลื่อนที่ ไม่มีคำแนะนำแก้กระสุนเพื่อจัดการกับเรื่องนี้ อย่างเหมาะสมในทุกสถานการณ์ คุณจะต้องจัดทำคลังเนื้อหาสำคัญของหน้าเว็บ และโหลดรูปภาพเหล่านั้นในรูปแบบแฟชั่นทั่วไป
นอกจากนี้ คุณอาจไม่ต้องการความเข้มงวดกับเส้นแบ่งครึ่งเหมือนเกณฑ์สำหรับการทริกเกอร์การโหลดแบบ Lazy Loading การสร้างโซนบัฟเฟอร์ในช่วงครึ่งหน้าล่างอาจเหมาะสำหรับวัตถุประสงค์ของคุณมากกว่า เพื่อให้รูปภาพเริ่มโหลดได้ดีก่อนที่ผู้ใช้จะเลื่อนรูปภาพเข้าสู่วิวพอร์ต ตัวอย่างเช่น Intersection Observer API ช่วยให้คุณระบุพร็อพเพอร์ตี้ rootMargin
ในออบเจ็กต์ตัวเลือกได้เมื่อสร้างอินสแตนซ์ IntersectionObserver
ใหม่ การดำเนินการนี้จะทำให้องค์ประกอบมีบัฟเฟอร์ ซึ่งจะทริกเกอร์พฤติกรรมการโหลดแบบ Lazy Loading ก่อนที่องค์ประกอบจะอยู่ในวิวพอร์ต
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
// lazy-loading image code goes here
}, {
rootMargin: "0px 0px 256px 0px"
});
หากค่าของ rootMargin
ดูคล้ายกับค่าที่คุณระบุสำหรับพร็อพเพอร์ตี้ CSS margin
ก็เป็นเช่นนั้น ในกรณีนี้ ขอบด้านล่างขององค์ประกอบที่สังเกตได้ (วิวพอร์ตของเบราว์เซอร์โดยค่าเริ่มต้น แต่สามารถเปลี่ยนเป็นองค์ประกอบที่เฉพาะเจาะจงโดยใช้พร็อพเพอร์ตี้ root
) กว้างขึ้นเป็น 256 พิกเซล ซึ่งหมายความว่าฟังก์ชันเรียกกลับจะทํางานเมื่อองค์ประกอบรูปภาพอยู่ภายในระยะ 256 พิกเซลของวิวพอร์ต และรูปภาพจะเริ่มโหลดก่อนที่ผู้ใช้จะเห็นภาพ
หากต้องการผลลัพธ์เดียวกันนี้ในเบราว์เซอร์ที่ไม่รองรับ "Intersection Observe" ให้ใช้โค้ดการจัดการเหตุการณ์การเลื่อนและปรับการตรวจสอบ getBoundingClientRect
เพื่อรวมบัฟเฟอร์
การเปลี่ยนเลย์เอาต์และตัวยึดตำแหน่ง
สื่อที่โหลดแบบ Lazy Loading อาจทำให้เกิดการเปลี่ยนเลย์เอาต์หากไม่ได้ใช้ตัวยึดตำแหน่ง การเปลี่ยนแปลงเหล่านี้อาจทำให้ผู้ใช้เกิดความสับสนและทำให้เกิดความยุ่งยากในการใช้งานเลย์เอาต์ DOM ที่มีราคาแพงซึ่งใช้ทรัพยากรของระบบและทำให้เกิดความยุ่งยาก อย่างน้อยที่สุด ให้พิจารณาใช้ตัวยึดตำแหน่งสีทึบที่มีขนาดเดียวกันกับรูปภาพเป้าหมาย หรือใช้เทคนิคอย่างเช่น LQIP หรือ SQIP ที่บอกใบ้เนื้อหาในรายการสื่อก่อนที่จะโหลด
สำหรับแท็ก <img>
ในขั้นต้น src
ควรชี้ไปยังตัวยึดตำแหน่งจนกว่าจะอัปเดตแอตทริบิวต์ด้วย URL ของรูปภาพสุดท้าย ใช้แอตทริบิวต์ poster
ในองค์ประกอบ <video>
เพื่อชี้ไปยังรูปภาพตัวยึดตำแหน่ง นอกจากนี้ ให้ใช้แอตทริบิวต์ width
และ
height
ทั้งในแท็ก <img>
และ <video>
วิธีนี้ช่วยให้มั่นใจว่าการเปลี่ยนจากตัวยึดตำแหน่งเป็นรูปภาพสุดท้ายจะไม่เปลี่ยนขนาดที่แสดงผลขององค์ประกอบเมื่อโหลดสื่อ
ความล่าช้าในการถอดรหัสรูปภาพ
การโหลดรูปภาพขนาดใหญ่ใน JavaScript แล้ววางลงใน DOM อาจเชื่อมโยงเทรดหลัก ทำให้อินเทอร์เฟซผู้ใช้ไม่ตอบสนองเป็นระยะเวลาสั้นๆ ขณะที่ถอดรหัส การถอดรหัสรูปภาพแบบไม่พร้อมกันโดยใช้เมธอด decode
ก่อนการแทรกรูปภาพลงใน DOM จะช่วยลดความยุ่งยากประเภทนี้ได้ แต่โปรดระวัง: มีให้บริการในบางพื้นที่เท่านั้นและช่วยเพิ่มความซับซ้อนให้กับตรรกะการโหลดแบบ Lazy Loading
หากต้องการใช้ คุณจะต้องตรวจสอบก่อน ด้านล่างนี้แสดงวิธีใช้ Image.decode()
พร้อมทางเลือกสำรอง
var newImage = new Image();
newImage.src = "my-awesome-image.jpg";
if ("decode" in newImage) {
// Fancy decoding logic
newImage.decode().then(function() {
imageContainer.appendChild(newImage);
});
} else {
// Regular image load
imageContainer.appendChild(newImage);
}
ไปที่ลิงก์ CodePen นี้เพื่อดูโค้ดที่คล้ายกับตัวอย่างนี้ หากรูปภาพส่วนใหญ่ของคุณค่อนข้างเล็ก ก็อาจไม่ได้ช่วยอะไรมากนัก แต่จะช่วยลดความยุ่งยากได้ถ้าการโหลดรูปภาพขนาดใหญ่แบบ Lazy Loading แล้วแทรกลงใน DOM
เมื่อเนื้อหาไม่โหลด
บางครั้งทรัพยากรสื่อโหลดไม่สำเร็จด้วยเหตุผลหนึ่งหรืออีกเหตุผลหนึ่ง และเกิดข้อผิดพลาดขึ้น กรณีนี้อาจเกิดขึ้นเมื่อใด ขึ้นอยู่กับสถานการณ์สมมติต่อไปนี้ คุณมีนโยบายการแคช HTML เป็นระยะเวลาสั้นๆ (เช่น 5 นาที) และผู้ใช้เข้าชมเว็บไซต์หรือผู้ใช้เปิดแท็บค้างทิ้งเป็นระยะเวลานาน (เช่น หลายชั่วโมง) และกลับมาอ่านเนื้อหา เมื่อถึงจุดหนึ่งของกระบวนการนี้ ก็มีการทำให้ใช้งานได้อีกครั้ง ในระหว่างการทำให้ใช้งานได้นี้ ชื่อของทรัพยากรรูปภาพจะเปลี่ยนเนื่องจากการกำหนดเวอร์ชันตามแฮช หรือถูกนำออกพร้อมกัน เมื่อผู้ใช้โหลดรูปภาพแบบ Lazy Loading ทรัพยากรจะไม่พร้อมใช้งาน ทำให้ไม่สามารถโหลดได้
แม้ว่ากรณีเหล่านี้จะเกิดขึ้นไม่บ่อยนัก แต่ขอแนะนำให้คุณเตรียมแผนสำรองไว้ในกรณีที่การโหลดแบบ Lazy Loading ล้มเหลว สำหรับรูปภาพ วิธีแก้ไขอาจมีลักษณะดังนี้
var newImage = new Image();
newImage.src = "my-awesome-image.jpg";
newImage.onerror = function(){
// Decide what to do on error
};
newImage.onload = function(){
// Load the image
};
การตัดสินใจของคุณในกรณีที่เกิดข้อผิดพลาดขึ้นอยู่กับใบสมัครของคุณ ตัวอย่างเช่น คุณอาจแทนที่พื้นที่ตัวยึดตำแหน่งรูปภาพด้วยปุ่มที่อนุญาตให้ผู้ใช้ลองโหลดรูปภาพอีกครั้ง หรือเพียงแสดงข้อความแสดงข้อผิดพลาดในพื้นที่ตัวยึดตำแหน่งรูปภาพ
สถานการณ์อื่นๆ ก็อาจเกิดขึ้นได้เช่นกัน ไม่ว่าคุณจะทำอะไร เราไม่ควรส่งสัญญาณแจ้งผู้ใช้เมื่อเกิดข้อผิดพลาดขึ้น และหากเป็นไปได้ให้พวกเขาดำเนินการตามนั้นหากเกิดข้อผิดพลาด
ความพร้อมใช้งานของ JavaScript
คุณไม่ควรคิดว่า JavaScript พร้อมใช้งานตลอดเวลา หากคุณจะโหลดรูปภาพแบบ Lazy Loading ลองเสนอมาร์กอัป <noscript>
ที่จะแสดงรูปภาพในกรณีที่ JavaScript ไม่พร้อมใช้งาน ตัวอย่างสำรองที่ง่ายที่สุดที่เป็นไปได้คือการใช้องค์ประกอบ <noscript>
เพื่อแสดงรูปภาพหาก JavaScript ปิดอยู่
หากปิด JavaScript ไว้ ผู้ใช้จะเห็นทั้งรูปภาพตัวยึดตำแหน่งและรูปภาพที่มีองค์ประกอบ <noscript>
ในการแก้ปัญหานี้ ให้วางคลาสของ no-js
ในแท็ก <html>
ดังนี้
<html class="no-js">
จากนั้นวางสคริปต์ในหน้า 1 บรรทัดใน <head>
ก่อนที่จะมีการขอสไตล์ชีตใดๆ ผ่านแท็ก <link>
ซึ่งนำคลาส no-js
ออกจากองค์ประกอบ <html>
หาก JavaScript เปิดอยู่
<script>document.documentElement.classList.remove("no-js");</script>
สุดท้าย ใช้ CSS บางส่วนเพื่อซ่อนองค์ประกอบด้วยคลาสแบบ Lazy Loading เมื่อ JavaScript ไม่พร้อมใช้งาน
.no-js .lazy {
display: none;
}
การทำเช่นนี้ไม่ได้ป้องกันการโหลดรูปภาพตัวยึดตำแหน่ง แต่ผลลัพธ์เป็นที่ต้องการมากกว่า ผู้ใช้ที่ปิด JavaScript จะได้รับสิ่งที่นอกเหนือจากรูปภาพตัวยึดตำแหน่ง ซึ่งดีกว่าตัวยึดตำแหน่งและไม่พบเนื้อหารูปภาพที่มีความหมายเลย