Lazy loading là gì? Cải thiện tốc độ website dùng Lazy loading

Lazy loading

Tốc độ website là một trong những yếu tố ảnh hưởng “trực tiếp” đến trải nghiệm người dùng trên trang.  Một phương pháp giúp trang web tối ưu web và hiệu suất người dùng khi truy cập vào chính là Lazy Loading. Để hiểu rõ hơn về công nghệ này, hãy cùng MrH tìm hiểu tại bài viết dưới đây nhé!

Bạn có thể dễ dàng nhận ra khi xem trên Facebook. Lần đầu mở trang web Facebook lên bạn sẽ đọc được 1 số lượng ít tin. Khi bạn cuộn đến cuối trang thì Facebook sẽ bắt đầu tải 1 số lượng tin tiếp theo để hiển thị. Đó chính là Lazy loading.

Lazy loading là gì?

Lazy loading là kỹ thuật tối ưu khi làm website, trì hoãn tải các dữ liệu không quan trọng vào thời điểm tải trang. Hiểu một cách đơn giản là nó chỉ load dữ liệu hiển thị khi bạn cần sử dụng đến chúng.

Khi website có nhiều dữ liệu cần phải tải, nếu phải tải hết vào cùng một thời điểm sẽ khiến tốc độ tải trang dễ bị chậm, gây ra trải nghiệm người dùng kém, dẫn đến thoát trang. Chính vì vậy, người dùng lướt (scroll) đến đâu sẽ tải đến đó là cách mà lazy loading được áp dụng khi tối ưu một trang web.

Lazy loading: có một điều quan trọng các bạn cần hiểu là nó chỉ là một khái niệm (ý tưởng) thôi nhé. Nghĩa là nó có thể được sử dụng trong nhiều trường hợp khác nhau, nhiều ngôn ngữ lập trình khác nhau, và mỗi nơi lại có nhiều cách implement khác nhau, nhưng ý tưởng thì cũng tương đối giống nhau thôi.

Khi đề cập đến ảnh, thì “không quan trọng” thường đồng nghĩa với “ngoài màn hình / off-screen”. Nếu bạn sử dụng Lighthouse và kiểm tra một số cơ hội cải thiện, bạn có thể thấy một vài hướng dẫn trong địa hạt này ở dạng kiểm tra các ảnh ngoài màn hình. Lazy loading có thể áp dụng cho bất cứ resource nào trên 1 page, thậm chí là file JavaScript.

Một ví dụ về Lazy Loading ảnh trong thực tế. Một ảnh chiếm chỗ được tải ở bên trái vào thời điểm tải trang, và khi được cuộn đến viewport, ảnh cuối cùng (ảnh thực) được tải vào thời điểm phù hợp để thay thế ảnh chiếm chỗ.

Nói nôm na, Lazy loading chính là khi cần mới xuất hiện. Các dữ liệu sẽ xuất hiện khi lướt đến để tránh làm chậm tốc độ tải trang.

Lý do nên sử dụng lazy loading?

Lazy loading là một trong những kỹ thuật tối ưu hiệu suất website hiệu quả được sử dụng phổ biến hiện nay. Nếu như lưu lượng truy cập là một trong những mối quan tâm của bạn thì việc sử dụng Lazy loading là không thể thiếu cho trang web.

Tiết kiệm cho bộ nhớ

Việc lazy loading tải dữ liệu cần thiết cho trang và trì hoãn các dữ liệu chưa sử dụng đến giúp tiết kiệm dung lượng bộ nhớ, CPU, băng thông… tránh tình trạng quá tải trang khiến một số lỗi dễ xảy ra khi vận dụng tối đa công suất tải trang của nó.

Áp dụng Lazy Loading để “trì trệ” các dữ liệu chưa cần sẽ tiết kiệm bộ nhớ, CPU, GPU,.. và hoàn toàn có ích với những users sử dụng trình duyệt trên thiết bị di động có kết nối chậm.

Đối với người dùng thì đặc biệt có ích vì trên các trình duyệt trên thiết bị di động tốc độ kết nối sẽ chậm hơn so với desktop.

Mang lại hiệu suất tốt

Khi bạn viết code 100 tấm ảnh chứa trong các thẻ img, browser sẽ tải về tất cả các tấm ảnh ấy, dù cho user có muốn hay không, hay có scroll và xem hết 100 tấm ảnh ấy không.

Lazy Loading với chức năng chỉ tải dữ liệu khi users lướt đến sẽ trả kết quả cho users nhanh hơn, cũng như cải thiện sự “chuyên nghiệp” của trang web, giúp trang web “bảo toàn” tất cả dữ liệu.

