[Medium] π HTTP Caching
1. Apa itu HTTP caching dan mengapa penting?β
Apa itu HTTP caching? Mengapa penting?
HTTP caching adalah teknik yang menyimpan respons HTTP sementara di klien (browser) atau server perantara, sehingga permintaan selanjutnya bisa menggunakan ulang data yang di-cache tanpa harus mengakses server asal lagi.
Cache vs Penyimpanan Sementara (Temporary Storage)β
Dalam konteks teknis, kedua istilah ini sering tercampur, tapi keduanya memiliki tujuan yang berbeda.
Cacheβ
Definisi: salinan tersimpan yang digunakan untuk optimisasi performa, fokus pada penggunaan ulang dan akses yang lebih cepat.
Karakteristik:
- β Tujuan: peningkatan performa
- β Data diharapkan untuk digunakan ulang
- β Strategi kedaluwarsa/revalidasi yang eksplisit
- β Biasanya salinan dari data asli
Contoh:
// HTTP Cache - cache respons API
Cache-Control: max-age=3600 // cache 1 jam
// Memory Cache - cache hasil komputasi
const cache = new Map();
function fibonacci(n) {
if (cache.has(n)) return cache.get(n); // gunakan ulang cache
const result = /* hitung */;
cache.set(n, result);
return result;
}
Penyimpanan Sementara (Temporary Storage)β
Definisi: data yang disimpan untuk kebutuhan alur kerja sementara, menekankan siklus hidup yang singkat.
Karakteristik:
- β Tujuan: penyimpanan sementara
- β Penggunaan ulang opsional
- β Biasanya siklus hidup lebih pendek
- β Mungkin menyimpan state perantara
Contoh:
// sessionStorage - data formulir sementara
sessionStorage.setItem('formData', JSON.stringify(form));
// path file upload sementara
const tempFile = await uploadToTemp(file);
await processFile(tempFile);
await deleteTempFile(tempFile);
Perbandinganβ
| Fitur | Cache | Penyimpanan Sementara |
|---|---|---|
| Tujuan utama | Performa | Penyimpanan sementara |
| Penggunaan ulang | Ya, sering berulang | Tidak dijamin |
| Siklus hidup | Digerakkan kebijakan | Biasanya pendek |
| Penggunaan umum | HTTP cache, memory cache | sessionStorage, file temp |
| Istilah Inggris | Cache | Temp / Temporary / Buffer |
Perbedaan praktisβ
// ===== Skenario cache =====
// 1) HTTP cache: gunakan ulang respons API
fetch('/api/users').then((response) => response.json());
fetch('/api/users').then((response) => response.json());
// 2) memoization cache
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
};
// ===== Skenario penyimpanan sementara =====
// 1) simpan draf saat unload
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('formDraft', JSON.stringify(formData));
});
// 2) pemrosesan upload sementara
async function handleUpload(file) {
const tempPath = await uploadToTempStorage(file);
const processed = await processFile(tempPath);
await deleteTempFile(tempPath);
return processed;
}
// 3) hasil perantara sementara
const tempResults = [];
for (const item of items) {
tempResults.push(process(item));
}
const final = combine(tempResults);
Dalam pengembangan webβ
// HTTP Cache (berumur panjang, bisa digunakan ulang)
Cache-Control: public, max-age=31536000, immutable
// sessionStorage (sementara, cakupan per tab)
sessionStorage.setItem('tempData', data)
// localStorage (penyimpanan persisten, bukan lapisan optimisasi cache utama)
localStorage.setItem('userPreferences', prefs)
Mengapa perbedaan ini pentingβ
- Keputusan desain:
- Butuh optimisasi performa -> cache
- Butuh penyimpanan sementara -> temp storage
- Manajemen sumber daya:
- Cache fokus pada hit rate dan strategi kedaluwarsa
- Temp storage fokus pada waktu pembersihan dan batas ukuran
- Kejelasan wawancara:
- Pertanyaan performa -> bahas strategi caching
- Pertanyaan data sementara -> bahas strategi temp storage
Artikel ini terutama fokus pada cache, khususnya HTTP caching.
Manfaat cachingβ
- Lebih sedikit permintaan jaringan
- Beban server lebih rendah
- Pemuatan halaman lebih cepat
- Penggunaan bandwidth lebih rendah
- Pengalaman pengguna lebih baik
Lapisan cache browserβ
βββββββββββββββββββββββββββββββββββββββ
β Lapisan Cache Browser β
βββββββββββββββββββββββββββββββββββββββ€
β 1. Memory Cache β
β - Tercepat, kapasitas kecil β
β - Dibersihkan saat tab/sesi β
β berakhir β
βββββββββββββββββββββββββββββββββββββββ€
β 2. Disk Cache β
β - Lebih lambat, kapasitas besar β
β - Penyimpanan persisten β
βββββββββββββββββββββββββββββββββββββββ€
β 3. Service Worker Cache β
β - Dikontrol penuh oleh aplikasi β
β - Memungkinkan perilaku offline β
βββββββββββββββββββββββββββββββββββββββ
2. Apa saja strategi HTTP caching?β
Strategi caching apa yang ada di HTTP?
Kategori strategiβ
Strategi HTTP Caching
βββ Strong Cache (Segar)
β βββ Cache-Control
β βββ Expires
βββ Validation Cache (Negosiasi)
βββ Last-Modified / If-Modified-Since
βββ ETag / If-None-Match
1. Strong cache (cache segar)β
Perilaku: browser menyajikan dari cache lokal secara langsung tanpa mengirim permintaan ke server asal.
Cache-Control (HTTP/1.1)β
Cache-Control: max-age=3600
Directive umum:
// 1) max-age: masa berlaku kesegaran dalam detik
Cache-Control: max-age=3600
// 2) no-cache: izinkan caching tapi wajibkan revalidasi sebelum penggunaan ulang
Cache-Control: no-cache
// 3) no-store: jangan cache sama sekali
Cache-Control: no-store
// 4) public: bisa di-cache oleh browser/CDN/proxy
Cache-Control: public, max-age=31536000
// 5) private: hanya cache browser
Cache-Control: private, max-age=3600
// 6) immutable: konten tidak akan berubah selama masa kesegaran
Cache-Control: public, max-age=31536000, immutable
// 7) must-revalidate: setelah kedaluwarsa, harus revalidasi
Cache-Control: max-age=3600, must-revalidate
Expires (HTTP/1.0, legacy)β
Expires: Wed, 21 Oct 2025 07:28:00 GMT
Masalah:
- Menggunakan waktu absolut
- Bergantung pada kebenaran jam klien
- Sebagian besar digantikan oleh
Cache-Control
2. Validation cache (negosiasi)β
Perilaku: browser bertanya ke server apakah sumber daya berubah.
Last-Modified / If-Modified-Sinceβ
# respons pertama
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
# permintaan selanjutnya
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
Alur:
- Permintaan pertama: server mengirim
Last-Modified - Permintaan berikutnya: browser mengirim
If-Modified-Since - Tidak berubah: server mengembalikan
304 Not Modified - Berubah: server mengembalikan
200 OK+ body baru
ETag / If-None-Matchβ
# respons pertama
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
# permintaan selanjutnya
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Keunggulan:
- Lebih presisi dari
Last-Modified - Berbasis konten (hash atau token versi)
- Bisa mendeteksi perubahan yang tidak terlihat di timestamp level detik
Last-Modified vs ETagβ
| Fitur | Last-Modified | ETag |
|---|---|---|
| Presisi | Level detik | Token/hash konten, lebih presisi |
| Biaya | Lebih rendah | Mungkin perlu komputasi ekstra |
| Cocok untuk | File statis umum | Kontrol validasi yang tepat |
| Prioritas | Lebih rendah | Lebih tinggi (ETag diutamakan saat keduanya ada) |
3. Bagaimana cara kerja caching browser?β
Apa alur kerja cache browser?
Alur kerja lengkapβ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Alur Permintaan Sumber Daya Browser β
ββββββββββββββββββββββββββββββββββββββββββββββββ
β
1. Periksa Memory Cache
β
βββββββββ΄βββββββββ
β Hit cache? β
βββββββββ¬βββββββββ
Ya β Tidak
β
2. Periksa Disk Cache
β
βββββββββ΄βββββββββ
β Hit cache? β
βββββββββ¬βββββββββ
Ya β Tidak
β
3. Periksa Service Worker
β
βββββββββ΄ βββββββββ
β Hit cache? β
βββββββββ¬βββββββββ
Ya β Tidak
β
4. Periksa kesegaran
β
βββββββββ΄βββββββββ
β Kedaluwarsa? β
βββββββββ¬βββββββββ
Ya β Tidak
β
5. Revalidasi dengan server
β
βββββββββ΄βββββββββ
β Berubah? β
βββββββββ¬βββββββββ
Ya β Tidak (304)
β
6. Minta konten baru
β
βββββββββ΄βββββββββ
β Kembalikan β
β 200 + body β
β baru β
ββββββββββββββββββ
Contoh praktisβ
// permintaan pertama
GET /api/data.json
Response:
200 OK
Cache-Control: max-age=3600
ETag: "abc123"
{ data: "..." }
// dalam 1 jam
// strong cache hit -> gunakan lokal, tidak ada permintaan
// status yang ditampilkan devtools: from disk cache atau from memory cache
// setelah 1 jam
GET /api/data.json
If-None-Match: "abc123"
// tidak berubah
Response:
304 Not Modified
// berubah
Response:
200 OK
ETag: "def456"
{ data: "data baru" }
4. Apa saja strategi caching yang umum?β
Strategi caching praktis yang umum
1. Aset statis berumur panjangβ
// HTML: jangan cache lama, selalu validasi
Cache-Control: no-cache
// CSS/JS dengan hash: cache immutable yang lama
Cache-Control: public, max-age=31536000, immutable
// nama file: main.abc123.js
Prinsip:
- HTML harus tetap segar untuk mereferensikan hash aset terbaru
- Aset statis yang di-hash bisa di-cache untuk waktu lama
- Perubahan konten -> perubahan nama file -> unduhan baru
2. Sumber daya yang sering diperbaruiβ
// Data API: cache pendek + revalidasi
Cache-Control: max-age=60, must-revalidate
ETag: "abc123"
3. Strategi gambarβ
// avatar pengguna: cache menengah
Cache-Control: public, max-age=86400
// logo/ikon: cache lebih lama
Cache-Control: public, max-age=2592000
// gambar dinamis: validasi
Cache-Control: no-cache
ETag: "image-hash"
4. Kebijakan yang disarankan berdasarkan jenis sumber dayaβ
const cachingStrategies = {
html: 'Cache-Control: no-cache',
staticWithHash: 'Cache-Control: public, max-age=31536000, immutable',
staticAssets: 'Cache-Control: public, max-age=2592000',
apiData: 'Cache-Control: private, max-age=60',
userData: 'Cache-Control: private, no-cache',
sensitive: 'Cache-Control: no-store',
};
5. Service Worker cachingβ
Service Worker caching
Service Worker memberikan kontrol penuh atas runtime caching dan perilaku offline.
Penggunaan dasarβ
// daftarkan Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
// sw.js
const CACHE_NAME = 'my-app-v1';
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png',
];
// install: pre-cache aset statis
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(urlsToCache);
})
);
});
// fetch: contoh cache-first
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
// activate: bersihkan cache lama
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
})
);
});
Strategi SW yang umumβ
1. Cache Firstβ
// terbaik untuk aset statis
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
2. Network Firstβ
// terbaik untuk permintaan API
self.addEventListener('fetch', (event) => {
event.respondWith(
fetch(event.request)
.then((response) => {
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, responseClone);
});
return response;
})
.catch(() => {
return caches.match(event.request);
})
);
});
3. Stale While Revalidateβ
// terbaik untuk respons cepat + pembaruan di background
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
const fetchPromise = fetch(event.request).then((networkResponse) => {
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, networkResponse.clone());
});
return networkResponse;
});
return cachedResponse || fetchPromise;
})
);
});
6. Bagaimana cara mengimplementasikan cache busting?β
Bagaimana cara mengimplementasikan cache busting?
Cache busting memastikan pengguna mengambil aset terbaru saat konten berubah.
Metode 1: hashing nama file (direkomendasikan)β
// dengan Webpack/Vite
// output: main.abc123.js
// webpack.config.js
module.exports = {
output: {
filename: '[name].[contenthash].js',
},
};
<script src="/js/main.abc123.js"></script>
Kelebihan:
- β Nama file baru memaksa unduhan
- β File lama tetap bisa di-cache
- β Best practice industri
Metode 2: query versiβ
<script src="/js/main.js?v=1.2.3"></script>
<link rel="stylesheet" href="/css/style.css?v=1.2.3" />
Kekurangan:
- β Beberapa CDN/proxy memperlakukan caching query-string secara berbeda
- β Pemeliharaan versi manual
Metode 3: timestampβ
// umum hanya di development
const timestamp = Date.now();
const script = document.createElement('script');
script.src = `/js/main.js?t=${timestamp}`;
document.body.appendChild(script);
Kasus penggunaan:
- bypass cache di development
- tidak ideal untuk production
7. Pertanyaan wawancara caching yang umumβ
Pertanyaan wawancara caching yang umum
Pertanyaan 1: Bagaimana cara mencegah HTML di-cache?β
Klik untuk melihat jawaban
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
atau tag meta HTML:
<meta
http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"
/>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
Pertanyaan 2: Mengapa menggunakan ETag dan bukan hanya Last-Modified?β
Klik untuk melihat jawaban
Keunggulan ETag:
- Lebih presisi
- Validasi berbasis konten
- Menghindari kasus edge timestamp (re-deploy dengan konten yang sama)
- Lebih baik di sistem terdistribusi dengan jam yang tidak sinkron
Contoh:
// konten tidak berubah, waktu deployment berubah
// Last-Modified berubah, tapi konten identik
ETag: 'hash-of-abc'; // stabil jika konten tidak berubah
Pertanyaan 3: perbedaan antara from disk cache dan from memory cache?β
Klik untuk melihat jawaban
| Fitur | Memory Cache | Disk Cache |
|---|---|---|
| Penyimpanan | RAM | Disk |
| Kecepatan | Sangat cepat | Lebih lambat |
| Kapasitas | Lebih kecil | Lebih besar |
| Persistensi | Biasanya berumur pendek | Persisten |
| Prioritas | Lebih tinggi | Lebih rendah |
Urutan pemuatan umum (konseptual):
1. Memory Cache
2. Service Worker Cache
3. Disk Cache
4. Revalidasi / Jaringan
Pertanyaan 4: bagaimana cara memaksa browser memuat ulang sumber daya?β
Klik untuk melihat jawaban
Development:
// Hard Reload
// Nonaktifkan cache di DevTools
const script = document.createElement('script');
script.src = `/js/main.js?t=${Date.now()}`;
Production:
// nama file dengan hash (terbaik)
main.abc123.js
// query versi
<script src="/js/main.js?v=2.0.0"></script>
// kebijakan cache
Cache-Control: no-cache
Cache-Control: no-store
Pertanyaan 5: bagaimana cara mengimplementasikan cache offline di PWA?β
Klik untuk melihat jawaban
// sw.js
const CACHE_NAME = 'pwa-v1';
const OFFLINE_URL = '/offline.html';
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll([
OFFLINE_URL,
'/styles/offline.css',
'/images/offline-icon.png',
]);
})
);
});
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request).catch(() => {
return caches.match(OFFLINE_URL);
})
);
}
});
Strategi PWA lengkap biasanya menggabungkan:
// 1) aset statis: cache-first
// 2) API: network-first
// 3) gambar: cache-first
// 4) navigasi HTML: network-first + fallback offline
8. Best practiceβ
Best practice
β Direkomendasikanβ
// 1. HTML: jangan cache lama untuk memastikan dokumen entry terbaru
Cache-Control: no-cache
// 2. CSS/JS dengan hash: cache immutable yang lama
// contoh nama file: main.abc123.js
Cache-Control: public, max-age=31536000, immutable
// 3. Gambar: cache menengah/panjang
Cache-Control: public, max-age=2592000
// 4. Data API: cache pendek + validasi
Cache-Control: private, max-age=60
ETag: "api-response-hash"
// 5. Service Worker untuk dukungan offline
β Hindariβ
// buruk: cache lama untuk dokumen entry HTML
Cache-Control: max-age=31536000
// buruk: hanya mengandalkan Expires
Expires: Wed, 21 Oct 2025 07:28:00 GMT
// buruk: tidak ada header cache eksplisit
// buruk: kebijakan sama untuk semua jenis sumber daya
Cache-Control: max-age=3600
Pohon keputusan strategi cacheβ
Apakah ini aset statis?
ββ Ya -> nama file punya hash?
β ββ Ya -> cache immutable lama (max-age=31536000, immutable)
β ββ Tidak -> cache menengah/panjang (misal max-age=2592000)
ββ Tidak -> Apakah ini HTML?
ββ Ya -> no-cache
ββ Tidak -> Apakah ini API?
ββ Ya -> cache pendek + validasi (max-age=60 + ETag)
ββ Tidak -> tentukan berdasarkan frekuensi pembaruan