5 Kỹ thuật để thực hiện Lazy Load ảnh giúp tăng Website performance

Cập nhật: Lượt xem: 884 [ Javascript ]

Lazy loading image có nghĩa là tải hình ảnh trên trang web theo kiểu bất đồng bộ - tức là sau khi nội dung được tải đầy đủ thì chúng mới xuất hiện trong trình duyệt.

5 Kỹ thuật để thực hiện Lazy Load ảnh giúp tăng Website performance

Lazy Loading là gì ?

Lazy loading image có nghĩa là tải hình ảnh trên trang web theo kiểu bất đồng bộ - tức là sau khi nội dung được tải đầy đủ thì chúng mới xuất hiện trong trình duyệt. Điều này có nghĩa là nếu người dùng không cuộn hết cỡ, hình ảnh được đặt ở cuối trang sẽ không được tải.

Một số trang web sử dụng phương pháp này, nhưng nó đặc biệt đáng chú ý trên các trang web có ảnh nặng. Thử xem qua các trang yêu thích của bạn có ảnh với độ phân giải cao và bạn sẽ sớm nhận ra cách trang web chỉ tải một số lượng hình ảnh giới hạn. Khi bạn cuộn trang xuống, bạn sẽ thấy hình ảnh tiếp theo nhanh chóng được tải thêm và xuất hiện. Ví dụ với Unsplash.com: khi cuộn trang xuống bạn sẽ thấy hình ảnh được load liên tục với độ phân giải đầy đủ.

Tại sao ta nên quan tâm đến lazy loading images ?

Có một vài lý do khiến bạn nên cân nhắc việc "lazy loading" ảnh cho trang web của mình:

  • Nếu trang web của bạn sử dụng JavaScript để hiển thị nội dung hoặc cung cấp một số chức năng cho người dùng, việc tải DOM một cách nhanh chóng trở nên khá quan trọng. Thông thường các scripts sẽ chờ cho đến khi DOM được tải xong trước khi chúng bắt đầu chạy. Trên một trang web có số lượng hình ảnh đáng kể, lazy loading hoặc load hình ảnh bất đồng bộ - có thể tạo sự khác biệt giữa người dùng staying hoặc leaving trang web của bạn.
  • Vì hầu hết các giải pháp lazy load chỉ hoạt động khi người dùng cuộn đến vị trí nơi hình ảnh sẽ hiển thị, ảnh sẽ không bao giờ được tải nếu người dùng không cuộn đến điểm đó. Điều này có nghĩa là tiết kiệm đáng kể băng thông, mà hầu hết người dùng, đặc biệt là những người truy cập web trên thiết bị di động và có kết nối chậm sẽ rất cảm ơn bạn.

Ok, lazy loading ảnh sẽ có lợi cho performance, nhưng cách tốt nhất để thực hiện việc đó là gì ?

Không có cách nào hoàn hảo.

Nếu bạn làm việc với JavaScript, việc triển khai giải pháp lazy loading của riêng bạn không phải là vấn đề. Không gì cho phép bạn kiểm soát nhiều hơn là tự viết code của chính mình.

Ngoài ra, bạn có thể xem qua năm kỹ thuật thú vị dưới đây.

#1 Lazy Loading Using the Intersection Observer API

Intersection Observer API là một modern interface mà bạn có thể tận dụng để tải hình ảnh và nội dung khác.

Dưới đây là cách MDN giới thiệu API này:

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.

Denys Mishunov có một hướng dẫn tuyệt vời dựa trên Intersection Observer và các lazy loading image sử dụng nó. Dưới đây là giải pháp của anh ấy.

Giả sử bạn muốn tải một thư viện ảnh theo dạng lazy load. Markup cho mỗi hình ảnh sẽ như sau:

<img data-src="image.jpg" alt="test image">

