Ana içeriğe geç

Mangle Nedir? JavaScript Değişken İsimlerini Kısaltma

Mangle Nedir? JavaScript Değişken İsimlerini Kısaltma - Web Geliştirme Rehberi

Bundle boyutunu küçültmek için minify açılır, build birkaç saniye daha hızlı biter ve iş tamam sanılır. Çoğu ekipte mangle seçeneği ise biraz tereddütle ele alınır. Çünkü değişken adlarını tek harfe düşürmek kulağa agresif gelir. “Kod kırılır mı?”, “Stack trace okunmaz hale mi gelir?”, “Gzip zaten sıkıştırıyor, buna gerçekten gerek var mı?” gibi sorular bu noktada başlar.

Mangle, JavaScript dosyasındaki yerel değişken, parametre ve bazı fonksiyon adlarını daha kısa isimlerle değiştirir. subtotalAmount yerine a, formattedCurrency yerine b yazılması gibi düşünün. Tarayıcı için bu isimlerin anlamsal değeri yoktur; önemli olan referansların tutarlı kalmasıdır. Aynı davranış korunduğu sürece dosya küçülür, parse maliyeti biraz düşer ve özellikle tekrar eden uzun tanımlarda ek kazanç elde edilir.

Yine de mangle her projede körlemesine açılacak seçenek değildir. Gzip ile birlikte gerçek kazanç bazen sınırlı kalır, bazı yapılarda ise tam tersine oldukça verimli sonuç üretir. Eğer farklı minify seçeneklerini tarayıcı içinde karşılaştırmak istiyorsanız mangle, compress ve beautify akışını yan yana görmek bu farkı daha net gösterir. Mesele yalnızca dosyayı küçültmek değil, hangi isimlerin güvenle kısalabileceğini bilmektir.

Mangle tam olarak ne yapar?

Minify ile mangle aynı şey değildir. Minify çoğunlukla yorumları, gereksiz boşlukları ve satır sonlarını temizler. Compress daha ileri gidip ölü kodları atar, bazı ifadeleri sadeleştirir, console çağrılarını kaldırabilir. Mangle ise isim düzeyinde çalışır. Yani kodun mantığını değil, kimlik etiketlerini küçültür.

Bunu küçük bir örnekle görmek daha kolaydır:

function renderCartSummary(items) {
    const taxRate = 0.2;
    const subtotalAmount = items.reduce((sum, item) => sum + item.price, 0);
    const totalAmount = subtotalAmount * (1 + taxRate);
    return totalAmount.toFixed(2);
}

Minify, compress, mangle ve obfuscation aynı katmanda değildir

Mangle sonrasında aynı mantık daha kısa isimlerle şu hale gelebilir: function renderCartSummary(t){const a=.2,e=t.reduce((t,a)=>t+a.price,0),n=e*(1+a);return n.toFixed(2)}. Burada dikkat edilmesi gereken nokta şu: renderCartSummary adı korunabilir, içerideki yerel isimler ise kısalabilir. Örneğin bu sitedeki Minify aracı Terser üzerinde çalışıyor ve varsayılanında toplevel: false kullanıyor. Yani üst seviye isimleri körlemesine ezmek yerine daha güvenli bir çizgi seçiyor.

Bu ayarın önemi pratikte hemen anlaşılmaz. Yerel scope içindeki isimler, dış dünya ile sözleşme kurmadığı için güvenle kısalabilir. Ama üst seviyede duran bir isim çoğu zaman başka script’lerle, tarayıcı konsoluyla ya da hata izleme sistemleriyle temas eder. Bir ekibin “mangle açtık, bir şey olmadı” demesi ile “mangle açtık, ödeme akışı bozuldu” demesi arasındaki fark çoğu zaman tam bu sözleşme yüzeyinde ortaya çıkar.

Hangi isimler kısalır, hangileri olduğu gibi kalmalıdır?

En güvenli adaylar, sadece tek bir modül ya da fonksiyon içinde yaşayan yerel isimlerdir. Döngü sayaçları, ara hesap değişkenleri, callback parametreleri ve geçici obje referansları buna girer. Tarayıcı bu isimlerin “anlamını” bilmez; sadece bağlandıkları scope zincirini takip eder. Bu yüzden subtotalAmount yerine a kullanılması davranışı bozmaz.

Risk tarafı public API yüzeyinde başlar. Eğer bir isim dışarıdan çağrılıyorsa, global nesneye yazılıyorsa, HTML içinden referans alınıyorsa veya başka bir paket tarafından string olarak aranıyorsa o ismi kısaltmak sorun çıkarabilir. window.checkoutApi, data-module="checkoutManager", form["customerEmail"] gibi yapılar buna örnektir. Burada problem JavaScript sözdizimi değil, dış dünyanın bu isme bağımlı olmasıdır.

