Setiap aplikasi web yang saya deploy di Commsult Indonesia berada di belakang Cloudflare. Bukan hanya untuk perlindungan DDoS dan sertifikat SSL gratis — terutama untuk layer CDN yang mengurangi latensi bagi pengguna di Indonesia dan menghilangkan sebagian besar beban server origin. Tetapi perilaku caching default Cloudflare bersifat konservatif: hanya meng-cache ekstensi file statis (CSS, JS, gambar) dan mengabaikan HTML dan respons API. Membuat Cloudflare benar-benar meng-cache 70-90% traffic Anda memerlukan konfigurasi deliberat dengan Cache Rules. Panduan ini mencakup persis cara saya mengonfigurasi Cloudflare untuk aplikasi Next.js dan React yang berat pada aset statis.
Secara default, Cloudflare meng-cache daftar ekstensi file tertentu: gambar (jpg, jpeg, png, gif, webp, svg, ico), stylesheet (css), skrip (js), font (woff, woff2, ttf), dan beberapa lainnya. Apa pun yang tidak ada dalam daftar ini — HTML, JSON, XML, respons API — melewati ke origin Anda pada setiap permintaan. TTL cache browser default untuk aset yang di-cache adalah 4 jam. TTL cache edge default menghormati header Cache-Control origin Anda. Jika origin Anda tidak mengatur Cache-Control: max-age=xxx, Cloudflare menggunakan defaultnya sendiri (bervariasi berdasarkan paket). TTL edge default paket gratis untuk konten tanpa header Cache-Control adalah 4 jam.
Cache Rules (sebelumnya Page Rules — Cloudflare memigrasikan semua Page Rules ke Cache Rules pada 2024) memungkinkan Anda menentukan resource mana yang di-cache, berapa lama, dan dengan perilaku apa. Cache Rule untuk aset statis mencocokkan permintaan ke /static/*, /_next/static/*, atau /images/* dan mengatur Edge Cache TTL ke 1 tahun, Browser Cache TTL ke 1 bulan, dan Cache Level ke Standard. TTL panjang ini berfungsi karena Next.js content-hash nama file aset statisnya — ketika bundle JS berubah, nama file berubah, secara otomatis membuang cache. Aturan ini aman untuk diatur secara agresif.
Masalah umum yang saya lihat adalah cache hit rate yang stagnan di 30-40% bahkan dengan aturan yang dikonfigurasi. Penyebabnya: query string membuat kunci cache unik untuk aset yang sama, cookie mencegah caching, dan vary header memaksa entri cache terpisah per nilai Accept-Encoding. Untuk mendiagnosis, periksa header respons CF-Cache-Status — MISS berarti resource tidak di-cache, HIT berarti disajikan dari cache, BYPASS berarti aturan atau pengaturan mencegah caching. Gunakan Cache Analytics Cloudflare (tersedia di paket gratis) untuk melihat hit rate berdasarkan pola URL dan mengidentifikasi resource mana yang paling berkontribusi pada cache miss.
Dari pengalaman saya: konfigurasi Cloudflare dengan dampak tertinggi untuk aplikasi Next.js adalah mengaktifkan Tiered Cache di bawah Caching → Tiered Cache → Smart Tiered Cache Topology. Tiered Cache membuat hierarki di mana PoP edge (points of presence) memeriksa PoP tier atas sebelum pergi ke origin Anda. Untuk aset populer, satu PoP tier atas mengambil dari origin Anda, dan semua PoP tier bawah di region mengambil dari PoP tier atas. Untuk situs dengan pengguna di Jakarta dan Surabaya (dilayani oleh PoP Cloudflare yang berbeda), Tiered Cache memastikan PoP Surabaya mengambil dari hub Singapura Cloudflare daripada berulang kali menekan origin region Singapura Anda.
Aplikasi Next.js memiliki pola aset yang dapat diprediksi. Aset statis di bawah /_next/static/ ditujukan berdasarkan konten dan aman untuk di-cache selama 1 tahun. API Optimasi Gambar Next.js di /_next/image menghasilkan gambar yang dioptimalkan pada permintaan pertama dan meng-cache-nya — konfigurasikan Cloudflare untuk meng-cache ini dengan TTL edge 24 jam untuk menghindari optimasi berulang. Halaman HTML memerlukan keputusan yang cermat: halaman ISR Next.js memiliki logika revalidasi mereka sendiri, dan caching HTML Cloudflare yang agresif dapat mengganggu. Saya merekomendasikan meng-cache HTML hanya untuk halaman yang benar-benar statis (posting blog, landing page) dan melewati cache untuk halaman yang terautentikasi atau dipersonalisasi.
┌──────────────────────────────────────────────────────┐
│ Cloudflare Tiered Cache Flow │
├──────────────────────────────────────────────────────┤
│ │
│ User (Jakarta) → CF Jakarta PoP │
│ ↓ MISS │
│ CF Singapore Upper Tier │
│ ↓ MISS (first time only) │
│ Origin Server (Singapore) │
│ ↑ Response cached at Singapore upper tier │
│ │
│ User (Surabaya) → CF Surabaya PoP │
│ ↓ MISS │
│ CF Singapore Upper Tier → HIT! (no origin hit) │
│ │
│ Result: origin only hit once per unique asset │
└──────────────────────────────────────────────────────┘Query string merusak caching ketika konten yang sama diminta dengan parameter query yang berbeda. File JavaScript yang diminta sebagai bundle.js?v=1 dan bundle.js?v=2 membuat dua entri cache terpisah. Konfigurasikan Cache Rules untuk mengabaikan query string untuk aset statis menggunakan pengaturan 'Cache Key' — atur Query String ke 'Ignore'. Untuk halaman di mana query string mengubah konten (hasil pencarian, daftar yang difilter), pertahankan query string di kunci cache atau lewati cache sepenuhnya. Untuk endpoint API, lewati cache sepenuhnya kecuali responsnya secara eksplisit publik dan identik untuk semua pengguna dengan parameter yang sama.
Saya pernah mengonfigurasi Cache Rule Cloudflare yang cocok dengan /api/* dengan TTL cache edge 5 menit untuk mengurangi beban pada Node.js API. Aturan tersebut berhasil — cache hit rate melonjak dari 0% ke 60%. Tetapi saya tidak memperhitungkan respons spesifik pengguna: API profil pengguna di /api/user/profile sekarang mengembalikan respons yang di-cache dari permintaan pengguna lain. Cloudflare meng-cache respons yang berisi data pribadi karena origin tidak mengatur Cache-Control: private. Selalu atur Cache-Control: private, no-store pada respons apa pun yang berisi data spesifik pengguna. Cache Rule Cloudflare tidak boleh menimpa respons private.
Untuk aset yang benar-benar statis (gambar, font, file yang dapat diunduh), hosting di Cloudflare R2 daripada GCP Cloud Storage atau DigitalOcean Spaces menghilangkan biaya egress sepenuhnya — R2 tidak memiliki biaya egress. Aset yang disajikan dari R2 melalui jaringan Cloudflare sudah berada di edge, sehingga disajikan dari cache Cloudflare tanpa perjalanan pulang-pergi ke origin di region tertentu. Untuk file media yang jarang berubah, R2 + Cloudflare CDN lebih cepat sekaligus lebih murah daripada GCS + Cloudflare CDN. Saya memigrasikan katalog gambar produk klien kami (80GB) dari GCS ke R2 dan menghilangkan biaya egress GCS $6,80/bulan.
# Cloudflare Cache Rule for Next.js static assets
# Rule: Cache /_next/static/* aggressively (content-hashed filenames)
#
# Expression:
# (http.request.uri.path matches "^/_next/static/")
#
# Then:
# Cache Level: Standard
# Edge Cache TTL: 1 year
# Browser Cache TTL: 1 month
# Cache Key > Query String: Ignore
# Check cache status via response header
curl -I https://mysite.com/_next/static/chunks/main.js | grep cf-cache-status
# cf-cache-status: HIT
# Purge cache via API on deployment
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" -H "Authorization: Bearer API_TOKEN" -H "Content-Type: application/json" --data '{"purge_everything": true}'Cloudflare menyediakan analitik bawaan yang menampilkan cache hit rate, bandwidth yang dihemat, dan jumlah permintaan berdasarkan status cache. Tetapkan target 70%+ cache hit rate untuk situs yang berat pada aset statis. Di bawah 60% biasanya mengindikasikan masalah konfigurasi yang layak diselidiki. Header CF-Cache-Status dalam respons memberi tahu Anda persis apa yang terjadi untuk setiap permintaan: HIT (disajikan dari cache), MISS (tidak ada di cache, diambil dari origin), BYPASS (caching dilewati karena aturan atau cookie), EXPIRED (ada di cache tetapi TTL kedaluwarsa, diambil ulang dari origin), dan DYNAMIC (Cloudflare menentukan konten dinamis dan melewati caching).
Saya menempatkan setiap proyek di belakang Cloudflare dari hari pertama, bahkan side project pribadi. Paket gratis mencakup bandwidth CDN tanpa batas, SSL gratis melalui Let's Encrypt, perlindungan DDoS, dan Cache Rules dasar. Untuk proyek klien Commsult Indonesia, kami menggunakan paket Cloudflare Pro ($20/bulan) yang menambahkan optimasi gambar, kapasitas Cache Rule lebih banyak, dan Web Application Firewall. ROI-nya langsung terasa: berkurangnya beban server origin berarti ukuran VM yang lebih kecil, tagihan egress GCP yang lebih rendah, dan waktu respons yang lebih cepat bagi pengguna Indonesia yang secara geografis dekat dengan node edge Singapura dan Jakarta Cloudflare.
Sumber & Bacaan Lanjutan