Hãy tưởng tượng xem nếu một website trong cùng một lúc tải hết từ đầu đến cuối nếu có lưu lượng truy cập cao chắc chắn phải cần đợi thời gian khá lâu thì mới hiển thị hết tất cả, còn chưa kể trang bị lag và phải load lại từ đầu.

Nhưng khi có lazy loading bạn sẽ thấy có sự cải thiện về tốc độ tải cũng như lượng dữ liệu sẽ được giảm xuống, bảo toàn dữ liệu cho trang. Điều này làm trang web “dễ thở” hơn khi tải trang.

Cải thiện kết quả SEO

Một website được đánh giá là SEO thành công thì bắt buộc không thể thiếu yếu tố cơ bản là trang web đó được đảm bảo về tốc độ tải trang và trải nghiệm người dùng hài lòng khi truy cập web nhanh hơn.

Khi có Lazy Loading tốc độ tải được cải thiện giúp giảm tỷ lệ thoát xuống tốt cho việc tối ưu SEO Onpage. Nhờ vậy mà Google nhận thấy trang web của bạn uy tín, nhận được nhiều truy cập từ người dùng và cải thiện chuyển đổi trên trang tốt sẽ xếp hạng trang web ở vị trí cao khi tìm kiếm.

Nâng cao trải nghiệm người dùng

Dù làm gì đi nữa thì mục đích cuối cùng của website tạo ra vẫn hướng đến là người dùng. Vì vậy, trải nghiệm người dùng rất quan trọng đối với một website. Có nhiều tiêu chí đánh giá một trang web có đáp ứng được trải nghiệm người dùng hay không. Và tốc độ tải trang là một trong số những tiêu chí đó.

Lazy loading giảm thiểu lỗi bị ẩn dữ liệu, cải thiện tốc độ tải nhanh hơn đảm bảo người dùng truy cập nhanh những gì cần tìm. Khi trải nghiệm tốt, tăng cơ hội giữ chân người dùng trên trang lâu hơn và tỉ lệ quay lại trang web cũng tốt hơn.

Tăng điểm số đánh giá web

Lazy Loading giúp trang web của bạn tải nhanh hơn bởi không tốn thời gian để đồng bộ tất cả dữ liệu, từ đó sẽ tăng điểm số đánh giá trang web của bạn dựa trên các thang đo tốc độ tải trang.

Một khi tốc độ tải trang nhanh hơn cũng đồng nghĩa với việc điểm số đánh giá của công cụ chấm cho website sẽ cao hơn. Mặt khác, Google ưu tiên các trang web tải nhanh hơn những trang web chậm, bởi các trang web tải nhanh sẽ cho người dùng thông tin nhanh hơn, đạt được nhiều lượt truy cập hơn.

Bản chất của Lazy Loading Images.

Bạn nói với browser rằng: “Này browser, tao có các tấm ảnh này, nhưng mày đừng tải nó nhé. Khi nào user scroll đến vị trí tấm ảnh nào, thì mày hãy tải tấm ảnh ấy ngay”. Có 3 vấn đề cốt lõi mà mình tô đậm trong đoạn hội thoại trên.

1. Đừng tải: Khi bạn gán thuộc tính src cho thẻ img, browser sẽ tải nó ngay và luôn, nên để bảo browser đừng tải nó, đơn giản là chúng ta đừng sử dụng thuộc tính src

2. scroll đến vị trí tấm ảnh: để kiểm tra được điều này, developers thường dùng những thứ gọi là “trick” như sự kiện scroll, hay mới hơn là “Intersection Observer API”. Mình sẽ code cả 2 cách trên trong phần tiếp theo nhé.

3. tải tấm ảnh: để bắt browser tải tấm ảnh, chúng ta chỉ đơn giản là copy tấm ảnh từ data-src vào thuộc tính src (hoặc background-image cho ảnh background) thôi.

Lazy-load ảnh background cũng tuân theo các bước như trên, chỉ là thay vì copy từ data-src vào src, chúng ta copy vào background-image là được. Các ví dụ bên dưới mình đều ứng dụng cho cả 2 trường hợp src và background-image nhé.

Để sử dụng lazy load image trên một trang thường có 2 cách như sau: sử dụng thẻ và sử dụng thuộc tính background-image của CSS.

Lazy Loading Images qua thẻ

Thẻ <img/>  với định dạng cơ bản:

< img src=”/path/to/some/image.jpg” />

Trình duyệt đọc src attribute để trigger đến việc tải ảnh. Vì vậy, chúng ta sẽ move link image qua 1 attribute khác để ngăn chặn việc tải ảnh này. Một ví dụ cụ thể về sử dụng data-src attribute mà bạn hoàn toàn có thể đặt bất cứ tên attr nào.

< img data-src=”https://ik.imagekit.io/demo/default-image.jpg” />

Khi trì hoãn được load Images tức thời thì bạn không thể bỏ qua bước thông báo cho trình duyệt khi nào nên hiển thị hình ảnh bằng cách sử dụng javascript để nắm bắt hành vi người dùng và thêm liên kết datasrc trở lại với attr src.

Lazy Loading Images sử dụng thuộc tính background-image

Với background-image, trình duyệt xây dựng cây DOM với CSSDOM và kiểm tra xem kiểu CSS có được áp dụng cho nút DOM hiện tại hay không. Nếu DOM hiện tại có hình nền, trình duyệt sẽ tải hình ảnh đó. Như với src attr, bạn phải thiết lập cấu hình DOM với giá trị là background-image: none, sau đó giá trị được thay đổi khi cần thiết.

Điểm chung của 2 trường hợp trên đều cần có class để trigger đến người dùng thông qua background-image.

Ưu nhược điểm lazy loading

Như đã tìm hiểu ở trên, chúng ta có thể thấy tác động tích cực nhất mà lazy loading mang lại là cải thiện hiệu suất trang web. Bởi chức năng này chỉ tải những nội dung cần thiết nhất đến với user, hạn chế được sự chậm trễ, lỗi trang khi tải quá nhiều dữ liệu.

Lazy loading thật không hổ danh là kỹ thuật tối ưu hiệu suất trang web được sử dụng nhiều nhất hiện nay, nhờ vậy mà bạn không mất chi phí băng thông cho những thông tin chưa được tiếp cận đến. Nếu như website của bạn đang gặp vấn đề về tốc độ tải trang thì lazy loading là một giải pháp đáng cân nhắc.

Không vì ưu điểm lazy loading mang lại quá nổi trội mà chúng ta quên đi nhược điểm của nó.

Nếu sử dụng lazy loading có thể dẫn đến sự nhấp nháy của phần nội dung bị thiếu khi người dùng truy cập vào trang.
Website muốn áp dụng lazy loading thì quá trình áp dụng đòi hỏi nhiều Javascript hơn, phức tạp, dễ xảy ra lỗi hơn.
Nếu javascript không được tải xuống hoặc không chạy do lỗi kết nối mạng, dữ liệu sẽ được khởi lệnh lazy loading sẽ không được hiển thị.

Kĩ thuật 1: lazy-load chính thống và hiện đại

Chém gió hơi nhiều rồi, mình đi vào code ngay nhé. Thay vì đi ngược từ cách “cổ xưa” cho đến cách “hiện đại”, mình xin giới thiệu về cách hiện đại trước. Cách này là cách chính thống (nghĩa là nó không phải trick), bạn sẽ không cần bất kì dòng Javascript nào, hay bất kì config gì phức tạp. Điều duy nhất bạn làm là báo cho browser biết tấm ảnh nào cần lazy-load là xong, với thuộc tính loading

Thuộc tính loading có 3 giá trị là lazyeager và auto

  • lazy: browser cần lazy-load tấm ảnh này
  • eager: browser cần tải tấm ảnh này ngay lập tức (hoặc càng sớm càng tốt). Nếu tấm ảnh đang được load với cơ chế lazy mà bạn đổi nó sang eager thì nó sẽ lập tức tải ngay.
  • auto: browser sẽ quyết định việc có nên lazy-load ảnh hay không.

Một điều quan trọng bạn cần lưu ý là nếu bạn muốn lazy-load ảnh background, thì cách này sẽ không chạy đâu nhé. Thay vào đó bạn phải dùng 2 cách mà mình đề cập bên dưới.

Một lưu ý khác nữa, là browser không đợi đến lúc tấm ảnh xuất hiện ở viewport mới tải, mà khi tấm ảnh gần xuất hiện ở viewport là nó đã tải rồi nhé. Điều này giúp browser tải tấm ảnh sớm nhất có thể để nó sẵn sàng xuất hiện trên màn hình kịp lúc, vì tải cũng mất thời gian mà. Nếu bạn muốn tìm hiểu thêm thì có thể search từ khóa “threshold” nhé.

