แม้ว่ารูปภาพและวิดีโอที่ใช้การโหลดแบบ Lazy Loading จะให้ประโยชน์ด้านประสิทธิภาพในเชิงบวกและวัดผลได้ แต่ก็ไม่ควรพิจารณาอย่างรอบคอบ หากคุณทำผิด อาจเกิดผลกระทบโดยไม่เจตนา ดังนั้น เราจึงควรคำนึงถึง ข้อกังวลต่อไปนี้
คำนึงถึงเส้นแบ่ง
คุณอาจอยากโหลดทรัพยากรสื่อทุกแหล่งในหน้าด้วย JavaScript อย่าง Lazy Loading แต่เราจำเป็นต้องพยายามอย่างหนักหน่วง สิ่งใดก็ตามที่อยู่ครึ่งหน้าบนไม่ควรเป็นแบบ 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 พิกเซล ซึ่งหมายความว่าฟังก์ชัน Callback จะทำงานเมื่อองค์ประกอบรูปภาพอยู่ภายในขนาด 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 เมื่อ JavaScript ไม่พร้อมใช้งาน ดังนี้
.no-js .lazy {
display: none;
}
แต่ไม่ได้ป้องกันไม่ให้รูปภาพตัวยึดตำแหน่งโหลด แต่ผลที่ได้จะเป็นที่ต้องการมากกว่า ผู้ใช้ที่ปิดใช้ JavaScript จะได้รับสิ่งที่นอกเหนือจากรูปภาพตัวยึดตำแหน่ง ซึ่งดีกว่าตัวยึดตำแหน่งและไม่มีเนื้อหารูปภาพที่มีความหมายเลย