Lưu ý cách đường dẫn đến hình ảnh được chứa bên trong thuộc tính data-src, chứ không phải thuộc tính src. Lý do là nếu sử dụng src có nghĩa là ảnh sẽ tải ngay lập tức, và đó không phải là những gì mà ta muốn.

Trong CSS, ta cung cấp cho mỗi hình ảnh một giá trị min-heigh giả sử là 100px. Điều này cho phép giữ mỗi phần placeholder của ảnh (img element không có thuộc tính src) theo chiều dọc.

img {
  min-height: 100px;
  ...more styles here
}

Trong JavaScript, bạn tạo một config object và đăng ký nó với một intersectionObserver instance:

// create config object: rootMargin and threshold
// are two properties exposed by the interface
const config = {
  rootMargin: '0px 0px 50px 0px',
  threshold: 0
};

// register the config object with an instance
// of intersectionObserver
let observer = new intersectionObserver(function(entries, self) {
  // iterate over each entry
  entries.forEach(entry => {
    // process just the images that are intersecting.
    // isIntersecting is a property exposed by the interface
    if(entry.isIntersecting) {
      // custom function that copies the path to the img
      // from data-src to src
      preloadImage(entry.target);
      // the image is now in place, stop watching
      self.unobserve(entry.target);
    }
  });
}, config);

Cuối cùng, bạn lặp qua tất cả các ảnh của bạn và thêm chúng vào instance iterationObserver này:

const imgs = document.querySelectorAll('[data-src]');
imgs.forEach(img => {
  observer.observe(img);
});

Những ưu điểm của giải pháp này: dễ dàng để thực hiện, nó có hiệu quả và có intersectionObserver để nâng cao khả năng tính toán.

Mặt khác, mặc dù Intersection Observer API được hỗ trợ bởi hầu hết các trình duyệt trong các phiên bản mới nhất của chúng, nhưng nó không được hỗ trợ đồng bộ. May mắn thay, ta có sẵn một polyfill.

Bạn có thể tìm hiểu thêm về Intersection Observer API và chi tiết về việc triển khai này trong bài viết của Denys.

#2 Robin Osborne’s Progressively Enhanced Lazy Loading

Robin Osborne đề xuất một giải pháp khéo léo dựa trên progressive enhancement. Trong trường hợp này là lazy loadchính nó, đạt được bằng cách sử dụng JavaScript, được coi là cải tiến trên HTML và CSS thông thường.

Tại sao lại là progressive enhancement ? Nếu bạn hiển thị hình ảnh bằng cách sử dụng giải pháp JavaScript-base, điều gì sẽ xảy ra nếu JavaScript bị disable hoặc xảy ra lỗi khiến code hoạt động không như mong đợi? Trong trường hợp này, nếu không có progressive enhancement, người dùng có thể không nhìn thấy hình ảnh nào cả.

Bạn có thể xem chi tiết về basic version của giải pháp Osborne tại đây và một giải pháp toàn diện hơn, có tính đến trường hợp mã JavaScript bị lỗi, bạn có thể xem nó tại đây.

Kỹ thuật này có một số ưu điểm:

  • Phương pháp progressive enhancement đảm bảo người dùng luôn có quyền accsess vào content.
  • Nó không chỉ phục vụ cho một tình huống JavaScript không có sẵn, mà còn cho những trường hợp khi JavaScript bị error: tất cả chúng ta đều biết các file script dễ bị lỗi, đặc biệt trong môi trường có một số lượng đáng kể các file đang chạy.
  • Nó thực hiện lazy load hình ảnh khi scroll vì vậy không phải tất cả hình ảnh sẽ được tải nếu người dùng không cuộn đến vị trí mà họ muốn trong trình duyệt.
  • Nó không phụ thuộc vào bất kỳ dependencies bên ngoài nào, do đó không cần framework hoặc plugin nào.

#3 Lozad.js

Một thay thế nhanh chóng và dễ dàng để thực hiện lazy load ảnh là để cho thư viện JS thực hiện hầu hết công việc cho bạn.

