Genel Bakış
compilation_level
ile ADVANCED_OPTIMIZATIONS
kullanarak Closure Compiler'ı kullanmak, SIMPLE_OPTIMIZATIONS
veya WHITESPACE_ONLY
ile derlemeye kıyasla daha iyi sıkıştırma oranları sunar. ADVANCED_OPTIMIZATIONS
ile derleme, kodu dönüştürme ve sembolleri yeniden adlandırma yöntemlerinde daha agresif davranarak ek sıkıştırma sağlar. Ancak bu daha agresif yaklaşım, ADVANCED_OPTIMIZATIONS
kullanırken daha dikkatli olmanız gerektiği anlamına gelir. Bu sayede çıkış kodunun giriş koduyla aynı şekilde çalıştığından emin olabilirsiniz.
Bu eğiticide, ADVANCED_OPTIMIZATIONS
derleme düzeyinin ne yaptığı ve ADVANCED_OPTIMIZATIONS
ile derleme işleminden sonra kodunuzun çalıştığından emin olmak için neler yapabileceğiniz açıklanmaktadır. Ayrıca, derleyici tarafından işlenen kodun dışında tanımlanan bir sembol olan extern kavramını da tanıtır.
Bu eğitimi okumadan önce, Java tabanlı derleyici uygulaması gibi Closure Compiler araçlarından biriyle JavaScript'i derleme sürecine aşina olmanız gerekir.
Terminolojiyle ilgili bir not: --compilation_level
komut satırı işareti, daha yaygın olarak kullanılan kısaltmalar ADVANCED
ve SIMPLE
ile daha hassas olan ADVANCED_OPTIMIZATIONS
ve SIMPLE_OPTIMIZATIONS
kısaltmalarını destekler.
Bu belgede daha uzun biçim kullanılmaktadır ancak komut satırında adlar birbirinin yerine kullanılabilir.
- Daha da İyi Sıkıştırma
- Nasıl yapılır? ADVANCED_OPTIMIZATIONS'ı etkinleştirme
- ADVANCED_OPTIMIZATIONS Kullanırken Dikkat Edilmesi Gerekenler
Even Better Compression
Closure Compiler, SIMPLE_OPTIMIZATIONS
varsayılan derleme düzeyiyle yerel değişkenleri yeniden adlandırarak JavaScript'i küçültür. Yerel değişkenler dışında kısaltılabilecek semboller ve sembolleri yeniden adlandırmak dışında kodu küçültmenin yolları vardır. ADVANCED_OPTIMIZATIONS
ile derleme, kod küçültme olanaklarının tümünden yararlanır.
Aşağıdaki kod için SIMPLE_OPTIMIZATIONS
ve ADVANCED_OPTIMIZATIONS
çıkışlarını karşılaştırın:
function unusedFunction(note) { alert(note['text']); } function displayNoteTitle(note) { alert(note['title']); } var flowerNote = {}; flowerNote['title'] = "Flowers"; displayNoteTitle(flowerNote);
SIMPLE_OPTIMIZATIONS
ile derleme, kodu şu şekilde kısaltır:
function unusedFunction(a){alert(a.text)}function displayNoteTitle(a){alert(a.title)}var flowerNote={};flowerNote.title="Flowers";displayNoteTitle(flowerNote);
ADVANCED_OPTIMIZATIONS
ile derleme, kodu tamamen kısaltarak şu hale getirir:
alert("Flowers");
Bu iki komut dosyası da "Flowers"
uyarısını verir ancak ikinci komut dosyası çok daha küçüktür.
ADVANCED_OPTIMIZATIONS
düzeyi, değişken adlarının basitçe kısaltılmasının ötesine geçerek çeşitli avantajlar sunar. Örneğin:
- daha agresif yeniden adlandırma:
Yalnızca
SIMPLE_OPTIMIZATIONS
ile derlemedisplayNoteTitle()
veunusedFunction()
işlevlerininnote
parametrelerini yeniden adlandırır. Bunun nedeni, komut dosyasındaki işlevlere yerel olan tek değişkenlerin bunlar olmasıdır.ADVANCED_OPTIMIZATIONS
, global değişkeni de yeniden adlandırırflowerNote
. - Ölü kod kaldırma:
ADVANCED_OPTIMIZATIONS
ile derleme, kodda hiçbir zaman çağrılmadığı içinunusedFunction()
işlevini tamamen kaldırır. - işlev satır içi yerleştirme:
ADVANCED_OPTIMIZATIONS
ile derleme,displayNoteTitle()
işlevine yapılan çağrıyı, işlevin gövdesini oluşturan tekalert()
ile değiştirir. Bir işlev çağrısının işlevin gövdesiyle değiştirilmesine "satır içi genişletme" adı verilir. İşlev daha uzun veya daha karmaşık olsaydı satır içi yapılması kodun davranışını değiştirebilirdi ancak Closure Compiler bu durumda satır içi yapmanın güvenli olduğunu ve yer kazandırdığını belirler. Derleme,ADVANCED_OPTIMIZATIONS
ile birlikte sabitleri ve bazı değişkenleri güvenli bir şekilde yapabileceğini belirlediğinde satır içine de yerleştirir.
Bu liste, ADVANCED_OPTIMIZATIONS
derlemesinin gerçekleştirebileceği boyut küçültme dönüşümlerinin yalnızca bir örneğidir.
ADVANCED_OPTIMIZATIONS nasıl etkinleştirilir?
Closure Compiler uygulaması için ADVANCED_OPTIMIZATIONS
özelliğini etkinleştirmek üzere komut satırı işaretini --compilation_level ADVANCED_OPTIMIZATIONS
aşağıdaki komuttaki gibi ekleyin:
java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js hello.js
ADVANCED_OPTIMIZATIONS Kullanırken Dikkat Edilmesi Gerekenler
ADVANCED_OPTIMIZATIONS ile ilgili sık karşılaşılan bazı istenmeyen etkiler ve bunları önlemek için uygulayabileceğiniz adımlar aşağıda listelenmiştir.
Saklamak istediğiniz kodun kaldırılması
Aşağıdaki işlevi yalnızca ADVANCED_OPTIMIZATIONS
ile derlerseniz Closure Compiler boş bir çıkış üretir:
function displayNoteTitle(note) { alert(note['myTitle']); }
Derleyiciye ilettiğiniz JavaScript'te işlev hiçbir zaman çağrılmadığı için Closure Compiler, bu kodun gerekli olmadığını varsayar.
Çoğu durumda bu davranış tam olarak istediğiniz şeydir. Örneğin, kodunuzu büyük bir kitaplıkla birlikte derlerseniz Closure Compiler, bu kitaplıktaki hangi işlevleri kullandığınızı belirleyebilir ve kullanmadığınız işlevleri atabilir.
Ancak Closure Compiler'ın tutmak istediğiniz işlevleri kaldırdığını fark ederseniz bunu önlemenin iki yolu vardır:
- İşlev çağrılarınızı Closure Compiler tarafından işlenen koda taşıyın.
- Dışa aktarmak istediğiniz işlevler için harici dosyaları ekleyin.
Sonraki bölümlerde her seçenek daha ayrıntılı olarak ele alınmaktadır.
Çözüm: İşlev çağrılarınızı Closure Compiler tarafından işlenen koda taşıyın
Kodunuzun yalnızca bir bölümünü Closure Compiler ile derlerseniz istenmeyen kod kaldırma işlemiyle karşılaşabilirsiniz. Örneğin, yalnızca işlev tanımlarını içeren bir kitaplık dosyanız ve kitaplığı içeren ve bu işlevleri çağıran kodu içeren bir HTML dosyanız olabilir. Bu durumda, kitaplık dosyasını ADVANCED_OPTIMIZATIONS
ile derlerseniz Closure Compiler, tüm kitaplık işlevlerinizi kaldırır.
Bu sorunun en basit çözümü, işlevlerinizi bu işlevleri çağıran programınızın bölümüyle birlikte derlemektir.
Örneğin, Closure Compiler aşağıdaki programı derlerken displayNoteTitle()
öğesini kaldırmaz:
function displayNoteTitle(note) { alert(note['myTitle']); } displayNoteTitle({'myTitle': 'Flowers'});
Bu durumda displayNoteTitle()
işlevi, Closure Compiler tarafından çağrıldığı görüldüğü için kaldırılmaz.
Başka bir deyişle, programınızın giriş noktasını Closure Compiler'a ilettiğiniz koda ekleyerek istenmeyen kod kaldırma işlemini önleyebilirsiniz. Bir programın giriş noktası, programın yürütülmeye başladığı kod bölümüdür. Örneğin, önceki bölümdeki çiçek notu programında son üç satır, JavaScript tarayıcıya yüklendiği anda yürütülür. Bu programın giriş noktasıdır. Hangi kodu saklamanız gerektiğini belirlemek için Closure Compiler bu giriş noktasından başlar ve programın kontrol akışını buradan itibaren ileriye doğru izler.
Çözüm: Kullanıma sunmak istediğiniz işlevler için Externs'i dahil edin
Bu çözüm hakkında daha fazla bilgiyi aşağıda ve stajyerler ve dışa aktarmalar sayfasında bulabilirsiniz.
Tutarsız Tesis Adları
Closure Compiler derlemesi, hangi derleme düzeyini kullanırsanız kullanın kodunuzdaki dize değişmezlerini asla değiştirmez. Bu, ADVANCED_OPTIMIZATIONS
ile derlemenin, kodunuzun özelliklere dizeyle erişip erişmediğine bağlı olarak özellikleri farklı şekilde ele aldığı anlamına gelir. Bir mülke yönelik dize referanslarını nokta söz dizimi referanslarıyla karıştırırsanız Closure Compiler, bu mülke yönelik referansların bazılarını yeniden adlandırır ancak diğerlerini yeniden adlandırmaz. Bu nedenle, kodunuz büyük olasılıkla doğru şekilde çalışmayacaktır.
Örneğin, aşağıdaki kodu ele alalım:
function displayNoteTitle(note) { alert(note['myTitle']); } var flowerNote = {}; flowerNote.myTitle = 'Flowers'; alert(flowerNote.myTitle); displayNoteTitle(flowerNote);
Bu kaynak kodundaki son iki ifade tam olarak aynı şeyi yapar. Ancak kodu ADVANCED_OPTIMIZATIONS
ile sıkıştırdığınızda şu sonuç elde edilir:
var a={};a.a="Flowers";alert(a.a);alert(a.myTitle);
Sıkıştırılmış koddaki son ifade hata veriyor. myTitle
özelliğine doğrudan referans a
olarak yeniden adlandırıldı ancak displayNoteTitle
işlevi içindeki myTitle
özelliğine yapılan alıntılanmış referans yeniden adlandırılmadı. Bu nedenle, son ifade artık mevcut olmayan bir myTitle
mülküne atıfta bulunuyor.
Çözüm: Mülk Adlarınızda Tutarlı Olun
Bu çözüm oldukça basittir. Belirli bir tür veya nesne için yalnızca nokta söz dizimini ya da tırnak içine alınmış dizeleri kullanın. Söz dizimlerini karıştırmayın. Özellikle aynı özelliklere referans verirken bu kurala uyun.
Ayrıca, mümkün olduğunda nokta söz dizimini kullanmayı tercih edin. Bu söz dizimi, daha iyi kontrolleri ve optimizasyonları destekler. Alıntılanmış dize özelliği erişimini yalnızca Closure Compiler'ın yeniden adlandırma yapmasını istemediğiniz durumlarda kullanın. Örneğin, adın kod çözümü yapılmış JSON gibi harici bir kaynaktan geldiği durumlarda bu yöntemi kullanabilirsiniz.
İki kod bölümünü ayrı ayrı derleme
Uygulamanızı farklı kod parçalarına bölerseniz parçaları ayrı ayrı derlemek isteyebilirsiniz. Ancak iki kod parçası etkileşime giriyorsa bu durum zorluklara neden olabilir. Başarılı olsanız bile iki Closure Compiler çalıştırmasının çıktısı uyumlu olmaz.
Örneğin, bir uygulamanın iki bölüme ayrıldığını varsayalım: verileri alan bir bölüm ve verileri görüntüleyen bir bölüm.
Verileri almak için kullanılan kod aşağıda verilmiştir:
function getData() { // In an actual project, this data would be retrieved from the server. return {title: 'Flower Care', text: 'Flowers need water.'}; }
Verileri görüntülemek için kullanılan kod aşağıda verilmiştir:
var displayElement = document.getElementById('display'); function displayData(parent, data) { var textElement = document.createTextNode(data.text); parent.appendChild(textElement); } displayData(displayElement, getData());
Bu iki kod parçasını ayrı ayrı derlemeye çalışırsanız çeşitli sorunlarla karşılaşırsınız. Öncelikle Closure Compiler, getData()
işlevini Removal of Code You Want to Keep (Tutmak İstediğiniz Kodun Kaldırılması) bölümünde açıklanan nedenlerle kaldırır. İkincisi, Closure Compiler, verileri görüntüleyen kodu işlerken ölümcül bir hata üretiyor.
input:6: ERROR - variable getData is undefined displayData(displayElement, getData());
Derleyici, verileri gösteren kodu derlerken getData()
işlevine erişemediği için getData
öğesini tanımlanmamış olarak değerlendirir.
Çözüm: Bir Sayfadaki Tüm Kodları Birlikte Derleyin
Doğru derleme için bir sayfanın tüm kodunu tek bir derleme çalıştırmasında birlikte derleyin. Closure Compiler, giriş olarak birden fazla JavaScript dosyası ve JavaScript dizesi kabul edebilir. Bu nedenle, kitaplık kodunu ve diğer kodları tek bir derleme isteğinde birlikte iletebilirsiniz.
Not: Derlenmiş ve derlenmemiş kodu karıştırmanız gerekiyorsa bu yaklaşım işe yaramaz. Bu durumu ele alma hakkında ipuçları için Derlenmiş ve Derlenmemiş Kod Arasındaki Bozuk Referanslar bölümüne bakın.
Derlenmiş ve Derlenmemiş Kod Arasındaki Bozuk Referanslar
ADVANCED_OPTIMIZATIONS
içinde sembol yeniden adlandırma, Closure Compiler tarafından işlenen kod ile diğer tüm kodlar arasındaki iletişimi bozar. Derleme, kaynak kodunuzda tanımlanan işlevleri yeniden adlandırır. İşlevlerinizi çağıran tüm harici kodlar, derleme işleminden sonra bozulur. Bunun nedeni, bu kodların hâlâ eski işlev adına başvurmasıdır. Benzer şekilde, derlenmiş koddaki harici olarak tanımlanmış sembollere yapılan referanslar da Closure Compiler tarafından değiştirilebilir.
"Derlenmemiş kod"un, eval()
işlevine dize olarak iletilen tüm kodları içerdiğini unutmayın. Closure Compiler, kodda dize değişmezlerini asla değiştirmez. Bu nedenle, Closure Compiler, eval()
ifadelerine iletilen dizeleri değiştirmez.
Bunların ilişkili ancak farklı sorunlar olduğunu unutmayın: derlenmişten hariciye iletişimi sürdürme ve hariciden derlenmişe iletişimi sürdürme. Bu ayrı sorunların ortak bir çözümü vardır ancak her iki tarafta da nüanslar bulunur. Closure Compiler'dan en iyi şekilde yararlanmak için hangi duruma sahip olduğunuzu anlamanız önemlidir.
Devam etmeden önce externs ve exports hakkında bilgi edinmeniz faydalı olabilir.
Derlenmiş koddan harici koda yapılan aramalarla ilgili çözüm: Extern'lerle derleme
Sayfanıza başka bir komut dosyası tarafından sağlanan kodu kullanıyorsanız Closure Compiler'ın, harici kitaplıkta tanımlanan sembollere yaptığınız referansların adını değiştirmediğinden emin olmanız gerekir. Bunun için, harici kitaplığın extern'lerini içeren bir dosyayı derlemenize ekleyin. Bu, Closure Compiler'a hangi adları kontrol etmediğinizi ve bu nedenle değiştirilemeyeceğini bildirir. Kodunuz, harici dosyanın kullandığı adları kullanmalıdır.
Bunun yaygın örnekleri arasında OpenSocial API ve Google Haritalar API'si gibi API'ler yer alır. Örneğin, kodunuz uygun harici dosyalar olmadan OpenSocial işlevi opensocial.newDataRequest()
'yı çağırırsa Closure Compiler bu çağrıyı a.b()
'ya dönüştürür.
Derlenmiş koddan harici koda yapılan çağrılarla ilgili çözüm: Externs'i uygulama
Kitaplık olarak yeniden kullandığınız JavaScript kodunuz varsa derlenmemiş kodun kitaplıktaki işlevleri çağırmasına izin verirken yalnızca kitaplığı küçültmek için Closure Compiler'ı kullanmak isteyebilirsiniz.
Bu durumda çözüm, kitaplığınızın herkese açık API'sini tanımlayan bir dizi harici değişken uygulamaktır. Kodunuz, bu harici dosyalarda tanımlanan semboller için tanımlar sağlar. Bu, stajyerlerinizin bahsettiği tüm sınıflar veya işlevler anlamına gelir. Bu, sınıflarınızın, externs'te belirtilen arayüzleri uygulaması anlamına da gelebilir.
Bu harici işlevler yalnızca sizin için değil, diğer kullanıcılar için de yararlıdır. Kitaplığınız, kullanıcıların bakış açısına göre harici bir komut dosyası olduğundan, kitaplığınızın tüketicileri kodlarını derlerken bu dosyaları eklemelidir. Harici kullanıcıları, sizinle tüketicileriniz arasındaki sözleşme olarak düşünün. Her ikinizin de bir kopyaya ihtiyacı var.
Bu nedenle, kodunuzu derlerken derlemeye extern'leri de eklediğinizden emin olun. Harici değişkenleri genellikle "başka bir yerden gelen" değişkenler olarak düşündüğümüz için bu durum alışılmadık görünebilir. Ancak Closure Compiler'a hangi sembolleri kullanıma sunduğunuzu söylemeniz gerekir. Böylece bu semboller yeniden adlandırılmaz.
Burada önemli bir uyarı, harici sembolleri tanımlayan kodla ilgili "yinelenen tanım" teşhisleri alabileceğinizdir. Closure Compiler, extern'lerdeki tüm sembollerin harici bir kitaplık tarafından sağlandığını varsayar ve şu anda tanımı kasıtlı olarak sağladığınızı anlayamaz. Bu teşhisler gizlenebilir ve gizleme işlemini, API'nizi gerçekten yerine getirdiğinizin onayı olarak düşünebilirsiniz.
Ayrıca Closure Compiler, tanımlarınızın harici bildirimlerin türleriyle eşleşip eşleşmediğini tür denetimiyle kontrol edebilir. Bu, tanımlarınızın doğru olduğuna dair ek onay sağlar.