Categories Lazy load

Giới thiệu LQIP – Ảnh giữ chỗ chất lượng thấp

LQIP giống cầu thủ dự bị

Với lời của người dịch (1): LQIP giống cầu thủ dự bị, ảnh chất lượng cao giống như cầu thủ chính. Khi bạn sử dụng lazy load ảnh, nếu ảnh chất lượng cao chưa kịp tải, LQIP là cách xoa dịu người dùng, giống như cầu thủ dự bị là giải pháp tình thế khi cầu thủ chính bị chấn thương, tuy chơi không hay bằng nhưng còn hơn là thi đấu thiếu người. LQIP kết hợp với tải trước ảnh khi nó đi vào khung nhìn trình duyệt (viewport) là bộ đôi hoàn hảo khi bạn muốn triển khai lazy load với ít ảnh hưởng tiêu cực đến trải nghiệm người dùng. OK, giờ chúng ta đi vào phần chính nhé.

Với các trang web ngày nay, ảnh là một thách thức thực sự.

Một mặt, ảnh chiếm đến hơn 60% dung lượng trang. Điều này có nghĩa là chúng chịu trách nhiệm chính trong tổng thời gian tải trang, vấn đề đó thúc đẩy các nhóm lập trình viên cố gắng tạo ra các ảnh càng nhỏ càng tốt (tính trên byte). Mặt khác, các thiết bị mới khoe khoang khả năng hiển thị retina và độ phân giải cao, còn các nhà thiết kế thì khát khao tận dụng các màn hình này để cung cấp các ảnh đồ họa đẹp mắt và hoành tráng. Với xu hướng trên, kết hợp với nhiều cái khác nữa, dẫn đến sự gia tăng trung bình 30 KB ảnh trên trang chỉ tính riêng vào năm ngoái (năm 2012, thời điểm bài gốc tiếng Anh được viết là năm 2013).

Tôi nghĩ mâu thuẫn này một phần là do “hiệu suất tình huống”. Nếu bạn đang ở trên kết nối cáp quang tốc độ cao (có thể lên đến vài chục MB / s) – giống như hầu hết các nhà thiết kế khác – ảnh chất lượng cao không làm chậm trang của bạn là bao, và sẽ đem đến trải nghiệm người dùng phong phú hơn (richer experience). Nếu bạn trên kết nối di động, bạn sẽ thích ảnh có chất lượng thấp hơn trên trang có kết nối chậm.

May mắn thay, không phải tất cả hy vọng đều mất hết.

Vài tháng trước đây chúng tôi đã tạo ra cách tối ưu hóa ảnh mới gọi là Low Quality Image Placeholders (Ảnh giữ chỗ chất lượng thấp) hoặc viết tắt là LQIP. Cách tối ưu hóa này tỏ ra hữu ích, nó như là một dạng cầu nối khỏa lấp khoảng trống giữa kết nối tốc độ cao và tốc độ thấp, và giữa người thiết kế và người làm IT, vì thế tôi nghĩ rằng nó rất đáng để chia sẻ.


Ý tưởng cốt lõi

Logic của LQIP thì đơn giản thôi. Theo một nghĩa nào đó, điều này giống với tải ảnh JPEG kiểu progressive (lũy tiến). Chi tiết về cách triển khai sẽ được tôi trình bày bên dưới, nhưng có hai bước chính cơ bản sau:

  • Trang tải lúc ban đầu kèm với ảnh chất lượng thấp
  • Một khi trang tải xong (ví dụ trong sự kiện onload), thay thế chúng bằng ảnh có chất lượng đầy đủ

LQIP đem đến cho chúng ta lợi thế tốt nhất cho cả hai phía. Trên kết nối chậm, người dùng sẽ tải một trang hoàn toàn có thể sử dụng nhanh hơn nhiều, đem đến cho họ trải nghiệm người dùng tốt hơn đáng kể. Trên kết nối nhanh, việc gia tăng tải thêm các ảnh chất lượng thấp – hoặc trì hoãn ảnh chất lượng cao trong chốc lát – không dẫn đến độ trễ đáng kể. Trong thực tế, thậm chí trên kết nối nhanh, người dùng sẽ có được trang khả dụng nhanh hơn, và họ vẫn sẽ có được trải nghiệm thị giác phong phú ngay sau đó.


Ví dụ trong thế giới thực

