D
P
0

CSS & Web Animation

Tailwind v4 `@source` Menghidupkan Lagi Class yang Sudah Kamu Hapus — Kecualikan Folder Seed/Import

27 Juni 2026·4 menit baca
Tailwind v4 `@source` Menghidupkan Lagi Class yang Sudah Kamu Hapus — Kecualikan Folder Seed/Import

Gejalanya bikin saya sempat ragu sama kewarasan sendiri. Saya bersih-bersih utility class yang sudah tidak dipakai di sebuah custom theme klien — class lama yang seharusnya sudah mati setelah komponennya saya rombak. Saya hapus class-nya dari template PHP, jalankan build Tailwind, lihat hasil CSS-nya, dan... class-nya masih ada. Saya hapus lagi, build lagi, masih ada. Tidak ada error, tidak ada warning, tidak ada apa-apa. CSS hasil compile tetap penuh class yang menurut saya sudah saya hapus.

Setup-nya kira-kira begini. Ini Tailwind v4, dan di entry CSS saya pakai @source yang lebar banget untuk memastikan semua template ke-scan:

@import "tailwindcss";
 
@source "../..";

@source "../.." itu menunjuk ke root proyek. Niatnya bagus: biar tidak ada template yang kelewat. Masalahnya, di root proyek itu ada satu folder yang sama sekali bukan bagian dari yang dikirim ke produksi.

Kenapa ini terjadi

Di proyek itu ada folder seed-import — sekumpulan file HTML hasil migrasi konten satu kali. Folder itu cuma ada untuk import awal: dump markup lama supaya kontennya bisa dipindahkan, lalu seharusnya tidak pernah disentuh lagi. Folder itu tidak pernah ikut ter-deploy. Tapi dia tetap ada di disk, di dalam root proyek, dengan markup lama yang masih dipenuhi class-class lawas.

Dan di situlah masalahnya. Content scanner Tailwind itu rakus. Dia tidak peduli apakah sebuah file benar-benar ter-render di situs atau cuma nongkrong di disk. Dia membaca setiap file yang cocok dengan glob @source, mencari string apa pun yang kelihatan seperti nama class, lalu menghasilkan CSS untuk semuanya. Scanner-nya tidak mengevaluasi kode, tidak tahu apa yang "dipakai" dalam arti runtime — buat dia, string yang cocok sama pola class itu sama saja dengan class yang dipakai.

Jadi alurnya jelas sekarang. Saya hapus .btn-legacy (dan teman-temannya) dari template PHP yang sebenarnya dikirim. Tapi string btn-legacy yang sama persis masih hidup di dalam file HTML lama di seed-import/. Karena @source "../.." mencakup folder itu juga, Tailwind menemukannya, menganggapnya "dipakai", dan meng-generate ulang CSS-nya. Setiap rebuild, scanner-nya menemukan kembali class-class itu dari folder seed dan menghidupkannya lagi. Saya merasa sedang menghapus class; Tailwind merasa sedang menemukannya. Kami berdua benar, dan justru itu yang bikin pusing.

Yang bikin bug ini licin adalah tidak ada sinyal kesalahan sama sekali. Build sukses. CSS valid. Class-nya pun beneran "ada sumbernya" — cuma sumbernya file yang tidak pernah saya buka dan tidak pernah saya pikirkan. Selama saya hanya melihat folder template, semuanya kelihatan seperti seharusnya class itu sudah hilang.

Perbaikannya

Begitu saya paham scanner-nya sedang membaca folder yang salah, solusinya langsung jelas: keluarkan folder yang tidak dikirim ke produksi dari scan. Tailwind v4 punya sintaks eksklusi pakai @source not:

@import "tailwindcss";
 
@source "../..";
@source not "../../seed-import";

Rebuild, dan class mati itu hilang. Beneran hilang. Folder seed-import sekarang dilewati scanner, jadi satu-satunya yang menentukan class mana yang di-generate adalah template yang benar-benar dikirim. Hapus class dari template, build, class-nya hilang — persis seperti yang saya harapkan dari awal.

Kalau kamu mau lebih ketat lagi (saya cenderung ke sini), jangan men-scan root proyek sama sekali. Persempit glob include-nya supaya cuma mengarah ke direktori template yang asli, dan tidak usah pakai eksklusi:

@import "tailwindcss";
 
@source "../templates";
@source "../parts";

Pendekatan ini saya suka karena membalik default-nya. Daripada men-scan semuanya lalu mengecualikan yang berbahaya satu per satu, kamu cuma scan yang memang dikirim. Folder baru yang muncul belakangan — folder seed lain, dump vendor, hasil build — tidak otomatis ikut ke-scan kecuali kamu sengaja menambahkannya. Buat saya itu sikap default yang lebih aman.

Mana yang dipilih tergantung struktur proyek. @source not enak kalau template-mu tersebar di banyak tempat dan lebih gampang men-scan luas lalu mengecualikan satu folder bermasalah. Glob yang dipersempit lebih bagus kalau template-mu memang rapi di beberapa direktori yang jelas. Dua-duanya menyelesaikan masalah inti: jangan biarkan scanner membaca markup yang tidak akan pernah kamu kirim.

Pelajaran

Content scan Tailwind itu greedy, dan dia memperlakukan setiap string yang cocok sebagai class yang dipakai. Dia tidak tahu mana file yang "live" dan mana yang cuma artefak — markup migrasi, dump seed, snippet vendor, output build, semua sama saja kalau ada di dalam jangkauan @source. Kalau kamu menghapus sebuah class tapi class itu tetap muncul di CSS hasil compile, jangan langsung curiga ke caching atau bug build tool. Tanya dulu: di mana lagi string ini masih hidup di dalam disk?

Aturan praktis yang saya pegang sekarang: kecualikan folder generated, seed, vendor, dan import dari scan Tailwind — entah pakai @source not atau dengan menyempitkan glob include. Kalau tidak, kamu akan terus mengirim utility mati yang kamu kira sudah dihapus, dan kamu akan menghabiskan satu sore yang aneh memelototi diff yang menolak berubah.