Encode (Kompresi) #
Kompresi response HTTP adalah salah satu optimasi performa web yang paling impactful. Dengan mengompresi teks (HTML, CSS, JavaScript, JSON) sebelum dikirim ke client, ukuran transfer bisa berkurang 60-80%, yang berarti halaman web dimuat jauh lebih cepat terutama untuk pengguna dengan koneksi lambat.
Caddy mendukung tiga algoritma kompresi modern: gzip (paling kompatibel), zstd (paling efisien), dan br (brotli, kompresi terbaik untuk teks). Caddy secara otomatis bernegosiasi algoritma yang didukung oleh client melalui header Accept-Encoding.
Cara Kerja Kompresi #
Tanpa kompresi:
Client → GET /app.js HTTP/1.1
Server → 200 OK
Content-Length: 125000
[125KB of JavaScript]
Dengan kompresi:
Client → GET /app.js HTTP/1.1
Accept-Encoding: gzip, deflate, br, zstd
Server → 200 OK
Content-Encoding: gzip
Content-Length: 28000 ← Turun dari 125KB ke 28KB (77% lebih kecil!)
[28KB gzip-compressed JavaScript]
Client decompress secara otomatis
Konfigurasi Dasar #
example.com {
# Aktifkan kompresi dengan semua algoritma yang tersedia
# Caddy otomatis memilih yang terbaik berdasarkan Accept-Encoding client
encode gzip zstd
file_server { root /var/www/html }
}
Semua Opsi Encode #
example.com {
encode {
# Aktifkan algoritma yang diinginkan
gzip # Kompatibilitas tertinggi (semua browser)
zstd # Efisiensi tinggi, kompatibilitas modern
# br # Brotli — perlu build dengan modul tambahan
# Minimum ukuran response sebelum dikompres (default: 512 bytes)
minimum_length 1024
# Jenis konten yang dikompres
# Default: text/*, application/json, application/javascript, dll.
# Bisa dikustomisasi jika perlu
match {
header Content-Type text/*
header Content-Type application/json*
header Content-Type application/javascript*
header Content-Type application/x-javascript*
header Content-Type image/svg+xml*
}
}
file_server { root /var/www/html }
}
gzip vs zstd vs Brotli #
Algoritma Rasio Kompresi Kecepatan Kompatibilitas
──────────────────────────────────────────────────────────────
gzip Baik (~70%) Cepat Semua browser (1990s+)
zstd Sangat Baik Sangat Cepat Modern browsers (2020+)
(~75%) (3-5x gzip)
brotli (br) Terbaik (~77%) Sedang Modern browsers (2016+)
Hanya via HTTPS
Rekomendasi praktis:
encode gzip zstd
→ zstd untuk browser modern (Chrome 94+, Firefox 98+, Edge 93+)
→ gzip fallback untuk browser lama dan tools (curl, wget)
Caddy otomatis pilih zstd jika client mendukung,
gzip jika tidak. Developer tidak perlu khawatir.
Jenis Konten yang Layak Dikompres #
Layak dikompres (teks, bisa mengecil 60-80%):
✓ text/html
✓ text/css
✓ text/javascript / application/javascript
✓ application/json
✓ application/xml / text/xml
✓ image/svg+xml
✓ text/plain
✓ application/x-javascript
✓ font/ttf, font/otf (font yang belum dikompres)
Tidak layak dikompres (sudah dikompres atau ukuran kecil):
✗ image/jpeg, image/png, image/webp (sudah dikompres)
✗ image/gif (sudah dikompres)
✗ video/mp4, video/webm (sudah dikompres)
✗ audio/mp3, audio/ogg (sudah dikompres)
✗ application/zip, application/gzip (sudah dikompres)
✗ font/woff, font/woff2 (sudah dikompres)
✗ File < 1KB (overhead kompresi tidak sepadan)
Encode dengan Reverse Proxy #
Ketika Caddy digunakan sebagai reverse proxy, kompresi bisa terjadi di dua tempat:
example.com {
# Kompresi di layer Caddy
# Caddy mengompres response dari backend sebelum dikirim ke client
encode gzip zstd
reverse_proxy backend:3000
# Catatan: Jika backend JUGA mengirim response yang sudah dikompres,
# Caddy tidak akan mengompres ulang (cek Content-Encoding dari backend)
}
Skenario dengan Backend yang Sudah Kompres #
example.com {
reverse_proxy backend:3000 {
# Jika backend mengirim header Accept-Encoding ke upstream,
# backend mungkin sudah mengompres response-nya
# Nonaktifkan Accept-Encoding forwarding jika Caddy yang akan kompres:
header_up -Accept-Encoding
}
# Caddy yang bertanggung jawab mengompres
encode gzip zstd
}
Mengukur Efektivitas Kompresi #
# Cek apakah kompresi aktif
curl -I -H "Accept-Encoding: gzip" https://example.com/ | grep -i "content-encoding"
# Output yang diharapkan: content-encoding: gzip
# Bandingkan ukuran dengan dan tanpa kompresi
echo "=== Ukuran tanpa kompresi ==="
curl -s --compressed -o /dev/null -w "%{size_download}" https://example.com/app.js
echo " bytes"
echo "=== Ukuran dengan kompresi ==="
curl -s -H "Accept-Encoding: gzip" -o /dev/null \
-w "Content-Length: %{size_download} bytes (actual transfer)\n" https://example.com/app.js
# Lihat rasio kompresi dari access log
cat /var/log/caddy/access.log | jq -r \
'select(.resp_headers["Content-Encoding"] != null) |
"\(.request.uri): \(.size) bytes (\(.resp_headers["Content-Encoding"][0]))"' | \
head -20
# Test zstd
curl -I -H "Accept-Encoding: zstd" https://example.com/ | grep -i "content-encoding"
Encode dan CDN #
Ketika menggunakan CDN di depan Caddy, perlu dipahami bagaimana CDN meng-cache response:
example.com {
encode gzip zstd
header {
# Instruksikan CDN untuk menyimpan versi berbeda berdasarkan encoding
Vary "Accept-Encoding"
# CDN harus meng-cache versi gzip DAN versi zstd secara terpisah
# sehingga bisa melayani yang tepat ke setiap client
}
file_server { root /var/www/html }
}
Pre-kompresi File Statis #
Untuk file statis yang tidak berubah, lebih efisien pre-kompres terlebih dahulu:
# Pre-kompres semua JS dan CSS di direktori build
find /var/www/html -name "*.js" -o -name "*.css" | while read f; do
gzip -9 -k "$f" # Buat .gz
# zstd -19 "$f" -o "$f.zst" # Buat .zst jika mau
done
# Verifikasi
ls -lh /var/www/html/assets/app.js*
# -rw-r--r-- app.js 125K
# -rw-r--r-- app.js.gz 28K (77% lebih kecil)
example.com {
root * /var/www/html
file_server {
# Aktifkan pre-compressed serving
# Caddy akan menyajikan app.js.gz jika client mendukung gzip
# tanpa perlu mengompres saat runtime!
precompressed gzip
}
}
Encode Bersama Templates #
Kompresi bekerja dengan baik bersama template rendering:
example.com {
root * /var/www/html
# Urutan penting: encode harus sebelum handler lain
encode gzip zstd
# Templates menghasilkan HTML, encode akan mengompresi hasilnya
templates
file_server
}
Mengukur Penghematan Bandwidth #
# Hitung total penghematan dari access log
# (memerlukan log yang menyimpan ukuran response)
cat /var/log/caddy/access.log | jq -r '
select(.resp_headers["Content-Encoding"] != null) |
[.size // 0, .resp_headers["Content-Encoding"][0]] |
@tsv
' | awk '{
total[$2] += $1
count[$2]++
} END {
for (enc in total) {
printf "%s: %d requests, %.1f MB compressed\n",
enc, count[enc], total[enc]/1048576
}
}'
Ringkasan #
- Selalu aktifkan
encode gzip zstd— pengurangan ukuran transfer 60-80% untuk file teks hampir tidak ada biaya CPU yang signifikan di hardware modern.- zstd lebih efisien dari gzip (lebih cepat dan rasio kompresi lebih baik) dan didukung oleh semua browser modern — gunakan keduanya bersama untuk kompatibilitas optimal.
- Caddy otomatis tidak mengompres file yang sudah dikompres (JPEG, PNG, video, ZIP) — kamu tidak perlu khawatir tentang double compression.
- Tambahkan header
Vary: Accept-Encodingsaat menggunakan CDN agar CDN meng-cache versi yang berbeda untuk client yang berbeda.- Untuk static sites, gunakan
precompressed gzipdifile_serveruntuk menyajikan file.gzyang sudah pre-kompres tanpa overhead kompresi runtime.- Posisikan
encodesebelum handler lain dalam konfigurasi — middleware dieksekusi dari atas ke bawah dan encode harus siap sebelum response dikirimkan.
← Sebelumnya: Redirect Berikutnya: Templates →
Encode dan TTFB (Time to First Byte) #
Satu trade-off kompresi adalah TTFB sedikit meningkat karena server perlu mengompres response sebelum mengirimnya. Untuk response kecil, ini mungkin tidak sepadan:
example.com {
encode {
gzip
zstd
# Jangan kompres response yang sangat kecil
# Default 512 bytes sudah cukup baik untuk kebanyakan kasus
minimum_length 1024
# Untuk API yang mengirim banyak response JSON kecil (<1KB),
# pertimbangkan meningkatkan minimum_length atau bahkan
# menonaktifkan kompresi untuk endpoint tersebut
}
# Matikan kompresi untuk endpoint health check
# (response kecil, dipanggil sangat sering)
@health path /health /ping /status
handle @health {
# Tanpa encode — langsung serve
respond "ok" 200
}
reverse_proxy backend:3000
}