Müşteri tarafı kodunuzu birleştirip küçülttükten sonra bile performansı etkilemeden okunabilir ve daha da önemlisi hata ayıklama yapılabilir durumda tutmayı hiç dilediniz mi? Artık kaynak haritalar sayesinde bunu yapabilirsiniz.
Kaynak eşlemeleri, birleştirilmiş/küçültülmüş bir dosyayı derlenmemiş bir duruma geri eşlemenin bir yoludur. Üretim için derleme yaptığınızda, JavaScript dosyalarınızı küçültüp birleştirmenin yanı sıra orijinal dosyalarınızla ilgili bilgileri içeren bir kaynak haritası oluşturursunuz. Oluşturulan JavaScript'inizde belirli bir satır ve sütun numarasını sorgularken kaynak haritada orijinal konumu döndüren bir arama yapabilirsiniz. Geliştirici araçları (şu anda WebKit gecelik derlemeleri, Google Chrome veya Firefox 23 ve sonraki sürümler), kaynak haritayı otomatik olarak ayrıştırabilir ve sıkıştırılmamış ve birleştirilmemiş dosyalar çalıştırdığınızı gösterebilir.
Demo, oluşturulan kaynağı içeren metin alanında herhangi bir yeri sağ tıklamanıza olanak tanır. "Orijinal konumu al"ı seçtiğinizde, oluşturulan satır ve sütun numarasını ileterek kaynak haritayı sorgulanır ve orijinal koddaki konum döndürülür. Çıktıyı görebilmeniz için konsolunuzun açık olduğundan emin olun.
Gerçek hayat
Kaynak haritalarının gerçek dünyadaki uygulamasını görüntülemeden önce, geliştirici araçları panelindeki ayarlar dişli çarkı simgesini tıklayıp "Kaynak haritalarını etkinleştir " seçeneğini işaretleyerek Chrome Canary veya WebKit nightly'de kaynak haritaları özelliğini etkinleştirdiğinizden emin olun.
Firefox 23 ve sonraki sürümlerde, yerleşik geliştirici araçlarında kaynak haritalar varsayılan olarak etkindir.
Kaynak haritalarını neden kullanmalıyım?
Şu anda kaynak eşleme yalnızca sıkıştırılmamış/birleştirilmiş JavaScript ile sıkıştırılmış/birleştirilmemiş JavaScript arasında çalışıyor ancak CoffeeScript gibi JavaScript'e derlenmiş diller ve hatta SASS veya LESS gibi CSS önişleyiciler için destek ekleme olasılığıyla gelecek parlak görünüyor.
Gelecekte, kaynak haritalarla neredeyse tüm dilleri tarayıcıda yerel olarak desteklenirmiş gibi kolayca kullanabileceğiz:
- CoffeeScript
- ECMAScript 6 ve sonraki sürümler
- SASS/LESS ve diğerleri
- JavaScript'e derlenen hemen hemen tüm diller
Firefox konsolunun deneysel bir sürümünde CoffeeScript'te hata ayıklama işleminin yapıldığı bu ekran video kaydına göz atın:
Google Web Toolkit'e (GWT) kısa süre önce kaynak eşlemeleri desteği eklendi. GWT ekibinden Ray Cromwell, kaynak harita desteğini çalışırken gösteren harika bir ekran kaydı hazırladı.
Hazırladığım bir diğer örnekte, ES6 (ECMAScript 6 veya Next) yazıp ES3 uyumlu koda derlemenize olanak tanıyan Google'ın Traceur kitaplığı kullanılmaktadır. Traceur derleyicisi de bir kaynak haritası oluşturur. Kaynak haritası sayesinde ES6 özelliklerinin ve sınıflarının tarayıcıda yerel olarak desteklendikleri gibi kullanıldığı bu demo'ya göz atın.
Demodaki metin alanı, anında derlenecek ve bir kaynak haritası ile eşdeğer ES3 kodu oluşturacak ES6 yazmanıza da olanak tanır.
Demo: ES6 yazma, hata ayıklama, kaynak eşlemeyi çalışırken görüntüleme
Kaynak eşlemesi nasıl çalışır?
Şu anda kaynak haritası oluşturma desteğine sahip olan tek JavaScript derleyici/küçültücü Closure derleyicidir. (Bu özelliği nasıl kullanacağınızı daha sonra açıklayacağım.) JavaScript'inizi birleştirip küçülttükten sonra, bunun yanında bir kaynak haritası dosyası bulunur.
Şu anda Closure derleyici, tarayıcı geliştirici araçlarına kaynak haritasının mevcut olduğunu belirtmek için gereken özel yorumu sonuna eklemiyor:
//# sourceMappingURL=/path/to/file.js.map
Bu sayede geliştirici araçları, çağrıları orijinal kaynak dosyalardaki konumlarıyla eşleyebilir. Daha önce yorum pragması //@
idi ancak bu ve IE koşullu derleme yorumlarıyla ilgili bazı sorunlar nedeniyle //#
olarak değiştirilmesine karar verildi. Şu anda Chrome Canary, WebKit Nightly ve Firefox 24 ve sonraki sürümler yeni yorum pragmasını desteklemektedir. Bu söz dizimi değişikliği, sourceURL'yi de etkiler.
Tuhaf yorum fikrini beğenmiyorsanız alternatif olarak derlenmiş JavaScript dosyanızda özel bir başlık ayarlayabilirsiniz:
X-SourceMap: /path/to/file.js.map
Yorum gibi bu da kaynak eşleme tüketicinize, JavaScript dosyasıyla ilişkili kaynak eşlemeyi nerede arayacağını söyler. Bu başlık, tek satırlık yorumları desteklemeyen dillerde kaynak haritalarına referans verme sorununu da çözer.
Kaynak eşleme dosyası yalnızca kaynak eşlemelerinizi etkinleştirdiyseniz ve geliştirici araçlarınızı açık bıraktıysanız indirilir. Geliştirme araçlarının gerektiğinde bu dosyalara referans vermesi ve bunları görüntülemesi için orijinal dosyalarınızı da yüklemeniz gerekir.
Nasıl kaynak haritası oluşturabilirim?
JavaScript dosyalarınızı küçültmek, birleştirmek ve kaynak haritası oluşturmak için Closure derleyicisini kullanmanız gerekir. Komut şu şekildedir:
java -jar compiler.jar \
--js script.js \
--create_source_map ./script-min.js.map \
--source_map_format=V3 \
--js_output_file script-min.js
İki önemli komut işareti --create_source_map
ve --source_map_format
'dur. Varsayılan sürüm V2 olduğu ve yalnızca V3 ile çalışmak istediğimiz için bu gereklidir.
Bir kaynak eşlemesinin anatomisi
Kaynak haritasını daha iyi anlamak için Closure derleyicisi tarafından oluşturulacak bir kaynak haritası dosyasını küçük bir örnek olarak ele alıp "eşlemeler" bölümünün işleyiş şekliyle ilgili daha ayrıntılı bilgi vereceğiz. Aşağıdaki örnek, V3 spesifikasyonundaki örnekten biraz farklıdır.
{
version : 3,
file: "out.js",
sourceRoot : "",
sources: ["foo.js", "bar.js"],
names: ["src", "maps", "are", "fun"],
mappings: "AAgBC,SAAQ,CAAEA"
}
Yukarıda, kaynak eşlemenin çok sayıda yararlı bilgi içeren bir nesne ifadesi olduğunu görebilirsiniz:
- Kaynak eşlemesinin temel aldığı sürüm numarası
- Oluşturulan kodun dosya adı (minileştirilmiş/birleştirilmiş üretim dosyanız)
- sourceRoot, kaynaklara klasör yapısı eklemenize olanak tanır. Bu, yer tasarrufu sağlayan bir tekniktir.
- sources, birleştirilen tüm dosya adlarını içerir
- adlar, kodunuzda görünen tüm değişken/yöntem adlarını içerir.
- Son olarak, Base64 VLQ değerlerinin kullanıldığı haritalar mülkünde sihrin gerçekleştiği yerdir. Gerçek alan tasarrufu burada yapılır.
Base64 VLQ ve kaynak haritayı küçük tutma
Başlangıçta kaynak eşleme spesifikasyonu, tüm eşlemelerin çok ayrıntılı bir çıktısına sahipti ve kaynak eşlemenin, oluşturulan kodun yaklaşık 10 katı boyutunda olmasına neden oldu. İkinci sürümde bu oran yaklaşık% 50, üçüncü sürümde ise %50 daha azaltıldı. Böylece 133 KB boyutunda bir dosya için yaklaşık 300 KB boyutunda bir kaynak haritası elde edersiniz.
Peki karmaşık eşlemeleri korurken boyutu nasıl küçülttüler?
Değerin Base64 değerine kodlanmasıyla birlikte VLQ (Değişken Uzunlukta Miktar) kullanılır. Eşlemeler mülkü çok büyük bir dizedir. Bu dize, oluşturulan dosyadaki bir satır numarasını temsil eden noktalı virgüller (;) içerir. Her satırda, ilgili satırdaki her segmenti temsil eden virgüller (,) bulunur. Bu segmentlerin her biri, değişken uzunluktaki alanlarda 1, 4 veya 5'tir. Bazıları daha uzun görünebilir ancak bunlar devam bitleri içerir. Her segment önceki segmentin üzerine inşa edilir. Bu sayede her bit önceki segmentlerine göre olduğundan dosya boyutu azaltılır.
Yukarıda belirtildiği gibi, her segment değişken uzunlukta 1, 4 veya 5 olabilir. Bu diyagram, bir devam bit'i (g) içeren dört değişken uzunlukta olarak kabul edilir. Bu segmenti ayrıntılı olarak inceleyip kaynak haritanın orijinal konumu nasıl hesapladığını göstereceğiz.
Yukarıda gösterilen değerler yalnızca Base64 kodunun çözüldüğü değerlerdir. Gerçek değerlerini almak için daha fazla işlem yapılması gerekir. Her segment genellikle beş şeyi belirler:
- Oluşturulan sütun
- Bu içeriğin yer aldığı orijinal dosya
- Orijinal satır numarası
- Orijinal sütun
- Varsa orijinal ad
Her segmentin adı, yöntem adı veya bağımsız değişkeni yoktur. Bu nedenle, segmentler dört ile beş değişken uzunluğu arasında geçiş yapar. Yukarıdaki segment diyagramındaki g değeri, devam bit'i olarak adlandırılır ve Base64 VLQ kod çözme aşamasında daha fazla optimizasyon sağlar. Devam bit'i, segment değerini temel almanıza olanak tanır. Böylece, büyük bir sayı depolamak zorunda kalmadan büyük sayılar depolayabilirsiniz. Bu, kökenleri midi biçiminde olan çok akıllı bir yer tasarrufu tekniğidir.
Yukarıdaki diyagram AAgBC
daha fazla işlendikten sonra 0, 0, 32, 16, 1 değerini döndürür. 32, sonraki 16 değerini oluşturmaya yardımcı olan devam bitini temsil eder. B, Base64'te tamamen kodu çözülmüş olarak 1'dir. Dolayısıyla kullanılan önemli değerler 0, 0, 16, 1'dir. Bu, oluşturulan dosyanın 1. satırının (satırlar noktalı virgüllerle sayılır) 0. sütununun 0. dosyayla (dosya dizisi 0, foo.js'dir) 1. sütunun 16. satırıyla eşleştiğini bize bildirir.
Segmentlerin nasıl kodunun çözüldüğünü göstermek için Mozilla'nın Source Map JavaScript kitaplığına atıfta bulunacağım. JavaScript'te yazılmış WebKit geliştirici araçları kaynak eşleme koduna da bakabilirsiniz.
B'den 16 değerini nasıl aldığımızı doğru şekilde anlamak için bit operatörleri ve kaynak eşleme için spesifikasyonun işleyiş şekli hakkında temel düzeyde bilgi sahibi olmamız gerekir. Bitsel VE (&) operatörü kullanılarak hane (32) ve VLQ_CONTINUATION_BIT (ikili 100000 veya 32) karşılaştırılarak önceki hane (g) devam bit olarak işaretlenir.
32 & 32 = 32
// or
100000
|
|
V
100000
Bu, her ikisinin de göründüğü her bit konumunda 1 döndürür. Bu nedenle, yukarıdaki şemada görebileceğiniz gibi yalnızca 32 bit konumu paylaştıkları için Base64 kod çözme işlemi uygulanmış 33 & 32
değeri 32 döndürür. Bu işlem, önceki her devam biti için bit kaydırma değerini 5 artırır. Yukarıdaki durumda yalnızca bir kez 5'e kaydırılır. Yani 1 (B) 5'e sola kaydırılır.
1 <<../ 5 // 32
// Shift the bit by 5 spots
______
| |
V V
100001 = 100000 = 32
Ardından bu değer, sayı (32) bir basamak sağa kaydırılarak VLQ işaretli değerden dönüştürülür.
32 >> 1 // 16
//or
100000
|
|
V
010000 = 16
İşte bu kadar. 1'i 16'ya dönüştürme işlemini tamamladınız. Bu süreç çok karmaşık görünebilir ancak sayılar arttıkça daha mantıklı hale gelir.
Olası XSSI sorunları
Spesifikasyonda, kaynak haritanın kullanılmasından kaynaklanabilecek siteler arası komut dosyası dahil etme sorunlarından bahsedilmektedir. Bu sorunu azaltmak için kaynak haritanızın ilk satırına ")]}
" eklemeniz önerilir. Böylece JavaScript'i kasıtlı olarak geçersiz kılar ve söz dizimi hatası oluşur. WebKit geliştirici araçları bu işlemi zaten yapabilir.
if (response.slice(0, 3) === ")]}") {
response = response.substring(response.indexOf('\n'));
}
Yukarıda gösterildiği gibi, ilk üç karakter, spesifikasyondaki söz dizimi hatasıyla eşleşip eşleşmediğini kontrol etmek için dilimlenir ve eşleşirse ilk yeni satır öğesine (\n) kadarki tüm karakterler kaldırılır.
sourceURL
ve displayName
'un kullanımı: Değerlendirme ve anonim işlevler
Kaynak haritası spesifikasyonunun bir parçası olmasa da aşağıdaki iki kural, evals ve anonim işlevlerle çalışırken geliştirmeyi çok daha kolay hale getirmenize olanak tanır.
İlk yardımcı, //# sourceMappingURL
mülküne çok benzer ve aslında kaynak harita V3 spesifikasyonunda belirtilmiştir. Kodunuza aşağıdaki özel yorumu ekleyerek (bu yorum değerlendirilir) değerlendirmeleri, geliştirici araçlarınızda daha mantıklı isimler olarak görünecek şekilde adlandırabilirsiniz. CoffeeScript derleyicisini kullanan basit bir demoya göz atın:
Demo: eval()
kodunu sourceURL aracılığıyla komut dosyası olarak görme
//# sourceURL=sqrt.coffee
Diğer yardımcı, anonim işlevin mevcut bağlamında bulunan displayName
mülkünü kullanarak anonim işlevleri adlandırmanıza olanak tanır. displayName
mülkünün nasıl çalıştığını görmek için aşağıdaki demoyu profilleyin.
btns[0].addEventListener("click", function(e) {
var fn = function() {
console.log("You clicked button number: 1");
};
fn.displayName = "Anonymous function of button 1";
return fn();
}, false);
Geliştirme araçları içinde kodunuzun profilini oluştururken (anonymous)
gibi bir şey yerine displayName
mülkü gösterilir. Ancak displayName artık kullanılmıyor ve Chrome'a eklenmeyecek. Ancak tüm umutlar tükenmiş değil. debugName adlı çok daha iyi bir öneri sunuldu.
eval adlandırması, bu makalenin yazıldığı tarih itibarıyla yalnızca Firefox ve WebKit tarayıcılarında kullanılabilir. displayName
mülkü yalnızca WebKit gece sürümlerinde bulunur.
Birlikte harekete geçelim
Şu anda CoffeeScript'e kaynak eşleme desteği eklenmesi konusunda çok uzun bir tartışma sürüyor. Sorunun olduğu sayfaya gidip kaynak haritası oluşturma özelliğinin CoffeeScript derleyicisine eklenmesi için desteğinizi ekleyin. Bu, CoffeeScript ve onun sadık takipçileri için büyük bir kazanç olacak.
UglifyJS'de de göz atmanız gereken bir kaynak haritası sorunu var.
Coffeescript derleyicisi de dahil olmak üzere birçok araç kaynak haritası oluşturur. Bu konuyu artık tartışmaya açık bulmuyorum.
Kaynak haritası oluşturabileceğimiz ne kadar çok araç olursa o kadar iyi olur. Bu nedenle, en sevdiğiniz açık kaynak projesine kaynak haritası desteği ekleyin veya isteyin.
Mükemmel değil
Kaynak eşlemeleri şu anda izleme ifadeleri için destek sunmamaktadır. Sorun şudur: Geçerli yürütme bağlamında bir bağımsız değişkeni veya değişken adını incelemeye çalıştığınızda, gerçekten mevcut olmadığı için hiçbir şey döndürülmez. Bu durumda, incelemek istediğiniz bağımsız değişkenin/değişkenin gerçek adını, derlenmiş JavaScript'inizdeki gerçek bağımsız değişken/değişken adıyla karşılaştırmak için bir tür ters eşleme gerekir.
Bu elbette çözülebilir bir sorundur. Kaynak haritalara daha fazla önem vererek bazı harika özellikleri ve daha iyi kararlılığı görmeye başlayabiliriz.
Sorunlar
Yakın zamanda jQuery 1.9, resmi CDN'lerden yayınlanırken kaynak haritalar için destek ekledi. Ayrıca, jQuery yüklenmeden önce IE koşullu derleme yorumları ("//@cc_on") kullanıldığında tuhaf bir hata olduğunu da belirtti. Bu tarihten sonra, sourceMappingURL'yi çok satırlı bir yoruma sarmalayarak bu sorunu azaltmak için bir commit yapıldı. Koşullu yorum kullanmayın.
Bu sorun, söz dizimi //#
olarak değiştirilerek çözüme ulaştırıldı.
Araçlar ve kaynaklar
İncelemeniz gereken bazı diğer kaynaklar ve araçlar:
- Nick Fitzgerald, kaynak eşleme desteğine sahip bir UglifyJS çatalı oluşturdu.
- Paul Irish'ın kaynak haritaları gösteren kullanışlı bir demo'su var.
- Bu özelliğin kaldırıldığı WebKit değişiklik kaydına göz atın.
- Değişiklik grubu, bu makalenin yazılmasını sağlayan bir düzen testi de içeriyordu.
- Mozilla'da, yerleşik konsoldaki kaynak haritalarının durumunu takip etmeniz gereken bir hata var.
- Conrad Irwin, tüm Ruby kullanıcıları için son derece kullanışlı bir source map gem yazdı.
- eval adlandırma ve displayName mülkü hakkında daha fazla okuma
- Kaynak haritası oluşturmak için Closure Compilers kaynağına göz atabilirsiniz.
- Bazı ekran görüntüleri ve GWT kaynak haritaları için destekten bahsediliyor.
Kaynak haritaları, geliştiricilerin araç setinde bulunan çok güçlü bir yardımcı programdır. Web uygulamanızı basit ancak kolayca hata ayıklanabilir tutabilmek son derece faydalıdır. Ayrıca, yeni geliştiricilerin okunamayan sıkıştırılmış kodlar arasında gezinmek zorunda kalmadan deneyimli geliştiricilerin uygulamalarını nasıl yapılandırdığını ve yazdığını görmesi için çok güçlü bir öğrenme aracıdır.
Neyi bekliyorsunuz? Tüm projeler için kaynak haritalar oluşturmaya hemen başlayın.