Sore itu tugasnya sepele: memperbaiki perilaku menu navigasi mobile di situs membership klien. Saya buka assets/js/src/nav.js, ubah beberapa baris, simpan, upload. Hard refresh di browser. Tidak ada perubahan. Refresh lagi sambil menahan Shift. Tetap tidak ada. Saya naikkan ?ver= di enqueue, purge cache halaman, buka incognito, bahkan tes dari HP pakai data seluler. Menu tetap berperilaku seperti sebelum saya edit, seolah perubahan saya tidak pernah ada.
Refleks pertama saya, seperti biasa, menyalahkan cache. Pasti ada satu lapisan lagi yang belum saya purge: object cache, CDN, cache browser yang bandel. Tapi setelah ?ver= naik, cache halaman di-purge, dan incognito pun masih menampilkan perilaku lama, teori cache mulai tidak masuk akal. Kalau cache-nya sudah dibust dan hasilnya tetap sama, mungkin yang dikirim server memang masih file lama.
Jadi saya lakukan hal yang seharusnya saya lakukan dari menit pertama: cek file mana yang sebenarnya di-load browser. Buka DevTools, tab Network, filter JS, refresh. Dan di situlah jawabannya. Browser tidak pernah me-load nav.js sama sekali. Yang di-load adalah nav.min.js, dari folder dist. Saya klik file-nya, lalu cari nama fungsi baru yang barusan saya tulis. Nol hasil. File yang saya edit dan file yang dikirim ke pengunjung adalah dua file yang berbeda.
Kenapa ini terjadi
Tema ini punya enqueue helper dengan pola yang sangat umum: kalau ada versi minified hasil build di folder dist, pakai itu; kalau tidak ada, fallback ke source. Kurang lebih seperti ini:
function theme_enqueue_nav_script() {
$src_rel = '/assets/js/src/nav.js';
$min_rel = '/assets/js/dist/nav.min.js';
$rel = file_exists( get_template_directory() . $min_rel )
? $min_rel
: $src_rel;
wp_enqueue_script(
'theme-nav',
get_template_directory_uri() . $rel,
array(),
'1.4.2',
true
);
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue_nav_script' );Pola file_exists( $min ) ? $min : $src ini niatnya bagus: production selalu dapat file yang kecil dan teroptimasi. Tapi di dalamnya ada asumsi tersembunyi bahwa file dist selalu sinkron dengan source. Begitu saya lupa menjalankan build setelah edit, dist jadi stale, file_exists tetap true, dan helper dengan setia menyajikan file minified lama itu. Edit saya di src tidak pernah punya jalan untuk sampai ke browser.
Bagian yang paling menyesatkan justru ?ver=. Menaikkan versi di enqueue itu benar-benar bekerja: browser mengunduh ulang file-nya, cache-bust berhasil. Tapi yang diunduh ulang adalah byte minified lama yang sama persis. Jadi semua gejalanya terlihat seperti masalah caching, dan setiap "perbaikan cache" yang saya lakukan memang berjalan tanpa mengubah apa pun, karena masalah sebenarnya ada satu langkah lebih awal: di build step.
Perbaikannya
Perbaikan langsungnya sederhana: jalankan build supaya dist digenerate ulang dari source yang baru.
npm run buildBegitu nav.min.js yang baru terbentuk dan ikut terdeploy, perubahan saya langsung tampil. Dan karena helper memilih file dist, file itulah yang benar-benar dikonsumsi production, jadi hasil build harus ikut di-commit, bukan cuma source-nya.
Untuk jangka panjang, saya tidak mau bergantung pada ingatan "habis edit harus build". WordPress sudah menyediakan jalan keluarnya: konstanta SCRIPT_DEBUG, yang memang dirancang untuk memaksa versi un-minified saat development. Aktifkan di wp-config.php lokal:
define( 'SCRIPT_DEBUG', true );Lalu ubah helper supaya menghormatinya:
$use_min = file_exists( get_template_directory() . $min_rel )
&& ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG );
$rel = $use_min ? $min_rel : $src_rel;Dengan ini, di lokal browser selalu me-load file source langsung, jadi setiap edit langsung live tanpa build. Di production, SCRIPT_DEBUG tidak didefinisikan, dan pengunjung tetap dapat file minified seperti seharusnya.
Checklist
Kalau edit JavaScript kamu terasa "tidak melakukan apa-apa", cek ini dulu sebelum menyalahkan cache:
- Pastikan file mana yang benar-benar di-load browser: DevTools, tab Network, buka file JS-nya, lalu cari potongan kode baru kamu di dalamnya. Kalau kode barunya tidak ada di file itu, masalahnya bukan cache.
- Kenali enqueue helper tema kamu. Kalau ada logika preferensi
.min.jsdaridist, edit di source tidak akan pernah sampai ke browser tanpa menjalankan build. - Jadikan build bagian dari alur kerja: setiap edit JS diikuti
npm run build, dan filedistikut di-commit. - Aktifkan
SCRIPT_DEBUGdiwp-config.phplokal supaya saat development yang disajikan selalu source, bukan hasil build lama.
Sejak hari itu, "cache" turun pangkat jadi tersangka terakhir yang saya periksa, bukan yang pertama. Pertanyaan pembuka saya sekarang selalu sama: file mana yang sebenarnya sampai ke browser?