İşlem Ne değişir? Asıl amaç
Minify Boşluk, yorum, satır sonu Ham dosya boyutunu küçültmek
Compress İfade sadeleştirme, ölü kod temizliği Daha verimli çıktı üretmek
Mangle Değişken ve parametre isimleri Ek küçülme ve daha kısa referanslar
Obfuscation Akış, string, isim ve yapı Kodu anlamayı zorlaştırmak

Bir başka ayrım da property adı ile değişken adının farklı şeyler olmasıdır. Mangle çoğu kurulumda property isimlerine dokunmaz. Yani service.openCart() çağrısında service kısalabilir ama openCart çoğu zaman aynı kalır. Bu, UI bileşenleri ve test altyapıları için önemli bir emniyet katmanıdır.

window.checkoutApi = {
    openCart() {
        return true;
    }
};

const checkoutApi = window.checkoutApi;
checkoutApi.openCart();

Bu örnekte yerel taraftaki checkoutApi referansı kısalsa bile window.checkoutApi ve openCart dış entegrasyon açısından anlam taşımaya devam eder. Eğer üst seviye isimleri de mangle etmeye kalkarsanız artık aynı nesneye başka script’lerin ulaşması zorlaşır. Bu nedenle mangle kararını verirken “hangi isimler sadece derleyicinin umurunda, hangileri uygulamanın dışına söz veriyor?” sorusunu açık biçimde ayırmak gerekir.

Eğer build hattınızda top-level mangle açacaksanız, “rezervli isim” listesi düşünmek gerekir. Globalde kalması gereken işaretleyiciler, hata yakalama servislerinin okuduğu sınıf adları, reflection kullanan kısımlar ve bazı framework entegrasyonları buna girer. Bu sitedeki araçta top-level kapalı olduğu için varsayılan davranış daha güvenlidir; ama büyük projelerde ek yapılandırma kaçınılmaz hale gelir.

Mangle ne kadar kazanç sağlar?

Bu sorunun tek bir cevabı yok. Ham dosya boyutunda görülen fark ile gzip sonrası taşınan gerçek fark aynı değildir. Uzun değişken isimlerinin çok tekrar ettiği, yorumlardan arındırılmış ama hâlâ okunaklı yazıldığı bir uygulamada mangle ciddi ek kazanç getirir. Fakat zaten kısa yazılmış, modüllere bölünmüş ve gzip altında iyi sıkışan bir pakette artış daha sınırlı olabilir.

Durum Ham boyut Gzip sonrası Not
Yalnız minify 180 KB 52 KB Boşluklar gider, isimler kalır
Minify + mangle 150 KB 49 KB Ham fark büyük, gzip farkı daha sınırlı

Bu örnekte ham tarafta 30 KB tasarruf vardır. Gzip altında ise sadece 3 KB görünür. O zaman mangle gereksiz mi? Her zaman değil. Çünkü ağ maliyeti tek ölçü değildir. Tarayıcı daha kısa token akışıyla çalışır, parse edilen kaynak biraz azalır ve özellikle mobil cihazlarda milisaniye bazlı kazanımlar birikerek TBT ya da INP çevresinde etkisini gösterebilir.

Gzip tarafındaki farkın daralmasının nedeni de anlaşılmalıdır. Gzip tekrar eden byte dizilerini zaten iyi sıkıştırır. Uzun değişken isimleri on kez geçiyorsa, bu tekrarın önemli kısmı sıkıştırma katmanında telafi edilir. Bu yüzden bazı ekipler yalnızca ham boyuta bakıp mangle’a fazla anlam yükler. Oysa gerçek karar çoğu zaman “hamda ne kazandık?” sorusundan çok “taşınan veri, parse süresi ve bakım maliyeti birlikte ne söylüyor?” sorusuyla verilmelidir.

Burada sayfa tipi de önemlidir. Kritik ilk ekran paketinde 6 KB bile kıymetli olabilir. Yönetim paneli gibi yalnızca giriş yaptıktan sonra yüklenen ağır bir ekranda aynı 6 KB daha önemsiz kalabilir. Yani mangle kazancı mutlak değildir; kullanıcı akışındaki yerine göre değer kazanır ya da sıradanlaşır. Teknik yazılarda gözden kaçan nokta tam budur.