Theo trang Can I Use, thuộc tính này đã được hỗ trợ trên Chrome và Firefox, không hỗ trợ IE, còn Safari thì đang thử nghiệm và sẽ sớm có thôi.

Fallback

Trong trường hợp browser chưa support thuộc tính loading, thường ta sẽ dùng polyfill hoặc fallback. Mình ví dụ một đoạn code fallback để kiểm tra nếu trình duyệt chưa support thuộc tính loading thì sẽ tự dùng third-party bên ngoài để lazy-load.

Kĩ thuật 2: lazy-load sử dụng Intersection Observer API

Định nghĩa về “Intersection Observer API” thì mình không nêu ra ở đây vì nó nằm ngoài phạm vi bài viết. Ứng dụng của nó thì có rất nhiều, và “lazy-loading images” là một trong số những ứng dụng ấy. Nói nôm na, bạn sử dụng API này để biết được khi nào user scroll đến vị trí tấm ảnh, và khi ấy chúng ta “ép” browser tải tấm ảnh ngay lập tức.

Tuy sử dụng Intersection Observer cho việc lazy-load là một cách không quá “lỗi thời”, nó vẫn không được support trên IE nhé. Tuy nhiên hầu hết các browser hiện nay và cả mobile nữa đều support nó, nên có thể nói đây là cách khá “an toàn”.

Nếu vì tính chất công việc mà bạn buộc phải support IE, bạn có thể sử dụng polyfill để giả lập Intersection Observer API, hoặc sử dụng kĩ thuật số 3 tiếp theo đây.

Kĩ thuật 3: lazy-load sử dụng scroll event (resize, orientationChange…)

Kĩ thuật này là khá cổ điển, có thể xem nó là giải pháp cuối cùng để lazy-load images nếu bạn buộc phải support các browser cũ. Giải pháp này tuy chạy nhưng có nhiều vấn đề về performance và hiệu ứng giật (lag), vì nó là cách thủ công mà. Bạn sẽ phải tính toán xem vị trí của tấm ảnh xem nó đã xuất hiện ở trên màn hình chưa, và cứ lặp đi lặp lại mỗi khi user scroll.

Mình không khuyến khích các bạn sử dụng cách này cho production nhé. Nếu buộc phải support các browser cũ, thì polyfill của Intersection Observer ở trên là đủ rồi.

Khi nào nên và không nên áp dụng lazy loading?

Mặc dù lazy-load có rất nhiều lợi ích như trên, bạn cần đặt câu hỏi cho bản thân liệu bạn có thật sự cần nó không, vì “lazy-loading images” cũng có những tác hại (mình có chia sẻ ở cuối bài viết) nếu chúng ta lạm dụng hoặc sử dụng sai cách. Vậy khi nào thì chúng ta nên lazy-load hình ảnh của web:

  • Trang của bạn có nhiều hình ảnh và chúng đang làm chậm trang web của bạn.
  • Hình ảnh trong trang của bạn nằm khuất màn hình và không cần phải tải tức thời.
  • Bạn cần tối ưu tốc độ tải trang trên mobile (và cả desktop), thì “lazy-load images” là một việc nên làm (tất nhiên chỉ lazy-load thôi chưa đủ đâu nhưng nhanh được thêm bao nhiêu hay bấy nhiêu)

Lazy loading chỉ phát huy tác dụng thực sự khi bạn “sử dụng đúng mục đích” cho đúng đối tượng vào “đúng thời điểm”. Lazy loading là lựa chọn cực kì phù hợp những người chủ yếu sử dụng các thiết bị có kết nối và bộ vi xử lý tốt như smartphone, laptop,… có các kết nối băng thông rộng để không gặp lỗi với Javascript của Lazy-load.

Tuy nhiên, những người dùng không có những đặc điểm trên thì tốt nhất bạn nên ít phụ thuộc vào JavaScript. Ngoài ra, website có thể áp dụng lazy loading khi có nhiều dữ liệu cần tải làm tốc độ trang bị chậm ảnh hưởng đến hiệu suất web.

Đối với những trường hợp như trên thì nên áp dụng lazy loading, ngược lại nếu bạn áp dụng đối với những website mang tính chất thương mại điện tử, bán hàng online thì sẽ phản tác dụng vì khách hàng đang có nhu cầu mua hàng nhưng không tìm ra sản phẩm đó vì nó đã bị ẩn mà họ cần. Thậm chí đối với những ai sử dụng thiết bị kết nối kém sẽ là một tín hiệu không tốt của website.

“Lazy-loading images” có hại không?