Lozad là một trình lazy loading có hiệu suất cao, nhẹ và có thể config được trong JavaScript thuần mà không cần dependencies. Bạn có thể sử dụng nó để tải hình ảnh, video, iframe và nhiều thứ khác, đồng thời nó cũng sử dụng Intersection Observer API.

Bạn có thể include Lozad với npm / Yarn và import nó bằng cách sử dụng gói module mà bạn lựa chọn:

npm install --save lozad

yarn add lozad
import lozad from 'lozad';

Ngoài ra, bạn có thể tải xuống thư viện bằng CDN và thêm nó vào cuối trang HTML trong thẻ <script>: <script src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>

Tiếp theo, để triển khai cơ bản, hãy thêm class lozad vào trong thẻ img: <img class="lozad" data-src="img.jpg">

Cuối cùng, khởi tạo Lozad trong JS của bạn:

const observer = lozad();
observer.observe();

Bạn sẽ tìm thấy tất cả các chi tiết về cách bạn có thể sử dụng thư viện trên Lozad GitHub.

Nếu bạn không muốn đi sâu vào hoạt động của  Intersection Observer API hoặc bạn đang tìm cách triển khai nhanh chóng áp dụng cho nhiều loại nội dung khác nhau, Lozad là một lựa chọn tuyệt vời. Nhưng hãy chú ý đến sự hỗ trợ của trình duyệt và cuối cùng tích hợp thư viện này với một polyfill cho Intersection Observer API.

#4 Lazy Loading with Blurred Image Effect

Nếu bạn là một "medium reader", bạn chắc chắn đã nhận thấy cách trang web tải hình ảnh chính bên trong một bài đăng. Điều đầu tiên bạn thấy là bản sao có độ phân giải thấp, mờ, trong khi phiên bản có độ phân giải cao của nó đang được tải xuống dạng lazy loading.

blur-image
Ảnh lúc lazy load

 

Ảnh sau khi load xong

Bạn có thể thực hiện lazy loading image với hiệu ứng làm mờ thú vị này theo một số cách. Kỹ thuật yêu thích của tôi là của Craig Buckler. Đây là một số ưu điểm của cách này:

  • Hiệu suất: chỉ 463 byte CSS và 1,007 byte code JavaScript được rút gọn.
  • Hỗ trợ cho màn hình retina.
  • Dependency-free: không yêu cầu jQuery hoặc các libraries và frameworks.
  • Update dần để phù hợp các trình duyệt cũ hơn và viễ JavaScript không hoạt động. Bạn có thể đọc tất cả về nó trong bài viết How to Build Your Own Progressive Image Loader và download code trên repo GitHub của dự án.

#5 Yall.js

Yall là một feature-packed lazy loading dành cho hình ảnh, video và iframe. Cụ thể hơn, nó sử dụng Intersection Observer API và fall back thông minh trong việc handler các sự kiện truyền thống khi cần thiết.

Khi include Yall, bạn cần khởi tạo nó như sau:

<script src="yall.min.js"></script>
<script>
  document.addEventListener("DOMContentLoaded", yall);
</script>

Tiếp theo, để lazy load một element img đơn giản, thì tất cả những gì bạn cần làm là:

<img class="lazy" src="placeholder.jpg" data-src="image-to-lazy-load.jpg" alt="Alternative text to describe image.">

Có một số lưu ý:

  • Bạn thêm class lazy vào element
  • Value của  src là một placeholder image
  • Đường dẫn đến hình ảnh bạn muốn lazy load nằm bên trong thuộc tính data-src

Những lợi ích của Yall:

  • Hiệu suất tuyệt vời với Intersection Observer API
  • Hỗ trợ trình duyệt tuyệt vời (hỗ trợ IE11)
  • Không cần dependencies khác. Để tìm hiểu thêm về những gì Yall có thể cung cấp và để có thể triển khai một cách phức tạp hơn, bạn có thể xem thêm trên GitHub.

Loading...