Belajar RoadRunner - Caching & Static Assets
Episode 13 of 26

Belajar RoadRunner - Caching & Static Assets

Mengoptimalkan penyajian file statis di RoadRunner: mengonfigurasi middleware static dengan forbid dan cache headers, memakai ETag serta last-modified, mengirim file besar lewat sendfile, dan menyusun strategi long-term caching untuk aset.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Di episode 5 kita sudah menyentuh http.static sebagai middleware. Pada episode kali ini kita memaksimalkannya: caching & static assets yang benar-benar dioptimalkan — header cache, ETag, kompresi, dan sendfile — supaya aset dilayani secepat mungkin dan bandwidth browser terhemat.

Mengapa episode ini penting? Karena aset statis (CSS, JS, gambar) adalah sebagian besar request di aplikasi web nyata. Jika aset sampai ke worker PHP, kalian membuang resource worker untuk pekerjaan yang seharusnya selesai di level Go dalam mikro detik. Episode ini menutup lubang performa paling umum.

Konfigurasi Static yang Lengkap

Blok static lengkap
http:
  address: 0.0.0.0:8080
  middleware: ["static", "gzip", "sendfile"]
  static:
    dir: public
    forbid: [".php", ".htaccess"]
    always: ["robots.txt", "favicon.ico"]
    cache:
      etag: true
      last_modified: true
KeyFungsi
dirDirektori root file statis
forbidEkstensi yang tidak boleh dilayani (keamanan)
alwaysFile yang selalu dilayani meski ada worker handler dengan path sama
cache.etagKirim header ETag untuk validasi cache
cache.last_modifiedKirim header Last-Modified

Cara Kerja: ETag dan Last-Modified

Saat browser meminta ulang file, header validasi menentukan apakah browser boleh pakai cache lokal:

  • ETag: server mengirim hash isi file. Browser membawa If-None-Match pada request berikutnya; bila hash cocok, server membalas 304 Not Modified (tanpa body) — hemat bandwidth total.
  • Last-Modified: versi sederhana berbasis waktu modifikasi file, divalidasi lewat If-Modified-Since.

Keduanya diaktifkan hanya dengan cache.etag: true dan cache.last_modified: true. Untuk file yang berubah-ubah (konten dinamis), keduanya diabaikan karena respons tidak berasal dari static.

Uji dengan curl:

Verifikasi header cache
curl -I http://localhost:8080/assets/app.css
curl -I -H "If-None-Match: <etag-dari-respons>" http://localhost:8080/assets/app.css

Respons kedua harus HTTP 304 — konfirmasi cache validasi bekerja.

Tip

Pasangkan dengan gzip di middleware supaya aset teks (CSS/JS/HTML) dikompresi sebelum dikirim. Urutan ["static", "gzip", "sendfile"] membuat Go: (1) menemukan file, (2) mengompresnya, (3) mengirim via kernel.

Sendfile: Kirim File Besar Tanpa Membebani Memory

Middleware sendfile memakai syscall kernel sendfile(2) untuk mengirim file langsung dari disk ke socket, tanpa membaca seluruhnya ke memory Go:

Aktifkan sendfile
http:
  middleware: ["static", "sendfile"]

Kapan berguna? Untuk file besar seperti video, archive, atau font besar yang diunduh ribuan kali. Tanpa sendfile, file 500 MB akan dimuat ke memory Go lalu disalin ke socket — boros memory dan CPU. Dengan sendfile, kernel yang menangani transfer — memory Go hampir tidak terpakai.

Long-Term Caching untuk Aset Ber-version

Aset yang namanya mengandung hash konten (hasil build Vite/Webpack) aman di-cache selama mungkin — isinya tidak akan berubah selama nama file tidak berubah. Tambahkan header Cache-Control untuk aset statis:

Cache-Control untuk aset ber-version
http:
  middleware: ["static", "headers", "gzip"]
  headers:
    response:
      "Cache-Control": "public, max-age=31536000, immutable"

Simpulan strategi cache:

Jenis FileHeaderAlasan
assets/build-*.{js,css} (hash)immutable, 1 tahunIsi tetap selama nama berubah
HTML, manifestTanpa cache agresifHarus selalu fresh
Gambar statismax-age=604800 (1 minggu)Berubah jarang, tanpa hash di nama
API responsesJangan cache browserBerbasis logika bisnis

Warning

Jangan pasang immutable global untuk semua file. Hanya aset yang ber-version (nama file memuat hash isi) yang aman dengan cache 1 tahun. Untuk file biasa, gunakan max-age wajar agar perubahan tetap terdeteksi.

Common Pitfalls

KesalahanDampakSolusi
forbid tidak lengkapSource .php/.env bocorSet forbid: [".php", ".htaccess", ".env", ".git"]
Aset tanpa cache headerBandwidth boros, TTFB lambatSet Cache-Control via headers
URL aset tanpa hash + cache lamaUser melihat versi lamaCache immutable hanya untuk file ber-version
Statis di-serve lewat PHPWorker penuh untuk asetPastikan static di posisi pertama middleware

Penutup

Pada episode 13 ini, kalian telah mengoptimalkan static assets.

Inti yang harus dibawa pulang:

  • http.static melayani file dari dir dengan forbid untuk keamanan.
  • ETag/Last-Modified mengaktifkan validasi cache (304).
  • sendfile mengirim file besar via kernel — hemat memory Go.
  • Header Cache-Control agresif hanya untuk aset ber-version.
  • Selalu lengkapi forbid; jangan pernah menyentuh PHP untuk aset.

Di episode 14 selanjutnya, kita belajar sessions, state & stateless best practice — mengapa worker persistent melarang state request-scoped, bagaimana mengelola session dengan aman, dan praktik refactor aplikasi agar worker-safe. Sampai jumpa di episode 14!

Belajar RoadRunner - Caching & Static Assets | Belajar RoadRunner