Mengenal Caching Strategies di Client-side

Yes, we can control cache in browser!

Ketika kita memulai untuk menerapkan prinsip-prinsip yang ada di Progressive Web Apps (PWA), prinsip pertama adalah Reliable. Aplikasi tidak bergantung dengan kondisi jaringan, meskpun dalam kondisi jaringan offline sekalipun.

Artinya, salah satu ciri dari aplikasi yang menerapkan prinsip PWA adalah tidak akan munculnya si dinosaurus yang tandanya suatu halaman website tidak bisa diakses karena kita sedang offline.

RIP MY CUTE DINOSAUR :( that cute sticker is from wwwid

Karena aplikasi web kita tidak bergantung dengan kondisi jaringan, kan? Lalu bagaimana cara menerapkannya?

How HTTP cache works

Sebelum kita ke pembahasan Caching Strategies di browser, mari kita berkenalan singkat tentang bagaimana browser meng-cache suatu request. Biasanya strategi caching berada di Web Server-level. Dan biasanya yang kita cache adalah suatu file statis seperti assets (HTML, CSS, JS, IMG, mp3, dll).

Jadi, ketika browser me-request style.css ke webserver, maka si browser akan memvalidasi terlebih dahulu apakah resources yang dimaksud sudah berada/dicache di browser atau tidak, jika tidak, maka request ke webserver.

Bagaimana browser bisa melakukan proses caching dibrowser? Dengan melihat ke Response Headers apakah ada tag cache-control atau tidak (biasanya dibarengi dengan etag).

Cache control yang membuat proses caching dibrowser terjadi. Biasanya formatnya adalah public, max-age=<seconds> . Yang berarti bilau resources tersebut bila memiliki response headers cache-control: public, max-age=60 berarti hanya cache resources tersebut selama 1 menit. Bila sudah lewat dari 1 menit setelah penyimpanan cache tersebut, maka browser akan merequest lagi ke webserver.

This is boring, bisa baca selengkapnya disini. Atau bisa lihat diagram ini yang sudah pasti bukan gue yang buat:

https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers

Ok cool. Lalu bila memang file statis tersebut ter-cache, mengapa ketika gue membuka file https://tarsius.id/_nuxt/87ff9383b0efca1dccae.js dibrowser ketika sedang offline tidak bisa? Sedangkan disini katanya diambil dari cache:

Ketika kalian mengakses https://tarsius.id/_nuxt/87ff9383b0efca1dccae.js, maka browser akan menganggap request tersebut sebagai document. Sedangkan menurut gue, file 87ff9383b0efca1dccae.js yang dicache tersebut berjenis script , bukan document yang meskipun content-type nya bernilai application/javascript

If caching is works in webserver-level, can we control —

Yes, thanks to serviceWorkers. Service Workers menyediakan API Cache untuk melakukan proses sesuai dengan nama API nya tersebut. Jadi disini kita bisa melakukan caching sesuai dengan yang kita butuhkan

Untuk caching sendiri, ada beberapa strategi yang bisa kalian terapkan. Dan ini yang sebenarnya akan kita bahas setelah pembahasan bertele-tele tersebut. Strategi berikut memiliki versi yang berbeda-beda. Dari tim mozilla, antara lain: Network or cache, Cache only, Cache and update, Cache, update and refresh, dan Embedded fallback sedangkan dari tim google antara lain: Cache First, Cache Only, Network First, Network Only, dan Stale while revalidate.

Secara teknis hampir serupa antara google & mozilla, namun untuk yang ditawarkan oleh google terlihat lebih variatif. So, just use it (terlebih tim google telah menyediakan library yang mempermudah kita menggunakan strategi tersebut alias tinggal langsung pakai saja).

Caching Strategies

CacheFirst

Sesuai namanya, prioritaskan pengambilan dari cache yang sudah disimpan. Jika tidak ada maka kembalikan ke jaringan. Bila kalian membuat web app yang offline-first, maka kalian akan banyak menggunakan strategi ini.

Dan juga bisa digunakan untuk suatu resource yang memang interval perubahannya lama sekali. Atau bisa juga untuk caching ke file yang memiliki penamaan revisi (seperti app.0088aa.css ). Jadi ketika kita membuat perubahan, dan berdampak kepada file css tersebut juga, maka strategi ini cocok digunakan karena si browser akan meminta file app.0099aa.css (yang baru) dari cache, jika tidak ada maka lakukan request ke target tersebut.

CacheOnly

Sesuai namanya (ya elah riz), hanya ambil resource berdasarkan yang ada dicache. Kalau gak ada, yaudah paling network error. Gak tau dah kenapa CacheOnly digunakan.

Punya alasan mengapa menggunakan strategi CacheOnly?

NetworkFirst

Network First biasanya digunakan untuk sesuatu yang dinamis. Dan perubahannya terjadi dengan sering. Namun, demi meningkatkan UX, penggunaan strategi NetworkFirst bisa dimaksimalkan untuk user yang yang sedang offline.

Seperti Twitter Lite (sekarang menjadi Twitter Web App). Twitter Lite menggunakan strategi NetworkFirst yang mana untuk user yang online dia akan menampilkan konten yang terbaru (dengan merequest ke server pastinya), namun bila sedang offline, maka request tersebut akan dikembalikan ke cache (seperti DM misalnya yang bisa dilihat meskipun sedang offline)

NetworkOnly

Untuk suatu request yang memang membutuhkan jaringan untuk memprosesnya. Analytics, non-GET request, dll. Lalu ngapain menggunakan strategi ini ya?

StaleWhileRevalidate

Ini yang terakhir, akhirnya. Strategi ini biasanya digunakan untuk sesuatu yang perubahannya sering, namun lebih memprioritaskan pengambilan dari cache. Seperti avatar misalnya (cek github, meskipun tidak menggunakan strategi ini di client-side).

Ketika kita mengubah avatar kita di Github, maka avatar kita tidak langsung berubah. Karena lebih memprioritaskan pemuatan dari cache, daripada dari server. Setelah perubahan terbaru tersebut sudah berada dicache, di next request kita akan menggunakan perubahan terbaru tersebut.

Gitu doang ya.

Iya juga ya, ngapain gue capek-capek nulis ini dah

Intinya, sesuatu yang gue pelajari dari gue menulis ini adalah:

Gunakan revision id ketika build assets

…untuk suatu assets yang memang frekuensi perubahannya sering. Sehingga user bisa mendapatkan assets terbaru, terlebih untuk assets yang terdapat fatal runtime error.

Untuk sesuatu yang tidak terlalu sering berubah (3rd party/vendor assets), mungkin tidak menggunakan revision id merupakan hal yang bijak.

Offline-first web is hard, but not with truly application

Sekarang sepertinya susah juga ya membedakan Web App dan Web app yang benar-benar application. Ecommerce bisa kita sebut Web App, tapi apakah benar-benar sebuah aplikasi?

Coba fikirkan tentang Figma, Web Assembly Studio, atau Gmail yang menurut gue benar-benar sebuah aplikasi. Silahkan buka iTerm, Sketch, atau Chrome. Kira-kira sudah jelas belum perbedaannya?

Untuk suatu aplikasi yang bukan benar-benar sebuah aplikasi gue sebutnya platform aja deh. Platform untuk jual-beli, aplikasi untuk membaca email, platform untuk belajar-mengajar secara online, aplikasi untuk melakukan meeting secara online.

Should my app implement PWA?

Jika dilihat dari benefit yang ditawarkan PWA, ya why not? Yang tidak perlu itu offline-first nya. Terlebih jika data yang ingin diproses sangat bergantung dengan jaringan/server.

Biasanya PWA sering dibandingkan dengan native app, padahal secara terminologi (sebagai “app”) enggak cocok menurut gue meskipun secara fungsionalitas (sebagai “app”) bisa dibandingkan.

Kayaknya ribet riz menerapkan strategi-strategi tersebut.

Yoi, tapi Workbox membuatnya lebih mudah. Meskipun Workbox memiliki tagline JavaScript Libraries for adding offline support to web apps, tapi tidak selalu tentang offline support kok. Mungkin gue lebih suka menyebutnya dengan JavaScript Libraries for adding reliable web apps in any network condition.

Dikasih enak, jangan ke-enakan.

GUE SIMPEN SEMUA ASSETS GUE DI CACHE BROWSER AH, KALAU ADA DATA TERBARU YA TINGGAL UPDATE AJA CACHENYA HAHAHA.

Ini bangsat emang

Untung ada limit untuk nyimpen cache. Bayangin kalau 80% cache yang disediakan oleh browser dipenuhi oleh cache web app lu semua

Selain konteks limit cache, juga di konteks pengetahuan. Mungkin kita tidak perlu mengetahui how it works nya dari cache-cache strategies tersebut, karena kita tinggal menggunakan higher-level API nya saja.

Tapi gue tidak merekomendasikan ini, setidaknya untuk diri gue sendiri. Gue harus tau apa yang terjadi dibalik magic tersebut.

We build progressive web app

Gue enggak terlalu yakin bahwa PWA adalah masa depan — terlebih karena Apple — tapi gue yakin dengan teknologi web. Teknologi web bertumbuh dengan lumayan liar, hasil pertaruhan gue ke teknologi web (terlebih ke JavaScript) ternyata tidak sia-sia meskipun kadang gue merasakan frustasinya nya di JavaScript & teknologi web.

Teknologi web menurut gue lebih privacy-friendly, open-standard oriented, dan cross-platform by design. Kenapa privacy friendly? Karena web app ter-isolasi. Tidak bisa langsung mengakses OS-level API. Gak tau deh kalau udah ada campur tangan yang merusak isolasi ini dengan dalih everything-but-business.

Kenapa berorientasi pada open standard? Karena gak ada yang benar-benar ngatur anjir. Bisa menjadi mimpi indah karena siapapun bisa ber-inovasi, dan menerapkannya sesuai standard bila tidak ingin tertinggal; Sekaligus bisa menjadi mimpi buruk (seperti IntersectionObserver yang sampai sekarang belum disupport di Safari stable, kecuali yang Technology Preview. Atau Web Push Notification yang belum support di Safari iOS).

Kenapa Cross Platform by design? Ya karena Web App tersebut berada di VM yang disediakan oleh browser. Seperti biasa, ada keuntungan dan kerugiannya juga. Keuntungannya adalah ya itu, cross-platform. Selagi browser yang ada didukung oleh OS tersebut, maka bisa dijalankan di OS apapun itu. Kekurangannya adalah ya jelas, limitasi. Tidak sebebas native mobile app yang mungkin bisa mengakses OS-level API.

Tapi gue yakin selagi terus berinovasi, dan selagi memang menguntungkan oleh banyak orang & bisa membantu pekerjaan kita sebagai manusia, lambat laun pasti akan diterapkan atas apa yang belum diterapkan saat ini.

References

Good evening and enjoy the rest of your friyay!