Optimasi load Progressive Web Application (PWA) dengan React JS kurang dari 5 detik dalam koneksi slow 3G

Tulisan ini merupakan bagian dari #WWWIDChallenge

Rizal Ibnu
React ID
7 min readApr 18, 2018

--

Progressive Web Application (PWA) mulai menjadi bahan perbincangan yang hangat dikalangan penggiat industri teknologi. PWA menggunakan teknologi web yang memberikan pengalaman terbaik kepada pengguna layaknya aplikasi native.

2 bulan yang lalu, WWWID mempublikasikan tantangan untuk membuat aplikasi web yang bisa tampil dan digunakan dalam waktu kurang dari 5 detik dalam koneksi slow 3G. Tantangan tersebut mengajak teman-teman developer untuk membuat sebuah aplikasi RSS reader sederhana dari publikasi WWWID di medium.

Saya ingin menceritakan metode yang saya gunakan dalam membuat Progressive Web Application (PWA) ketika mengikuti tantangan dari WWWID. Saya menggunakan framework React JS berbasis Create-React-App (CRA). CRA secara default telah tersetup service-worker sebagai langkah awal memulai PWA.

Pastikan service-worker telah ter-setup dengan benar.

Starting Loader

Starting Loader dalam aplikasi web React JS

React JS merupakan framework yang cukup gemuk karena memiliki banyak fitur, hal tersebut mengakibatkan starting load-nya agak lambat dan tampilannya akan blank putih sebelum DOM ter-render, hal ini kurang baik dalam user experience. Karena masalah tersebut, diperlukan Starting Loader untuk membuat tampilan loading awal sebelum aplikasi React JS di-render. Tampilan Starting Loader ini akan muncul pada detik pertama.

Starting Loader muncul pada detik pertama

Saya menaruh Starting Loader ini pada index.html, lalu menghapusnya dalam lifecycle method componentDidMount(). Kamu juga bisa menambahkan kode CSS untuk mempercantik Starting Loader.

Konfigurasi PWA pada Android dan iOS

Android

Ketika Kamu baru memulai generate aplikasi React menggunakan CRA, dalam folder public secara default telah ter-setup file manifest.json. File ini yang mengontrol bagaimana aplikasi PWA terlihat oleh pengguna, seperti splash screen, app icon, start url dll.

Namun ketika Kamu memulai percobaan menggunakan lighthouse, Ditemukan beberapa kesalahan ketika audit dalam bagian PWA.

Test lighthouse pada aplikasi create-react-app

Kesalahan pada audit tersebut adalah :

  1. Does not redirect HTTP traffic to HTTPS.
  2. User will not be prompted to install the Web App.
  3. Is not configured for a custom splash screen.

Untuk kesalahan point 1, hal tersebut bisa diatasi dengan redirect ke HTTPS dalam server Kamu. Sedangkan, untuk kesalahan pada point 2 dan 3 terjadi karena secara default dalam manifest.json hanya menyertakan App Icon dengan ukuran 64x64 32x32 24x24 16x16 pixel. Oleh karena itu, Kamu perlu menambahkan ikon dengan ukuran 192x192 dan 512x512 pixel. Selain itu, start_url saya ubah menjadi “/” dari sebelumnya “./index.html” karena dalam konfigurasi router yang saya buat “./index.html” diarahkan ke halaman 404 not found.

Konfigurasi PWA pada file manifest.json

Kamu bisa mempelajari tentang web manifest disini.

iOS

Konfigurasi PWA di iOS memerlukan tambahan meta dan link tag seperti dibawah ini yang dicantumkan didalam head tag.

Konfigurasi PWA di iOS

Dalam gist diatas, terdapat <link rel=”apple-touch-startup-image” />, ini menentukan splash screen image pada perangkat iOS. Saya menggunakan media query agar dalam tampil dengan baik di berbagai model perangkat iOS.

Kamu bisa mempelajari konfigurasi PWA di iOS disini.

Code Splitting

Aplikasi web memiliki kecenderungan untuk tumbuh besar karena bertambahnya fitur yang dikembangkan. Semakin lama waktu yang diperlukan untuk memuat aplikasi, semakin membuat frustasi pengguna. Masalah ini semakin kuat dalam lingkungan smartphone dimana koneksi bisa sangat lambat. Untuk itu diperlukan pemecahan kode atau code splitting daripada mem-bundle-nya menjadi 1 file saja, ini memungkinkan hanya memuat kode yang diperlukan saja saat pengguna membutuhkannya.

Kali ini saya menggunakan library react-loadable karena memiliki banyak fitur seperti preloading, delay, timeout dan loading component. Selain itu, ada alternatif lain seperti loadable-components, react-async-component, react-code-splitting. Library tersebut masing-masing mempunyai keunggulan dan kekurangan, Kamu bisa mencoba salah satunya yang bisa memenuhi kebutuhan Kamu.

Code splitting pada route menggunakan react-loadable

File javascript dipecah menjadi beberapa chunk file sesuai route, Kamu juga bisa menerapkannya dalam komponent tertentu yang tidak terlihat langsung seperti Modal.

File javascript yang dipecah menjadi beberapa chunk file

Optimasi Gambar

Sebagian besar konten situs web terdiri dari gambar. Pengoptimalan gambar adalah proses untuk menyaring gambar sehingga mengurangi ukuran total halaman dan load time, juga mengurangi beban jaringan dan penggunaan data (sangat bermanfaat ketika pengguna menggunakan paket data seluler).

Lazy Load Image

