Improving web performances using Progressive Image Lazyloading (Part 1/2)
Oct 28, 2019 19:52 · 1183 words · 6 minute read
We know about Lazyload but how about Progressive Image Loading, and what is Progressive Image Lazyloading? How it can significantly improve our web performances?
Topik ini akan saya bagi menjadi 2 artikel karena lumayan panjang. Ini adalah artikel pertama.
Overview
Seperti yang sudah saya jelaskan pada bagian akhir artikel sebelumnya, kali ini saya akan mengulas beberapa cara dalam menampilkan gambar dengan memperhatikan performances pada web .
Setiap front-end/fullstack developer memiliki cara yang berbeda-beda dalam meningkatkan performances pada website. Salah satu cara paling umum adalah melakukan request management pada proses rendering images. Salah satu teknik yang terkenal ialah Lazyloading. Cara yang lain dan cukup populer ialah Progressive Image Loading, cara ini hampir (r: mirip) dengan yang Medium lakukan. 2 teknik ini secara umum akan meningkatkan performa web secara signifikan. Untuk penjelasan lebih detail di artikel ini, artikel ini akan dibagi menjadi 3 bagian beserta contoh, implementasinya, dan seberapa besar pengaruhnya pada performa website.
1. Old ways, STF*, let’s rendering all images
Cara pertama dan yang paling banyak masih dilakukan oleh developer terutama pemula, adalah menampilkan seluruh gambar secara langsung dari server ke client browser. Cara yang sangat beresiko, karena jika satu halaman tertentu memiliki banyak gambar dan tidak ada image management request dari sisi code, akan seperti apa lama load web-nya nanti?
Coba kita perhatikan contoh berikut ini. Saya sudah menyediakan sebuah web yang menampilkan 6 gambar dengan 5 gambar diantaranya beresolusi besar dan lebih dari 1MB Total (10.1 MB). Silahkan buka blog-without-lazyload.herokuapp.com, matikan cache browser, atau tekan cmd+shift+R.
Sederhanya website ini hanya menampikan 6 gambar, dan informasi seberapa lama waktu yang dibutuhkan untuk proses load seluruh gambar yang ada pada halaman.
<body>
<h1>DISCLAIMER: All Images from <a href="https://unsplash.com">https://unsplash.com</a> (THANK YOU). FOR Educational
Purpose Only!</h1>
<h2>Rendering time: <span style="background-color: red; color: white; padding: 2px 5px;" id="rendering-time"> ... counting (wait until all image fully loaded)</span> </h2>
<img src="img/[email protected]">
<img src="img/[email protected]">
<img src="img/[email protected]">
<img src="img/[email protected]">
<img src="img/[email protected]">
<img src="img/[email protected]">
</body>
Untuk menampilkan informasi waktu, saya membuat script JS sederhana untuk melakukan time tracking pada event windows.onload.
var timerStart = Date.now();
window.onload = (event) => {
//eksekusi waktu ketika page telah load seutuhnya
let loadTime = (Date.now() - timerStart) / 1000;
document.getElementById("rendering-time").innerHTML = loadTime + 's';
};
Hasilnya seperti berikut (Waktu rendering tergantung device dan koneksi):
Proses ini membutuhkan setidaknya 41 detik untuk menampilkan ke-6 gambar secara utuh. Terlihat pada network tab DevTools bagaimana proses rendering terjadi.
Dengan waktu seperti itu, sangat tidak memungkinkan untuk menerapkannya pada koneksi yang lebih rendah seperti 3G, bukan?. Bagaimana kita mengurangi waktu onload ini? nah, kita gunakan teknik yang disebut lazyloading.
2. Lazyload, Rendering image based on current visible viewport.
Lazyload adalah teknik yang diperuntukan saat sebuah halaman memiliki banyak images. Dengan Lazyload, browser hanya akan me-render gambar yang terlihat pada layar kaca device yang kita miliki. Misalnya, contoh diatas ada 6 gambar, dan yang terlihat saat pertama kali loading web adalah 3 gambar. Maka hanya 3 gambar ini yang akan di request oleh borwser ke server. 3 gambar lain akan di request ketika kita melakukan scrolling pada web nantinya. Silahkan baca teknik ini lebih lanjut dari google web dev.
Untuk teknik ini, saya menambahkan script javascript lazyload yang populer di github. Sesuai dokumentasinya, code HTML akan menyesuaikan menjadi:
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
<img class="lazyload" data-src="img/[email protected]" src="img/thumbs/[email protected]">
Kemudian, kita aktifkan fitur lazyload-nya:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lazyload.js"></script>
<script>
//aktifkan lazyload. semua tag img dengan attr data-src dan class lazyload akan mendapatkan efek lazyload.
lazyload();
</script>
Setelah menerapkan lazyload, waktu rendering halaman menurun hingga - 25% menjadi 29.6 detik! Silahkan buka blog-without-lazyload.herokuapp.com/lazyload.html, matikan cache browser, atau tekan cmd+shift+R (Waktu rendering tergantung device dan koneksi).
Terlihat pada gambar, browser hanya melakukan request 3 gambar yang muncul dilayar ke server. Jika halaman di scroll, browser kembali melakukan request 3 gambar sisanya. Teknik lazyload ini pada dasarnya menggunakan Intersect Observer API, sebuah teknik modern web app dengan melakukan observasi pada halaman secara asynchronous.
Pertanyaannya adalah, apakah teknik ini sudah yang paling baik? apakah ada teknik yang lain untuk mengurangi waktu rendering page lebih baik lagi? Jawabannya ada, teknik itu disebut dengan Progressive Image Loading.
Progressive Image Loading, Medium-like Rendering Image Method
Progressive Image Loading pertama kali diperkenalkan oleh José M. Pérez. Teknik ini mirip dengan yang diperkenalkan facebook dengan fitur review image pada aplikas android-nya. Singkatnya, teknik ini akan mengganti proses umum rendering image pada halaman kita menjadi 3 step utama:
- Render div with image & placeholder. Terdapat sebuah placeholder (div) yang didalamnya terdiri dari gambar utama dan gambar pengganti (placeholder). Gambar pengganti ialah gambar yang sama dengan gambar utama hanya saja memiliki kualitas kompresi dan juga ukuran yang lebih kecil. Biasanya berukuran sekitar 42px. Pada kasus ini saya menggunakan 2px saja, selain lebih kecil dan hasilnya sama saja, juga sangat mengurangi penggunaan bandwidth user.
- Render placeholder image instead of original-image. Saat halaman dibuka, browser melakukan request ke server untuk kedua jenis gambar. Sejalan dengan request original image yang lama dan besar, browser akan menampilkan gambar pengganti (placeholder image).
- Once Original Image is loaded, it will shown to the user and placeholder is hidden.
Antara proses 2 & 3, placeholder image akan ditampilkan dalam efek blurring hingga gambar asli selesai di load oleh browser. Proses mengunduh gambar asli inilah yang disebut dengan progressive. Lebih jelasnya silahkan lihat contoh hasil penerapan metode ini di blog-without-lazyload.herokuapp.com/progressive.html, matikan cache browser, atau tekan cmd+shift+R (Waktu rendering tergantung device dan koneksi).
How it can be so fast?
Actually, it’s a tricky method. Setiap gambar placeholder memiliki ukuran sebesar 2px dan 20% quality dari gambar asli. Gambar ini dipakai sebagai gambar sementara
selagi gambar asli sedang diunduh browser. Dengan sedikit bantuan CSS, proses transisi antara gambar placeholder dan gambar asli dapat dilakukan dengan memanfaatkan transisi opacity.
.placeholder img {
position: absolute;
opacity: 0;
top: 0;
left: 0;
width: 100%;
transition: opacity 1s linear;
}
.placeholder img.loaded {
opacity: 1;
}
Untuk bagian ini, akan saya jelaskan lebih rinci pada artikel kedua. Yang perlu diperhatikan adalah dengan teknik ini, proses rendering time berkurang drastis dari 41 detik ke hanya 1.9 detik!! -95% DARI PROSES PADA TAHAP PERTAMA! tanpa mengurangi kualitas dari gambar yang akan ditampilkan.
Hal-hal yang perlu dicatat untuk di-optimize selanjutnya:
- Total request masih dilakukan secara utuh (10.2 MB) oleh browser meskipun gambar belum tampil pada layar. Dengan menggunakan Intersect Observer API, kita akan menerapkan lazyload teknik kedalam teknik ini (That’s why it called Progressive Lazyload Image).
- Setiap gambar wajib memiliki versi thumbnail yang digunakan sebagai placeholder yang akan di request oleh browser ke server. Harapannya, proses ini telah dilakukan oleh server (server side compressing). Untuk simulasinya, kita akan menggantinya dengan client side compressing menggunakan javascript terlebih dahulu.
Source code dari semua contoh diatas, dapat diakses pada repo github. Code oleh Jose telah saya modifikasi untuk memenuhi kebutuhan bukan hanya untuk 1 gambar saja, tapi semua gambar yang ditentukan pada halaman.
Sekian artikel kali ini. Hope you enjoy it. Happy Coding! (/¯◡ ‿ ◡)/¯