Cách Medium tối ưu tốc độ load hình ảnh
Một website tốt đòi hỏi tốc độ load trang phải nhanh, đó là điều tất yếu. Đối với những website có lượng hình ảnh lớn, điều này đã trở thành 1 trong những quan tâm hàng đầu của các nhà phát triển. Trong bài viết này chúng ta cùng đi vào tìm hiểu kỹ thuật Progressive Image Loading mà Medium đã áp dụng, implement xem nó thế nào và bạn có áp dụng được vào các dự án của mình không. Hãy cùng Bizfly Cloud theo dõi nhé!
Việc đầu tiên cần làm là dùng các công cụ test có sẵn đễ xem tốc độ load của web bạn nhanh hay chậm. Các bạn có thể kiểm tra ở Google Page Speed, GTmetrix, WebPageTest hay những trang tương tự. Bạn sẽ thấy thủ phạm do đâu mà ra. Đa phần là do những hình ảnh chất lượng cao chưa được nén (chiếm cỡ 85% tốc độ load). Bạn biết vấn đề ở đâu rồi chứ? Và Medium đã giải quyết nó như thế nào?
1. Kỹ thuật của Medium
Để xem hình ảnh trên Medium được load thế nào, hãy cùng xem qua demo này:
https://www.youtube.com/watch?v=YJsCyLb_IJ
Nếu bạn muốn tự test, hãy mở Medium'post này (https://medium.com/backchannel/exclusive-why-apple-is-still-sweating-the-details-on-imac-531a95e50c91) trong browser, disable cache rồi xem hiệu ứng.
Đây là những gì đã xảy ra:
Render div chứa ảnh sẽ hiển thị
Medium sử dụng 1 thẻ <div/> với padding-bottom set theo tỷ lệ %, tương ứng với tỉ lệ ratio của ảnh. Điều này cũng được đề cập đến trong intrinsic placeholders (https://daverupert.com/2015/12/intrinsic-placeholders-with-picture/).
Load 1 phiên bản thu nhỏ của ảnh
Lúc này, nó request 1 ảnh JPEG thu nhỏ với chất lượng rất thấp (cỡ 20%). Markup cho ảnh thu nhỏ này được trả về trong initial HTML với 1 thẻ, nên trình duyệt bắt đầu fetch chúng vào.
Một khi ảnh đã được load, nó sẽ đẩy vào <canvas/>
Sau đó, dữ liệu sẽ được lấy và truyền vào function blur(). Bạn có thể thấy, trong main-base.bundle JS file. Đồng thời, ảnh chính đã được requested.
Một khi ảnh chính đã được load, nó hiển thị ra và canvas được ẩn đi
Toàn bộ quá trình này được diễn ra một cách trơn tru nhờ vào CSS animation.
2. Markup
Đây là cái nhìn toàn cảnh về markup cho image:
Một ví dụ cụ thể:
<figure name="7012" id="7012" class="graf--figure graf--layoutFillWidth graf-after--h4">
<div class="aspectRatioPlaceholder is-locked">
<div class="aspect-ratio-fill" style="padding-bottom: 66.7%;"><div/>
<div class="progressiveMedia js-progressiveMedia graf-image is-canvasLoaded is-imageLoaded" data-image-id="1*sg-uLNm73whmdOgKlrQdZA.jpeg" data-width="2000" data-height="1333" data-scroll="native">
<img src="https://cdn-images-1.medium.com/freeze/max/27/1*sg-uLNm73whmdOgKlrQdZA.jpeg?q=20" crossorigin="anonymous" class="progressiveMedia-thumbnail js-progressiveMedia-thumbnail">
<canvas class="progressiveMedia-canvas js-progressiveMedia-canvas" width="75" height="47"></canvas>
<img class="progressiveMedia-image js-progressiveMedia-image __web-inspector-hide-shortcut__" data-src="https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg" src="https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg">
<noscript class="js-progressiveMedia-inner"><img class="progressiveMedia-noscript js-progressiveMedia-inner" src="https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg"></noscript>
</div>
</div>
</figure>
Chú ý là chất lượng ảnh request còn phụ thuộc vào thiết bị.
>>> Nếu bạn quan tâm tới dịch vụ tăng tốc website Bizfly CDN thì có thể tham khảo tại: https://bizflycloud.vn/cdn
3. Tái hiện lại hiệu ứng
Trong CodePen bên dưới, tác giả đã implemented 1 hiệu ứng tương tự, tuy nhiên thay thế canvas bằng cách sử dụng CSS filters để làm mờ.
Các ảnh loading dưới thể hiện cách load ảnh khi disable cache:
4. Vậy có đáng để thực hiện việc này không?
Rõ ràng có khá nhiều việc phải làm để render ảnh theo cách này. Và tất nhiên nó có thể gây nản chí, nhưng hiệu quả nó mang lại thì quá tuyệt. Việc hiểu và nắm rõ được cách load image có khá nhiều lợi thế:
- Lazy loading
Sử dụng JS cho việc tạo request cho phép kiểm soát được image nào đã requested. Khi tất cả ảnh thu nhỏ đã được request, ảnh lớn chỉ được request khi chúng được nằm trong viewport.
- Placeholder tốt hơn
Ảnh thumbnails rất nhỏ, cỡ 2kB, kết hợp với hiệu ứng làm mờ sẽ tốt hơn 1 màu solid, mà ko ảnh hưởng gì đến payload.
- Kích thước hình ảnh phù hợp
Medium chuẩn bị rất nhiều ảnh có size khác nhau phụ thuộc vào từng device request lên, nên tải trọng sẽ được tối ưu hơn qua đó tăng tốc độ upload.
5. Các biến thể
Inlining image data
Thay vì tạo request cho ảnh thumbnails, ta có thể inline chúng bằng cách sử dụng data URIs. Việc này làm tăng kích thước HTML, nhưng giúp đẩy nhanh quá trình render placeholder, ngay khi markup được tải xuống.
Hiệu ứng làm mờ
Mặc định thì khi trình duyệt render 1 ảnh nhỏ theo kiểu scaled up, nó sẽ tạo ra 1 hiệu ứng mờ để làm mịn dần các góc cạnh của ảnh đó. Hiệu ứng này có thể tắt/mở được. Cả Chrome, Safari, Firefox đều có hiệu ứng này, tuy nhiên Chrome có hiệu ứng làm mịn tốt hơn cả. Đây là demo, bạn nên mở to màn hình lên xem cho rõ:
Ảnh này nó chỉ có 27px và chất lượng rất thấp, nhưng được phóng to lên khá mịn
Hiệu ứng này cũng có thể đạt được khi sử dụng CSS Filter Effects (có support IE). Lợi thế của kỹ thuật này là bạn có thể dể dàng tinh chỉnh độ mờ của ảnh bao nhiêu tùy thích, và mọi thứ đã có CSS lo. 1 option khác là sử dụng SVG filter, được đề cập đến ở đây.
Một cách khác để cải thiện placeholder: Google Images Search
Họ lấy 1 mã màu và sử dụng solid colour background. Điều này làm cho user cảm thấy ảnh được load nhanh hơn :man_detective:
Thêm 1 kỹ thuật nâng cao nữa: Facebook's 200 bytes
Đầu năm nay Facebook đã post bài: "The technology behind preview photos", một chủ đề rất thú vị về việc sử dụng 1 ảnh 42x42 px làm ảnh previews với JPEG headers. Bạn có thể tham khảo thêm nếu muốn.
LQIP: Low Quality Image Placeholders
Thay vì chờ ảnh cuối cùng đc load, ta có thể dùng ảnh nén trước, xong rồi switch qua ảnh to kia sau. Đây có 1 bài viết về chủ đề này: Low Quality Image Placeholders. Ý tưởng này cũng giống như của Medium, nhưng dùng ảnh nén kích thước cao hơn.
6. Kết luận
Nếu web của bạn load càng nhiều ảnh, thì bạn nên nghĩ đến cách tối ưu image loading đi là vừa, điều này sẽ làm cho trải nghiệm người dùng tốt hơn.
Chúc các bạn thực hiện cách trên thành công!
Theo: viblo.asia
>> Có thể bạn quan tâm: Hướng dẫn tối ưu kích thước hiển thị hình ảnh trên website