Gambar merupakan salah satu konten di aplikasi web yang ukurannya cukup besar, semakin besar dan banyak gambar yang dimuat, semakin lama juga waktu yang diperlukan untuk memuat aplikasi. Sama halnya dengan code splitting, lazy load image juga bertujuan untuk memuat gambar yang diperlukan saja saat gambar tersebut terlihat di viewport.

Saya menggunakan library react-lazy karena implementasinya yang sangat mudah dan menggunakan IntersectionObserver API. Kamu perlu menambahkan polyfill intersection-observer. Lihat Can I use untuk status browser yang mendukungnya.

Dukungan untuk webP

WebP adalah format gambar modern yang menyediakan kompresi lossless dan lossy untuk gambar di web. Menggunakan WebP, Kamu dapat membuat ukuran gambar yang lebih kecil namun tetap menjaga kualitas gambar, sehingga membuat web lebih cepat. Gambar lossless WebP berukuran 26% lebih kecil dibandingkan dengan PNG. Gambar lossy WebP berukuran 25–34% lebih kecil dari gambar JPEG dengan indeks kualitas SSIM yang setara.

Solusi paling mudah untuk mengimplementasikan format webP adalah mengkonversi gambar dari API dengan pihak ketiga, salah satunya adalah Cloudinary.

Namun sayangnya, saat ini WebP hanya didukung oleh Chrome dan Opera, Kamu akan mendapat masalah pada browser di perangkat iOS dan browser Firefox.

Resource Hints (Preload, Prefetch & Preconnect)

Preload

Preload adalah standar web baru yang menawarkan kontrol lebih untuk memuat resources seperti gambar, CSS, JavaScript, dan file font yang akan dimuat dalam suatu halaman web. Umumnya digunakan untuk melakukan pramuat resources yang high priority.

Prefetch

Prefetch digunakan untuk mengkontrol resources yang low priority dimana browser mengambil resources yang mungkin diperlukan nanti dalam background process, dan kemudian menyimpannya di cache browser. Ada tiga jenis prefetching, yaitu Link Prefetching, DNS Prefetching, dan Prerendering.

  1. Link Prefetching

Seperti yang sudah dijelaskan diatas, dengan Link Prefetching browser akan mengambil resources dan menyimpannya di cache browser.

“This technique has the potential to speed up many interactive sites, but won’t work everywhere. For some sites, it’s just too difficult to guess what the user might do next. For others, the data might get stale if it’s fetched too soon. It’s also important to be careful not to prefetch files too soon, or you can slow down the page the user is already looking at. — Google Developers“

2. DNS Prefetching

Prefetch DNS memungkinkan browser untuk melakukan DNS lookups untuk domain eksternal pada halaman web dalam background process saat pengguna sedang menjelajah. Gunakan cara ini untuk domain eksternal yang benar-benar dibutuhkan saja.

“DNS requests are very small in terms of bandwidth, but latency can be quite high, especially on mobile networks. By speculatively prefetching DNS results, latency can be reduced significantly at certain times, such as when the user clicks the link. In some cases, latency can be reduced by a second. — Mozilla Developer Network

3. Prerendering

Prerendering sangat mirip dengan Link Prefetching karena mengumpulkan resources yang mungkin akan ditelusuri oleh pengguna. Perbedaannya adalah bahwa Prerendering menyajikan seluruh halaman dalam background process, semua aset dokumen.

“The prerender hint can be used by the application to indicate the next likely HTML navigation target: the user agent will fetch and process the specified resource as an HTML response. To fetch other content-types with appropriate request headers, or if HTML preprocessing is not desired, the application can use the prefetch hint. – W3C

Preconnect

Preconnect memungkinkan browser untuk mengatur koneksi awal sebelum permintaan HTTP benar-benar dikirim ke server. Preconnect meliputi DNS lookups, TLS negotiations, TCP handshakes. Hal ini berguna untuk menghilangkan roundtrip latency dan menghemat waktu bagi pengguna.

Saatnya Audit!

Langkah-langkah dalam proses audit aplikasi web :

Deploy ke hosting

Untuk hosting saya memilih Firebase karena penerapannya sangat mudah, mendukung HTTPS, HTTP/2 dan Cache Control. Kamu bisa mempelajari lebih detil tentang Firebase dan menambah project baru disini. Alternatif lain, Kamu dapat menggunakan Heroku, Netlify, Github Pages, Now, Surge dll.

Audit dengan Webpagetest.org

Audit bisa dilakukan dengan dengan mudah menggunakan tools performance test dan lighthouse dari Webpagetest.org.

Hasil audit performa dengan webpagetest.org

Lihat detil hasil audit performa dengan webpagetest.org dengan mode Easy, lokasi percobaan Dulles, VA dan koneksi Slow 3G pada tanggal 16 April 2018 disini.

Hasil audit lighthouse dengan webpagetest.org

Lihat detil hasil audit lighthouse dengan webpagetest.org dengan lokasi percobaan USA-Virginia pada tanggal 7 Agustus 2018 disini.

Dari hasil percobaan diatas, aplikasi web berhasil dimuat dalam waktu kurang dari 5 detik, tepatnya 3,16 detik, skor PWA 100 dan skor Performance 95.

Project React PWA WWWID

Saya sangat terbuka untuk kontribusi dalam project ini.

Repository GitHub :

Preview Demo :

Terimakasih kepada teman-teman WWWIDPWA yang saling memberikan solusi dalam mengikuti tantangan ini, banyak ilmu yang saya dapatkan semoga grup WWWIDPWA semakin solid dan saling memberi manfaat.

--

--

Rizal Ibnu
React ID

A Craftsman, designer and coder. Currently work at Kumparan as Frontend Engineer. https://rizalibnu.com