Mặc dù lazy-load là một kĩ thuật tốt và hiệu quả, việc sử dụng lazy-loading images sẽ có một số mặt hại sau:

Page bị nhảy khi tấm ảnh được load (layout shift)

Vấn đề này là thường gặp nhất khi áp dụng lazy-load. Lý do là vì browser không biết được kích thước của tấm ảnh trước khi nó thật sự load nó. Vì thế khi load xong tấm ảnh, nó sẽ đẩy content xung quanh ra xa gây giật trang khá khó chịu. Có rất nhiều cách để giải quyết vấn đề này, nhưng để tránh bài viết quá dài nên mình chỉ đưa một cách đơn giản và dễ hiểu nhất thôi. Nếu các bạn cần tìm hiểu thêm nhiều cách khác thì có thể Google hoặc để comment bên dưới nhé.

Cách để tránh layout shift thường thấy là chỉ ra chính xác kích thước của tấm ảnh, khi đó browser sẽ dành chỗ trước cho tấm ảnh đó trên layout, để đảm bảo khi load xong tấm ảnh, nó sẽ lấp đúng khoảng trống đó và không gây lỗi layout shift.

Ngoài ra, bạn nên tránh lazy-load những tấm ảnh ở ngay phần đầu của trang (thuật ngữ chuyên môn gọi là above-the-fold) để tránh việc layout shift nhé.

Khi web bị tắt Javascript

Đối với những user đã tắt Javascript trên trình duyệt (tỉ lệ rất thấp), thì cách sử dụng Intersection Observer hay scroll sẽ không những không chạy, mà nó còn làm những tấm ảnh của bạn mãi mãi không xuất hiện. Để giải quyết vấn đề đó, ta có thể sử dụng thẻ noscript

Tuy nhiên bạn không cần phải lo lắng vì thật sự tỉ lệ user lướt web mà tắt javascript là rất thấp.

Không tốt cho SEO

Vẫn là khi sử dụng Intersection Observer hay scroll. Khi con bot (mình ám chỉ GoogleBot) crawl trang web của bạn, nó sẽ không hiểu data-src là gì mà nó chỉ hiểu src mà thôi. Trong trường hợp này nó sẽ xem như tấm hình đó bị lỗi và không index tấm hình của bạn. Tuy nhiên nói vậy không có nghĩa là không có giải pháp, có một số trick dành cho bạn nếu bạn quan tâm:

  • Feed cho con bot bằng cách thủ công thông qua sitemap (nếu bạn là dân SEO thì bạn sẽ hiểu nó là gì)
  • Kiểm tra xem navigator.userAgent có phải là bot của Search Engine không. Nếu phải thì ta bỏ qua việc lazy-load bằng cách thực hiện ngay thao tác copy từ data-src sang src. Việc này khá tricky nên mình không nói chi tiết ở đây (nó liên quan đến SSR và CSR). Nếu bạn có thắc mắc gì thì để lại comment bên dưới nhé.

Thêm code Javascript chỉ để lazy load vài tấm ảnh

Nếu số lượng ảnh cần lazy load chỉ dưới 5 tấm, và chúng không ảnh hưởng nhiều đến tốc độ tải trang, thì mình khuyên không nên sử dụng lazy load. Điều này chỉ khiến bạn tốn thêm nhiều dòng code javascript, và sẽ lớn hơn nếu bạn nhúng cả polyfill vào nữa. Thay vào đó, hãy tìm cách optimize tấm ảnh của bạn, và sử dụng native lazy-load nếu có thể.

loading="lazy" không hỗ trợ background image

Nếu bạn muốn lazy-load ảnh background, thì cách sử dụng loading="lazy" sẽ không chạy và bạn buộc phải dùng 2 cách còn lại nhé.

Kết bài

“Lazy-loading images” chỉ là một trong rất nhiều kĩ thuật để tối ưu performance cho web. Sắp tới mình sẽ viết thêm nhiều bài viết phân tích về web performance nhé.

Mong rằng những chia sẻ về lazy loading mà MrH chia sẻ trong bài viết này là hữu ích, giúp bạn giải đáp được thắc mắc của chính mình, đồng thời có thể áp dụng thành công những kiến ​​thức này vào kỹ thuật lập trình web của mình.

Bài viết của mình khá dài rồi, hi vọng các bạn thích bài viết lần này của mình, mình sẽ luôn cập nhật để nó không bị lỗi thời nhé. Nếu các bạn có góp ý hay thắc mắc gì thì xin để lại comment bên dưới.

Đánh giá post