Öte yandan ham boyuta bakıp abartılı vaat üretmek de doğru olmaz. Mangle çoğu projede tek başına yüzde 30 mucize yaratmaz. Daha makul aralık, minify edilmiş JavaScript üzerinde ek yüzde 5-15 küçülmedir. Çok tekrar eden adlar varsa yukarı çıkabilir. Yoksa daha aşağıda kalır. Bu nedenle gerçek performans farkını Lighthouse tabanlı hız raporunda ölçmeden karar vermek eksik olur.

Bir istisna daha var: büyük framework uygulamalarında kaynak kod zaten araç zinciri tarafından optimize edildiği için mangle kazancı görünürde düşük kalabilir. Buna karşılık kendi yazdığınız yönetim paneli, dashboard ya da eski jQuery tabanlı uygulamalarda uzun ve tutarsız isimler nedeniyle kazanç daha belirgin olur. Aynı seçeneğin iki projede bu kadar farklı davranmasının sebebi budur.

Bu yüzden karar verirken sadece toplam bundle boyutuna değil, kritik giriş paketine de bakmak gerekir. Uygulamanın tamamı 400 KB olabilir ama ilk ekranda yalnızca 90 KB taşınıyorsa, mangle’ın kullanıcıya hissettirdiği fark daha sınırlı kalır. Tersine, ilk etkileşimden önce 250 KB JavaScript parse edilen bir projede 10-12 KB’lık net küçülme bile bekleme hissini azaltabilir. Dosya boyutu tek başına değil, yükleme sırası ile birlikte okunmalıdır.

Hangi durumlarda mangle risk üretir?

İlk risk, isme göre çalışan kodlardır. eval, new Function, string üzerinden method çağrısı, HTML içinde inline handler kullanımı ve bazı eski plugin mimarileri bu gruba girer. Kodun kendisi sözdizimsel olarak bozulmaz; ama çalışma anında aranan ismi artık bulamaz. Sorun bu yüzden geç fark edilir. Derleme başarılıdır, sayfa açılır, fakat belirli etkileşimlerde sessiz hata çıkar.

İkinci risk hata ayıklama tarafındadır. Stack trace içinde paymentValidationStep görmek ile a görmek aynı şey değildir. Üretim hatalarında tanı koymak zorlaşır. Source map kullanıyorsanız bu sorun yönetilebilir. Kullanmıyorsanız ya da hata raporlama altyapınız bunu toplamıyorsa, ekipteki herkes bir noktada hangi fonksiyonun patladığını bulmak için daha fazla zaman harcar.

Üçüncü risk framework dışı entegrasyonlardır. Bazı CMS eklentileri, A/B test kodları, reklam etiketleri veya gömülü widget’lar global isim arar. Siz o ismi bundler içinde güvenli sanıp kısaltırsınız, dış script ise artık karşısında beklediği nesneyi bulamaz. Bu nedenle mangle kararı yalnızca uygulama koduna bakılarak verilmez; sayfaya sonradan enjekte edilen script’ler de denkleme girer.

Framework kullanan projelerde bile bu risk bitmez. React, Vue ya da Svelte tarafında çoğu bileşen yerel scope içinde güvenli görünür; ama hydration sınırında, üçüncü parti ölçüm kodlarında ve hata raporlama eklentilerinde isimlerin dışarı sızdığı noktalar olabilir. Özellikle function.name üzerinden davranış kuran eski yardımcı paketler ya da class adına bakarak otomasyon yapan test katmanları mangle sonrası beklenmedik sonuç üretebilir.

Dördüncü risk, mangle’ı güvenlik çözümü sanmaktır. Kodu biraz daha okunmaz hale getirir, evet. Fakat bu gerçek koruma değildir. Tarayıcı kodu yine indirir, çalıştırır ve isteyen kişi yine çözümleyebilir. Eğer amaç fikri mülkiyeti saklamaksa daha ağır teknikler gerekir; ama onların da bakım ve performans maliyeti yüksektir. Mangle burada güvenlik değil optimizasyon seçeneği olarak görülmelidir.

Güvenli kullanım için karar sırası nasıl kurulmalı?

En sağlıklı sıra, mangle’ı en sona koymaktır. Önce minify ve compress ile ne kazandığınıza bakın. Ölü kod temizliği, drop_console, modül bölme ve gereksiz bağımlılık azaltma çoğu zaman daha büyük etki üretir. Bunlar temizlenmeden mangle açmak, yanlış yerde hassas ayar yapmak gibidir.

  1. Önce minify ve compress ile temel çıktıyı alın.
  2. Bundle boyutunu ham ve gzip olarak ayrı ölçün.
  3. Smoke test ve kritik kullanıcı akışlarını staging ortamında çalıştırın.
  4. Mangle’ı açıp farkı yeniden ölçün.
  5. Public API, global isim ve hata ayıklama gereksinimlerine göre kalıcı kararı verin.

