Encode (Kompresi)

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-Encoding saat menggunakan CDN agar CDN meng-cache versi yang berbeda untuk client yang berbeda.
  • Untuk static sites, gunakan precompressed gzip di file_server untuk menyajikan file .gz yang sudah pre-kompres tanpa overhead kompresi runtime.
  • Posisikan encode sebelum 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
}
About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact