Kod Küçültme Rehberi: CSS, JS ve HTML
Kod küçültme (code minification), CSS, JavaScript ve HTML kaynağınızdan makinenin ihtiyaç duymadığı karakterleri (boşlukları, yorumları, satır sonlarını) kaldırır ve uzun yazımları daha kısa eşdeğerleriyle değiştirir. Davranış aynı kalır; dosya yalnızca küçülür ve daha hızlı yüklenir.
Baştan netleştirilmesi gereken en önemli şey şudur: küçültme, sıkıştırma değildir. Minify, kaynak kodunuz üzerinde çalışır ve sözdizimsel fazlalığı temizler. Gzip ve Brotli ise aktarımdaki baytlar üzerinde çalışır ve tekrarlayan kalıpları kodlar. Bunlar farklı aşamalarda çalışır, farklı türden fazlalıklara saldırır ve üst üste yığılır. Sunucunuz zaten Brotli sunarken bile neden hâlâ küçültme yapmanız gerektiğinin nedeni budur.
Hemen bir şey sıkıştırmak mı istiyorsunuz? Doğrudan CSS sıkıştırıcı, JavaScript sıkıştırıcı veya HTML sıkıştırıcı bölümüne geçin; her biri tamamen tarayıcınızda çalışır. Ancak mekanizmayı anlamak, nerede sıkıştırma yapacağınıza ve bunu elle yapmanıza gerek olup olmadığına karar vermenizi sağlar. Geri kalanı küçültmenin gerçekte ne yaptığını, CSS, JS ve HTML’in her birinin nasıl küçültüldüğünü, minify’ın gzip ve Brotli ile nasıl üst üste yığıldığını, build aracınızın bunu zaten ne zaman hallettiğini ve kaynak haritalarının küçültülmüş kodu nasıl hata ayıklanabilir tuttuğunu ele alıyor.
Küçültme nedir (ve ne değildir)
Küçültme iki şey yapar. Ayrıştırıcı için hiçbir anlam taşımayan karakterleri siler ve kaynağınızı tam olarak aynı anlama gelen daha kısa bir biçime yeniden yazar. Çıktı, bir makine için tamamen eşdeğer ve bir insan için neredeyse okunamaz hâldedir. Kodun nasıl çalıştığına dair hiçbir şey değişmez; yalnızca yüzeyi değişir.
Bu son nokta, rehberin geri kalanı boyunca akılda tutmanız gereken değişmezdir: minify yalnızca kaynağınızın yüzeyini düzenler (boşluk, yorumlar, tanımlayıcı adları, gereksiz sözdizimi), asla davranışı veya çıktıyı değil. Bu, biçimlendirmenin ayna görüntüsüdür. Biçimlendirme, kodu okunabilir kılmak için boşluk ekler; küçültme ise kodu ufaltmak için boşluğu temizler. İkisi de aynı “anlamsal olarak eşdeğer” ekseninde oturur, sadece zıt yönlere bakar.
İnsanlar sürekli kulağa benzer gelen üç işlemi karıştırır. Bu tablo onları ayırıyor:
| Boyut | Biçimlendirme (beautify) | Minify | Sıkıştırma (gzip/Brotli) |
|---|---|---|---|
| Neyi değiştirir | Boşluk, satır sonu, girinti ekler | Boşluk ve yorumları kaldırır, sözdizimini kısaltır | Tekrarlayan kalıpların bayt düzeyinde kodlanması |
| Hangi katman | Kaynak kodu | Kaynak kodu | Aktarım / depolama |
| Hâlâ kaynak kodu mu | Evet (okunabilir) | Evet (çalıştırılabilir, okunması zor) | Hayır (ikili, çözülmeli) |
| Kim yapar | Geliştirici / editör | Build aracı / minifier | Sunucu + tarayıcı |
| Geri alınabilir mi | Anlamsal olarak | Anlamsal olarak (davranış değişmez) | Tamamen (çözme baytları geri getirir) |
Biçimlendirme ve minify tek bir eksende, anlamsal eşdeğerlik ekseninde yaşar. Sıkıştırma ise tamamen farklı bir eksende yaşar. Biçimlendirilmiş bir dosya ve küçültülmüş bir dosya, ikisi de geçerli kaynaktır; sıkıştırılmış bir dosya ise herhangi bir şey çalışmadan önce çözülmesi gereken ikili bir veri yığınıdır.
Burada maliyetli bir yanılgı var: “Sunucum zaten gzip yapıyor, yani küçültme yapmak gereksiz.” Değil ve bu rehberdeki sayılar nedenini gösteriyor. Küçültme ve sıkıştırma farklı fazlalıkları kaldırır, dolayısıyla birini yapmak diğerini gereksiz kılmaz. Her dile teker teker bakarken bunu aklınızda tutun.
Minifier’ın kaldırdığı baytların neden en başta var olduğunu düşünmek yardımcı olur. Boşlukları, yorumları ve açıklayıcı adları kendiniz ve takım arkadaşlarınız için yazarsınız; bunlar kodu incelenebilir ve sürdürülebilir kılar. CSS’inizi ayrıştıran, JavaScript’inizi çalıştıran ya da DOM’unuzu oluşturan makine bunların her birini görmezden gelir. Küçültme, insanlar kaynakla işini bitirdikten sonra yalnızca insanlara ait malzemeyi atan adımdır. Küçültmenin neden bir üretim meselesi olduğu ve asla bir geliştirme meselesi olmadığı da budur: okunabilir sürümü deponuzda tutar, sadeleştirilmiş sürümü tarayıcılara gönderirsiniz. Okunabilir kopya gerçeğin kaynağıdır; küçültülmüş kopya ise istediğiniz zaman yeniden üretebileceğiniz bir build çıktısıdır.
CSS küçültme nasıl çalışır
CSS, üçü arasında küçültülmesi en yumuşak olanıdır, çünkü dilbilgisi belirsizliğe pek yer bırakmaz. Bir minifier yorumları temizler, ardışık boşlukları hiçliğe çökertir, her bloktaki son noktalı virgülü atar ve {, }, : ve ; çevresindeki boşlukları kaldırır. Bu tek başına baytların çoğunu temizler.
CSS ayrıca başka hiçbir dilin paylaşmadığı bir dizi eşdeğerlik yeniden yazımına izin verir. İyi bir minifier bunları güvenle uygular:
- Renkleri kısaltma.
#ffffff,#fffolur ve#ff0000,red’e çöker (ya da tam tersi, yazması hangisi daha kısaysa). - Sıfırda birimleri atma.
0px,0olur vemargin: 0 0 0 0,margin: 0olur. - Baştaki sıfırları temizleme.
0.5em,.5emolur. - Kısaltmaları birleştirme. Ayrı dört
margin-top,margin-right,margin-bottomvemargin-leftbildirimi tek birmargin’de toplanır. - Kuralları birleştirme. Aynı seçicilere veya bildirimlere sahip bitişik kurallar birleştirilebilir ve yinelenen bildirimler atılabilir.
Bunların her biri, oluşturulan sonucu özdeş tutar; uyumlu bir minifier’ın asla aşmadığı sınır budur. Ama CSS sıra duyarlıdır: sonraki bir kural, basamaklama (cascade) yoluyla öncekini geçersiz kılar. Bu yüzden güvenli bir minifier, hangi bildirimin kazandığını değiştirebilecek kuralları körü körüne yeniden sıralamaz. Baytları ufaltmak serbesttir; basamaklamayı değiştirmek değildir.
Bu kısıt, kulağa geldiğinden daha incedir. Birleştirilebilir görünen iki bildirim, aralarındaki bir şey aynı özgüllükte aynı özelliğe başvurduğu için birleştirilemez olabilir. Şunu düşünün:
.btn { color: #ff0000; }
.alert .btn { color: blue; }
.btn { color: #f00; }
Birinci ve üçüncü kurallar bir seçiciyi paylaşır ve birleşebilir, ama yalnızca bunu yapmak, her ikisiyle de eşleşen bir öğe için hangisinin kazandığını değiştirecek şekilde bildirimi ortadaki kuralın ötesine taşımıyorsa. Bunları yeniden sıralayan naif bir birleştirme basamaklamayı bozabilir. Bu, CSSO gibi üretim sınıfı bir motorun üzerine düşünmek için inşa edildiği türden bir uç durumdur ve kendi “boşlukları sil” minifier’ınızı bir regex ile el yordamıyla yazmamanızın nedeni de budur. Dönüşümler mekanik görünür, ama arkalarındaki güvenlik analizi öyle değildir.
CSS sıkıştırıcı aracımız tam da bu tür kayıpsız küçültme için CSSO motorunu kullanır ve tamamen tarayıcınızda, her geçişin yük etkisini görebilmeniz için bir bayt-tasarrufu göstergesiyle birlikte çalışır. Aynı araç diğer yönde de biçimlendirme yapar, böylece canlı bir siteden kopyaladığınız küçültülmüş bir stil sayfasını alıp okunabilir, girintili kurallara geri açabilirsiniz. Bir CSS parçasını kopyaladığınızda sıkıştırılmış boyutunu kontrol etmek istediğinizde ya da bunu sizin için yapacak bir build adımı olmayan statik bir sayfa yayınlarken ona başvurun.
JavaScript küçültme nasıl çalışır
JavaScript küçültme, CSS’ten çok daha ileri gider ve hem tasarrufların hem de tuzakların yaşadığı yer burasıdır. Nedenini görmek için küçük bir işleve Terser öncesi ve sonrası bakın:
// before
function calculateTotal(items, taxRate) {
let runningTotal = 0;
for (const item of items) {
runningTotal += item.price * item.quantity;
}
return runningTotal * (1 + taxRate);
}
// after
function calculateTotal(t,a){let n=0;for(const o of t)n+=o.price*o.quantity;return n*(1+a)}
calculateTotal işlev adı hayatta kalır çünkü dışa aktarılmıştır (ya da başka bir yerden çağrılabilir); parametreler ve döngü değişkenleri tek harflere çöker. Temel fikir bu, ama bir JS minifier’ı birkaç farklı şey yapar:
- Tanımlayıcı bozma (mangling). Yerel değişkenler ve parametreler tek harflere yeniden adlandırılır:
getUserPreferences,aolur. Yalnızca yereller bozulur; globaller ve dışa aktarılan adlar varsayılan olarak olduğu gibi kalır, çünkü onları yeniden adlandırmak dışarıdan onlara başvuran kodu bozardı. - Ölü kod eleme. Erişilemez dallar ve kullanılmayan değişkenler kaldırılır; bunlar paketleyici düzeyindeki tree-shaking ile el ele çalışır.
- Sabit katlama ve sözdizimi sıkıştırma. İfadeler kısaltılır:
true,!0olur,false,!1olur vereturn undefined;,return;olur.
JS küçültme hakkında bilinmesi gereken en önemli şey, otomatik noktalı virgül ekleme (ASI) tuzağıdır. JavaScript noktalı virgülleri atlamanıza izin verir ve ayrıştırıcı bunları belirli kurallar altında sizin yerinize ekler. Bir minifier bu kuralların dayandığı satır sonlarını sildiğinde, kod anlam değiştirebilir. Klasik hata, ( veya [ ile başlayan bir ifadenin sessizce bir önceki satıra yapışmasıdır:
const x = getValue()
[1, 2, 3].forEach(handle)
Noktalı virgüller olmadan bu, iki ifade olarak değil, bir indeksleme ifadesi olan getValue()[1, 2, 3] olarak ayrıştırılır. Tek satıra küçültüldüğünde, hata kilitlenir. Aynı tehlike, önceki ifadenin bir işlev gibi çağrıldığı ( ile başlayan bir satırda da ortaya çıkar. Modern Terser çoğu gerçek dünya durumunu sorunsuz ele alır çünkü kodu önce bir soyut sözdizimi ağacına ayrıştırır ve noktalı virgülleri gerekli oldukları yere yeniden yerleştirir; kör bir metin silme işlemi yapmıyor. Ama kötü kaynak ile saldırgan küçültmenin birleşimi gerçek bir üretim hatası kaynağıdır ve bu hatalar tam olarak yalnızca küçültülmüş build’de ortaya çıktıkları, geliştirmede çıkmadıkları için kötü huyludur. Çözüm sizin tarafınızda: kodu açık noktalı virgüller ve belirsizlik içermeyen sözdizimiyle yazın, böylece minifier güvende kalır. Kaynak düzeyinde noktalı virgül ekleyen bir linter kuralı veya otomatik biçimlendirici, riski tamamen ortadan kaldırır.
Uyumlu bir minifier davranışı korur, ama yalnızca girdi geçerli, standart JavaScript ise. Terser, ECMAScript’i ayrıştırır; TypeScript’i veya JSX’i anlamaz. Bunların önce düz JS’e dönüştürülmesi (transpile) gerekir, aksi takdirde küçültme ayrıştırma adımında başarısız olur. Bir .ts dosyasını bir JS minifier’a yapıştırıp hata alıyorsanız, nedeni budur.
Çokça gündeme gelen bir adlandırma sorusu var: minify mı uglify mi. Bunlar pratikte aynı anlama gelir. “Uglify”, erken dönemin popüler JS minifier’ı olan UglifyJS’ten gelir; Terser ise onun ES2015 ve sonrasını destekleyen modern bir çatallamasıdır (fork). Bugün “minify” üç dilin tamamında genel terimdir ve “uglify”, aynı işlem için daha eski, JS’e özgü bir ad olarak hayatta kalır.
JavaScript sıkıştırıcı aracımız Terser’ı tarayıcıda çalıştırır; yerelleri yeniden adlandırır, ölü kodu atar, yorumları temizler ve her geçişte kaç bayt tasarruf ettiğini bildirir.
HTML küçültme nasıl çalışır
HTML küçültme temellerle başlar: yorumları kaldır (<!DOCTYPE> bildirimini ve hâlâ güvendiğiniz koşullu yorumları koruyarak), etiketler arasındaki boşluğu çökert ve öznitelik listelerinin içindeki gereksiz boşlukları kırp. Küçük bir parça bunun biçimini gösteriyor:
<!-- nav -->
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
şuna dönüşür:
<ul><li><a href=/>Home</a><li><a href=/about>About</a></ul>
Yorum gitti, etiketler arasındaki girinti çöktü, isteğe bağlı </li> kapanış etiketleri atıldı ve tırnak gerektirmeyen öznitelik değerleri tırnaklarını kaybetti. Buradan bir minifier birkaç HTML’e özgü hile daha uygulayabilir:
- İsteğe bağlı kapanış etiketlerini kaldırma. HTML belirtimi
</li>,</p>,</td>ve diğer birkaçının atlanmasına izin verir, bu yüzden bir minifier onları atabilir. - Öznitelik tırnaklarını kaldırma. Bir değer boşluk veya özel karakter içermediğinde,
class="x",class=xolur. - Boole özniteliklerini çökertme.
disabled="disabled", yalnızcadisabledolur vechecked="checked",checkedolur. - Gömülü CSS ve JS’i küçültme.
<style>ve<script>bloklarının içeriği de küçültülür, böylece tek bir geçiş tüm belgeyi ufaltır.
En çok önem taşıyan sınır şudur: HTML’de boşluk bazen anlamlıdır. <pre> ve <textarea> içinde, her boşluk ve satır sonu olduğu gibi oluşturulur. white-space: pre özelliğine sahip öğeler de aynı şekilde davranır. Ve satır içi öğeler arasındaki boşluk düzeni etkiler: iki <a> etiketi arasındaki bir boşluk sayfada bir boşluk olarak görünür. Bu boşluğu düzleyen saldırgan küçültme, sayfanın görünümünü değiştirebilir. Genel kural: küçülttükten sonra, yayınlamadan önce pre, textarea ve satır içi öğe sınırları çevresindeki oluşturmayı doğrulayın.
HTML sıkıştırıcı aracımız js-beautify ile biçimlendirir ve gömülü stiller ile betikler için CSSO ve Terser ile küçültür; hepsi istemci tarafında. Sıkıştırmayı sizin için yapacak bir build adımının nadiren bulunduğu e-posta HTML’i ve CMS’ten dışa aktarılan işaretlemede özellikle işe yarar.
Minify vs Gzip vs Brotli: nasıl üst üste yığılırlar
Merkezdeki soru şu: sunucunuz zaten gzip veya Brotli sunuyorsa, hâlâ küçültme yapmanız gerekir mi? Evet ve nedeni, iki tekniğin farklı fazlalıkları kaldırmasıdır.
Küçültme, kaynak düzeyindeki sözdizimsel fazlalığı kaldırır: insanların okunabilirliği için var olan boşluklar, yorumlar, uzun adlar ve uzun yazımlar. Gzip ve Brotli ise bayt düzeyindeki istatistiksel fazlalığı kaldırır: dosya boyunca tekrarlayan dizeler ve kalıplar daha kısa kodlarla değiştirilir. Biri kodunuzun sözdizimini anlar; diğeri yalnızca bir bayt akışı görür. Farklı şeyleri hedefledikleri için üst üste yığmak iyi işe yarar.
Somut bir örnek: gzip, function dizesinin bir pakette iki yüz kez geçtiğini fark etmekte ve her geçişi kısa bir geri başvuruyla değiştirmekte harikadır. getUserPreferences ile getUserSettings’in kısaltabileceği değişken adları olduğu ya da bütün bir if (false) { ... } bloğunun asla çalışmayacağı konusunda hiçbir fikri yoktur. Küçültme tam da bunları, bayt düzeyinde bir sıkıştırıcının kör olduğu yapısal ve anlamsal kazanımları halleder. İkisini birlikte çalıştırın, her biri diğerinin göremediğini temizlesin.
Gerçekte gerçekleştiği sırayla hesap şöyle:
- Tek başına minify genellikle CSS, JS ve HTML’i %20–30 oranında küçültür; boşlukları ve yorumları kaldırarak ve sözdizimini kısaltarak.
- Küçültülmüş çıktı üzerinde gzip bir %60–80 daha kaldırır; metinde kalan tekrarlayan kalıpları kodlayarak.
- Gzip yerine Brotli, daha büyük yerleşik bir sözlük ve daha iyi bir algoritma sayesinde bir %15–25 daha küçük çıktı üretir.
Tek satırlık çıkarım: önce minify, sonra sıkıştırma; birleşik sonuç çoğu zaman orijinal kaynaktan %80–90 daha küçüktür. İkisi birbirini dışlamaz ve herhangi birini atlamak masada bayt bırakır.
Küçültme, Brotli’nin üstünde neden hâlâ ağırlığını çeker? Üç neden:
- Daha küçük girdi daha küçük sıkışır. Küçültülmüş bir dosya, sıkıştırıcıya çiğnenecek daha az fazlalık malzemesi verir ve daha küçük, daha temiz bir girdi genellikle daha küçük bir çıktı verir.
- Minify, sıkıştırmanın yapamadığı şeyleri yapar. Ölü kod eleme ve kısa değişken adları anlamsal kaldırmalardır. Gzip kodunuzu anlamaz, yalnızca baytları görür, bu yüzden asla kullanılmayan bir işlevi silemez veya bir değişkeni yeniden adlandıramaz.
- Tarayıcı daha az bayt ayrıştırır. Çözmeden sonra tarayıcı küçültülmüş kodu alır. Daha az kod, yalnızca daha küçük bir indirme değil, daha hızlı ayrıştırma ve yürütme demektir.
Sıra bir tercih değil, her adımın nerede yaşadığının doğal sonucudur. Küçültme build zamanına aittir (siz veya build aracınız bir kez yaparsınız). Sıkıştırma aktarım zamanına aittir (sunucu her istekte yapar, tarayıcı geldiğinde çözer). Yani işlem hattı doğal olarak minify → dağıt → sunucu sıkıştırır şeklindedir. Bunu tersine çalıştıramazsınız: “önce sıkıştır, sonra minify” diye bir şey yoktur, çünkü sıkıştırılmış çıktı artık kaynak kodu değildir.
“Önce minify, sonra sıkıştır” konusunda küçük ama önemli bir uyarı var: içerik bir kez sıkıştırıldıktan sonra, onu tekrar sıkıştırmak anlamsız ya da ters etki yaratır. Zaten ikili, yüksek entropili varlıklar (JPEG’ler, PNG’ler, WebP, WOFF2’deki yazı tipleri) gzip veya Brotli’den hiçbir şey kazanmaz ve metin sıkıştırma kurallarınızda hiç yer almamalıdır. Küçültme yalnızca metne yönelik bir dönüşümdür, bu yüzden o dosyalara asla dokunmaz; seçici olmanız gereken yer sıkıştırmadır. Sunucunuzu metin MIME türlerini (HTML, CSS, JS, JSON, SVG) sıkıştıracak, zaten sıkıştırılmış ikili dosyaları rahat bırakacak şekilde yapılandırın.
Aktarım katmanını yapılandırmak (Brotli’yi etkinleştirmek, Content-Encoding ayarlamak) sunucunuz veya CDN’iniz tarafından ele alınan bir operasyon meselesidir. Bu rehber, küçültmenin gerçekleştiği kaynak katmanında kalıyor. Yükü daha geniş biçimde optimize ediyorsanız, aynı “kodlama katmanında bayt tasarrufu” düşüncesi görüntülere de uygulanır; görüntü formatı rehberimiz o hikâyenin WebP/AVIF/JPEG tarafını ele alıyor.
Manuel küçültmeye ne zaman gerek yoktur
Birçok minifier pazarlamasının atladığı bir gerçek var: bir build adımınız varsa, üretim çıktınız zaten küçültülmüştür. Modern build işlem hatları bunu otomatik olarak yapar.
Vite ve esbuild, JavaScript ve CSS’i kutudan çıktığı hâliyle küçültür. Rollup ve webpack bunu TerserPlugin ve CssMinimizerPlugin aracılığıyla yapar. Lightning CSS, CSS’i yerel hızda işler. Next.js, Astro ve benzeri çerçeveler, üretim build’lerinde siz parmağınızı kıpırdatmadan küçültür, tree-shake yapar ve parçalara böler. Komut genellikle vite build veya npm run build’ten başka bir şey değildir; küçültme, “üretim için build” demenin bir parçasıdır, üstüne eklediğiniz ayrı bir adım değil. Projeniz buysa, bir dosyayı sonradan ayrı bir minifier’dan geçirmek en iyi ihtimalle gereksiz, en kötü ihtimalle zararlıdır; zaten küçültülmüş kodu çifte bozmak (mangle) kafa karıştırıcı çıktı üretebilir ve anlamlı bir ek bayt tasarrufu sağlamaz.
Build araçları, bağımsız bir minifier’ın yapamayacağı bir şeyi de yapar: tüm bağımlılık grafiğiniz bağlamında küçültürler. Tree-shaking özellikle yalnızca paketleyici her içe ve dışa aktarımı görebildiğinde ve belirli bir işlevin asla kullanılmadığını kanıtlayabildiğinde çalışır. Tek dosyalık bir minifier’ın üzerinde düşüneceği bir grafiği yoktur; size verdiğiniz dosyanın içindeki ölü kodu atabilir, ama içe aktarılan bütün bir modülün erişilemez olduğunu söyleyemez. Bu da üretim küçültmesinin doğru evinin build işlem hattı olmasının bir başka nedenidir.
Peki bağımsız bir minifier ne zaman doğru araçtır? Bunu sizin için yapan bir build adımının olmadığı dürüst durumlar kümesinde:
- Statik siteler ve elle yazılmış tek dosyalık sayfalar, döngüde bir paketleyici olmadan.
- E-posta HTML şablonları, birçok sistemin bayt başına ücret aldığı ve hiçbir build işlem hattının olmadığı yerlerde.
- Üçüncü taraf parçaları ve widget kodu, başkasının sayfasına gömdüğünüz.
- Hızlı boyut kontrolleri. Bir blok yapıştırın, küçülttükten sonra ne kadar büyük olduğunu ve ne kadar tasarruf ettiğinizi görün. Bayt-tasarrufu göstergesi bunun içindir.
- Başkasının küçültülmüş kodunu okumak, biçimlendiriciyi tersine çalıştırarak onu yeniden okunabilir kıldığınızda.
Karar basit. Build’iniz var mı? Bırakın build küçültsün. Build yok, tek seferlik bir iş ya da yalnızca bir boyut mu kontrol ediyorsunuz? Çevrimiçi bir araç en hızlı yoldur ve bu araçlar tamamen tarayıcınızda çalıştığından kodunuz cihazınızdan asla ayrılmaz. Bu, sunucu tarafında her şeyin bir kopyasını alan bir biçimlendiriciye asla yapıştırmamanız gereken tescilli veya henüz yayımlanmamış kod için önemlidir. Bu, bu kümedeki diğer biçimlendirme derinlemesine incelemesi olan SQL Stil Kılavuzu boyunca akan aynı gizlilik argümanıdır.
Kaynak haritaları: küçültülmüş kodun hata ayıklaması
Küçültülmüş kod tek başına bir hata ayıklama kâbusudur. Terser her yerel değişkeni a, b ve c olarak yeniden adlandırdıktan sonra, bundle.min.js:1:48211’i işaret eden bir üretim yığın izi gerçekte neyin bozulduğu hakkında size esasen hiçbir şey söylemez.
Kaynak haritaları bunu çözer. Bir kaynak haritası (source map), küçültülmüş çıktıdaki her konum ile orijinal kaynağınızdaki karşılık gelen konum arasındaki eşlemeyi kaydeden bir .map dosyasıdır. Tarayıcının DevTools’u onu yüklediğinde, küçültülmüş hataları gerçek dosya adlarına, satır numaralarına ve değişken adlarına geri çevirir. Tarayıcı, build’inizin ürettiği kodu çalıştırıyor olsa bile, yazdığınız koda karşı hata ayıklarsınız.
Pratikte build aracınız kaynak haritasını küçültülmüş paketin yanında üretir ve bir //# sourceMappingURL=bundle.min.js.map yorumu (veya bir HTTP başlığı) tarayıcıyı .map’e yönlendirir. DevTools’u açın, bir hataya rastlayın, yığın izi küçültülmüş çorba yerine gerçek dosya adlarınızı ve satır numaralarınızı gösterir. Harita tembel biçimde, yalnızca DevTools açıkken yüklenir, bu yüzden ziyaretçilerinize hiçbir maliyeti olmaz.
Bilmeye değer bir gizlilik boyutu var. Herkese açık bir kaynak haritası, DevTools’u açan herkese pratikte orijinal kaynak kodunuzu gönderir. Açık kod için bu sorun değil; tescilli kod için sorun. Gizli (hidden) kaynak haritalarının amacı budur: paket hiçbir sourceMappingURL yorumu taşımaz, böylece halk haritayı asla görmez, ama yine de onu Sentry gibi bir hata izleme hizmetine yüklersiniz. Hizmet, üretim yığın izlerini kendi tarafında küçültmeden çıkarır (de-minify) ve kaynağınızı dünyaya açmadan size okunabilir hatalar verir.
Bunun daha önceki noktayı nasıl pekiştirdiğine dikkat edin: kaynak haritaları bir build aracı yeteneğidir. Düz bir çevrimiçi minifier genellikle bir tane üretmez, çünkü tek seferlik sıkıştırmanın buna ihtiyacı yoktur. Bu da üretim küçültmesini build’inize bırakmanın bir başka nedenidir; haritayı bedavaya verir. Ve unutmayın, bir kaynak haritası asla küçültülmüş paketin kendisini değiştirmez; yanında oturan saf bir hata ayıklama yardımcısıdır. .map’i bir üretim bağımlılığı sanmayın.
Sık Sorulan Sorular
Küçültme, sıkıştırmayla aynı şey midir?
Hayır. Küçültme kaynak kodunuzu yeniden yazar; boşlukları, yorumları temizler ve adları kısaltır, böylece geçerli kod olarak kalır, sadece daha küçük. Sıkıştırma (gzip, Brotli) ortaya çıkan baytları aktarım için kodlar ve tarayıcı onları çözer. Farklı fazlalıklara saldırırlar, farklı aşamalarda çalışırlar ve üst üste yığılırlar: önce minify, sonra sıkıştırma.
Gzip veya Brotli kullanıyorsam küçültme yapmam gerekir mi?
Evet. Küçültme, gzip ve Brotli ile birlikte hâlâ önemlidir. Küçültülmüş kod sıkıştırıcıya daha az fazla girdi verir, böylece daha küçük sıkışır ve minify, bayt düzeyinde sıkıştırmanın yapamayacağı anlamsal kaldırmaları (ölü kod, kısa değişken adları) gerçekleştirir. Tarayıcı da daha az bayt ayrıştırır. Her ikisini de, o sırayla kullanın.
Küçültme kodumu bozar mı?
Uyumlu bir minifier davranışı korur: CSS özdeş biçimde oluşturulur ve Terser JavaScript’i eşdeğer tutar. Çıktı, kaynakla aynı şekilde çalışır. İki uyarı: otomatik noktalı virgül eklemeye dayanan JavaScript geçerli sözdizimine ihtiyaç duyar ve <pre> veya <textarea> gibi boşluk duyarlı HTML, küçülttükten sonra doğrulanmalıdır.
Minify ile uglify arasındaki fark nedir?
JavaScript için pratikte aynı anlama gelirler. “Uglify”, erken dönemin popüler JS minifier’ı olan UglifyJS’ten gelir; Terser ise güncel sözdizimini destekleyen modern bir çatallamasıdır. Bugün insanlar CSS, JS ve HTML genelinde genel olarak “minify” der, “uglify” ise aynı işlem için daha eski, JS’e özgü bir addır.
Geliştirme sırasında küçültme yapmalı mıyım?
Hayır. Üretim build’lerini küçültün, geliştirmeyi değil. Küçültülmüş kod okunamaz ve hata ayıklaması zordur, bu yüzden geliştirirken tam, biçimlendirilmiş kaynak istersiniz. Build aracınız (Vite, esbuild, webpack) üretim için build yaptığınızda otomatik olarak küçültür, çoğu zaman dağıtılan paketi hâlâ hata ayıklayabilmeniz için kaynak haritalarıyla birlikte.
Küçültme dosya boyutunu ne kadar azaltır?
Tek başına küçültme genellikle CSS, JS ve HTML’i yaklaşık %20–30 oranında küçültür; çoğunlukla boşlukları ve yorumları kaldırarak ve adları kısaltarak. Üstüne gzip veya Brotli katmanlandığında, birleşik sonuç çoğu zaman orijinal kaynaktan %80–90 daha küçüktür. Tam rakam, dosyanın ne kadar boşluk ve fazlalık içerdiğine bağlıdır.