Dưới đây là ví dụ về cách trang chủ của Etsy tải khi có và không có LQIP. Lưu ý rằng Etsy không thực sự áp dụng tối ưu hóa này – tôi tạo một trang tĩnh sao chép từ trang chủ của họ và áp dụng tối ưu cho nó thông qua Akamai FEO.

Trên tốc độ kết nối DSL thì LQIP giúp tăng tốc hiển thị trang lên 500ms (~20%), trong khi trên kết nối FIOS (cáp quang) nó giúp tăng tốc ít hơn, khoảng 100ms (10%). Việc tăng tốc này đến từ thực tế rằng dung lượng trang giảm từ ~480KB xuống ~400KB nhờ các ảnh chất lượng thấp hơn. Xét trên tổng thể, đây chẳng phải con số tệ cho một biện pháp tối ưu – đặc biệt là trên trang đã được tối ưu hóa cao như trang chủ của Etsy.

Kết nối DSL, không có LQIP (phía trên) vs có LQIP (phía dưới)

kết nối DSL, có và không có LQIP

Kết nối FIOS, không có LQIP (phía trên) vs có LQIP (phía dưới)

kết nối FIOS, có và không có LQIP

Dù vậy, tốc độ hiển thị nhanh không phải là toàn bộ câu chuyện. Trang LQIP mà bạn thấy thực sự sử dụng ảnh chất lượng thấp hơn các trang khác. Trong khi trước sự kiện onload trang LQIP nhẹ hơn 80KB, nó sẽ nặng hơn 40KB vào thời điểm các ảnh chất lượng đầy đủ được tải xong. Tuy nhiên, trang chắc chắn sử dụng được với ảnh chất lượng thấp, giúp nó tránh phải chờ đợi tải các ảnh lớn hơn. Bạn có thể xem ví dụ về ảnh thông thường và ảnh chất lượng thấp trong bảng bên dưới – tôi không thiết lập chất lượng xuống quá thấp.

Ảnh bình thường (15,6 KB)

Ảnh bình thường

Ảnh LQIP (5,2 KB)

Ảnh LQIP

Nó đơn giản chỉ là cách phân phối thông minh hơn

LQIP cũng giúp ích trên mặt trận chính trị, bằng cách làm cầu nối giữa IT/Dev và người thiết kế.

Người thiết kế hạnh phúc bởi vì ảnh chất lượng đầy đủ của họ được hiển thị cho người dùng, không phải thay đổi gì. Chắc chắn, các ảnh sẽ bị hiển thị trễ một chút, nhưng kết quả cuối cùng thường sẽ xuất hiện trong vòng vài giây, và thành quả thiết kế vất vả (handiwork) của họ sẽ không hề hấn gì.

Người làm IT hạnh phúc vì họ phân phối trang nhanh hơn cho người dùng, thậm chí cả trên kết nối có tốc độ chậm. Ảnh chất lượng thấp chỉ là ảnh giữ chỗ (placeholders), nhưng (giả định chất lượng không bị giảm quá nhiều) trang có khả năng sử dụng hoàn chỉnh khá lâu trước khi ảnh chất lượng đầy đủ tải về.


Các mẹo triển khai

Triển khai LQIP bao gồm ba phần:

  1. Chuẩn bị ảnh chất lượng thấp (phía máy chủ)
  2. Tải ảnh chất lượng thấp (phía máy khách)
  3. Tải ảnh chất lượng cao (phía máy khách)

Bước #1 thay đổi rất nhiều tùy thuộc vào hệ thống của bạn. Bạn có thể tạo các ảnh trong hệ thống CMS của bạn, nhân chúng lên trong hệ thống bạn xây dựng, hoặc điều chỉnh chất lượng theo thời gian thực sử dụng công cụ kiểu như Akamai Edge Image Manipulation.

Bước #2 thì đơn giản thôi – chỉ là tải các ảnh về. Bạn có thể làm thế với thẻ ảnh đơn giản, CSS, hoặc sử dụng mã JS ưu thích của bạn để làm nhiệm vụ tải ảnh. Nếu bạn sử dụng ảnh đủ nhỏ, bạn thậm chí có thể nội tuyến các ảnh đó (phù hợp với đề xuất của Ilya). Tại Akamai, chúng tôi sử dụng LQIP kết hợp với tải ảnh theo yêu cầu (loading images on-demand), nó cũng giúp giảm số lượng request tới ảnh.