Bu noktada ağ tarafını da unutmayın. Mangle, gzip ya da cache başlıklarının yerine geçmez. Hatta çoğu zaman onun etkisi ancak teslimat katmanı düzgün kurulduğunda anlam kazanır. Çünkü JavaScript dosyanızı 15 KB küçültüp sunucuda sıkıştırma kapalı bırakmak iyi takas değildir. Eğer bu katmanları birlikte düzenlemek istiyorsanız Gzip ve cache başlıklarını sunucu tarafında doğru kurmak daha bütünlüklü sonuç verir.

Bu sitedeki Minify aracında JavaScript tarafında dört ana seçenek bulunuyor: mangle, gelişmiş sıkıştırma, ölü kod temizliği ve console kaldırma. Böyle bir arayüzün faydası tam da burada ortaya çıkar. Tek tek açıp kapatarak hangi seçenek grubunun gerçekten fark yarattığını görebilirsiniz. Bazı dosyalarda mangle yerine drop_console daha büyük kazanç verir. Bazılarında tam tersi olur.

Bir ayrıntı daha var: property mangling bu arayüzde özellikle yok. Bu, eksiklik değil; güvenlik freni olarak da okunabilir. Çünkü property adlarını topluca kısaltmak, değişken kısaltmaktan çok daha risklidir. API yanıtı, event adı, DOM dataset anahtarı ya da üçüncü parti entegrasyon tarafından tüketilen alanlar bir anda kırılabilir. Çoğu ekip için ilk etapta ihtiyaç duyulan şey zaten bu kadar ileri seviye agresiflik değildir.

İyi ekiplerde bu karar CI hattına da taşınır. Mangle kapalı ve açık çıktılar ayrı ayrı üretilebilir, smoke testler her iki paket üzerinde koşabilir ve bundle analyzer raporu değişim yüzdesini doğrudan gösterebilir. Böyle kurulan süreçlerde “açalım mı, kapatalım mı?” tartışması sezgiyle değil ölçümle yönetilir. Özellikle çok geliştiricili projelerde bu disiplin, tek bir optimizasyon ayarının aylar sonra görünür hale gelen regressions üretmesini engeller.

Debug sürecinde mangle ile nasıl baş edilir?

Mangle açıldıktan sonra üretim dosyasını çıplak gözle okumak keyifli değildir. Tek satır, tek harfe inmiş değişkenler ve sıkışık akış yüzünden nerede olduğunuzu kolay kaybedersiniz. Bu yüzden beautify düğmesi ile geri dönüş aynı şey değildir. Beautify sadece biçimi açar. a, b, c olarak kalan isimleri eski haline getirmez.

Gerçek çözüm source map’tir. Tarayıcı geliştirici araçları minify edilmiş dosya ile kaynak kod arasında eşleme kurar. Böylece hata ayıklarken tekrar anlamlı dosya ve satır numaraları görürsünüz. Yine de bu dosyaları körlemesine herkese açık bırakmak iyi fikir değildir. Kaynak yapınızı ifşa edebilir. Bu yüzden birçok ekip source map’i sadece staging ortamında ya da kimlik doğrulamalı hata izleme servisinde tutar.

Burada küçük bir pratik kural işe yarar: mangle açtıktan sonra yalnızca hata olup olmadığına bakmayın, stack trace okunabilirliği ve gözlemleme kalitesini de test edin. Hata çözme süresi uzuyorsa, kazandığınız birkaç kilobayt beklediğiniz kadar değerli olmayabilir.

Bazı ekipler burada iki katmanlı yaklaşım kullanır. Production çıktısında mangle açık kalır, source map dosyası ise sadece hata izleme servisine yüklenir. Tarayıcıdan doğrudan erişilemez ama Sentry benzeri bir sistem stack trace’i çözebilir. Eğer böyle bir akışınız yoksa, staging’de mangle açık test yapmak ve production’da daha muhafazakar kalmak çoğu zaman daha düşük riskli çözümdür.

Mangle çoğu projede ilk bakılacak düğme değil, ölçüm sonrası açılan optimizasyon katmanıdır. İç uygulama kodunda ve güvenli scope sınırlarında fayda sağlayabilir; public API yüzeyi, string tabanlı bağımlılıklar ve zor debug edilen yapılarda ise daha kontrollü uygulanmalıdır. Doğru karar ancak boyut farkı, parse etkisi, test sonucu ve hata ayıklama maliyeti birlikte okununca verilir.