Bước #3 là nơi mà đoạn JS mới có thể được đưa vào. Các bước đơn giản sẽ như sau:

  1. Tạo một hàm JS tương tác lặp đi lặp lại với các thẻ img trên trang, và làm từng cái sau: (1) Xác định URL của ảnh có chất lượng đầy đủ (sử dụng quy ước đặt tên hoặc một thêm một thuộc tính vào thẻ IMG)
  2. Điều chỉnh thuộc tính SRC để trỏ đến URL đầy đủ này (trình duyệt sẽ tải lại ảnh này)
  3. Gọi hàm JS của bạn trong sự kiện onload

Nếu muốn tốt hơn nữa, bạn có thể tải ảnh chất lượng cao trong thẻ ẩn của IMG, và sau đó trao đổi ảnh chất lượng thấp với nó vào sự kiện onload. Điều này sẽ ngăn ảnh chất lượng thấp biến mất trước khi ảnh chất lượng cao tải về đầy đủ, hỗ trợ này sẽ giúp cải thiện trải nghiệm người dùng.

Cuối cùng, nếu bạn sử dụng CSS để tải các ảnh của bạn, bạn cũng có thể thực hiện chuyển đổi từ ảnh chất lượng thấp sang ảnh chất lượng cao bằng cách tải/áp dụng CSS mới.


Tổng kết

Tôi khá thích thú LQIP.

Nó giúp làm cầu nối giữa hai nhu cầu đang phát triển và mâu thuẫn nhau, LQIP hoạt động tương tự nhau trên các trình duyệt cũ và mới, và là cách triển khai (tương đối) dễ dàng. Đây là tối ưu hóa “hiệu suất nhận thức”, đó là cách mà tất cả chúng ta nên suy nghĩ, và tôi tin tưởng rằng LQIP là kiểu tối ưu mà tất cả mọi người nên áp dụng.

P/S 1: Tôi dịch bài này vì thấy LQIP được sử dụng rất nhiều trong lazy load ảnh, và một thư viện JS áp dụng nó rất tốt là lazysizes.

P/S 2: Bạn có thể xem ví dụ sử dụng ảnh LQIP trong thực tế trong lazy load ảnh qua ví dụ này: https://static.kiencang.net/2020/lazysizes-demo-LQIP1.html (hầu hết các ảnh LQIP trong link vừa dẫn chỉ có dung lượng chưa đến 10% ảnh gốc. Có nhiều quan điểm về chất lượng nên có của ảnh LQIP, trong link trên nó ưu tiên ảnh LQIP chất lượng càng thấp càng tốt)

Vài lời của người dịch (2): hãy tưởng tượng LQIP giống như thế này, một anh chàng quyết định lấy vợ, anh mô tả với vợ một viễn cảnh tốt đẹp sau ngày cưới (ảnh chất lượng cao). Anh có một căn hộ tuy không rộng nhưng vừa xinh cho đôi vợ chồng trẻ và em bé sau này, anh đang có công việc với thu nhập “sống được” ở khu vực ngoại thành Hà Nội, và cô cũng cảm thấy anh là một người chăm chỉ, vì anh thường xuyên làm việc khi đến thăm cô. Thế rồi ngày cưới cũng đến, cô đến ở với anh, cô dâu trẻ phát hiện ra rằng anh nghiện game, thường chơi thâu đêm suốt sáng, căn hộ không quá hẹp nhưng vô cùng bừa bộn và công việc mà anh nói là ổn định cũng không đúng, do anh chỉ làm việc tùy hứng, thu nhập của anh vì thế cũng rất eo hẹp trong khi chỉ vài tháng nữa là cô sinh em bé (vâng, họ “ăn cơm trước kẻng”). Lúc này hãy tưởng tượng sự thất vọng của người vợ trẻ. Áp vào lazy load ảnh, điều này không khác việc người dùng kéo đến khu vực cần hiển thị ảnh thì lại thấy một ô trống không hoặc một ảnh mới chỉ tải được chưa nổi 5%, người dùng thất vọng như người vợ trẻ vậy, nội dung thì hứa hẹn nhưng kết quả thực tế thì không. LQIP như một sự xoa dịu, đúng, nó không phải là ảnh chất lượng cao, nhưng ảnh chất lượng thấp đó còn hơn rất nhiều khoảng trống, một chút còn hơn là không có gì. Và rồi quả thực ảnh chất lượng cao sẽ thay thế ảnh chất lượng thấp, giống như một người chồng mới lập nghiệp còn nhiều thiếu sót, nhưng với thời gian, anh đã lo toan được cho gia đình ấm êm.

(Dịch từ bài viết Introducing LQIP – Low Quality Image Placeholders của tác giả Guy Podjarny)

Back to Top