ASP.NET 4.5 ile yeni gelen özelliklerden biri olan Bundling and Minification temelde sunucuya gelen bir talebe (request), talep sayısını ve boyutunu düşürerek performans kazandırmayı amaçlayan bir özellik. Bu yazımda ASP.NET 4.5 ile gelen bu yeni özelliği ASP.NET MVC 4 ile incelemeye çalışacağım.
Bundling ve Minification'dan Önce
Bundling ve Minification öncesinde bir çok projemizde stil ve script dosyalarımızı sayfalarımıza aşağıdaki gibi tek tek tanımlardık :
<script src="~/Scripts/SiteScripts/LargeJSFile.js" type="text/javascript"></script>
<script src="~/Scripts/SiteScripts/SmallJSFile.js" type="text/javascript"></script>
<script src="~/Scripts/SiteScripts/Z_HighPriorityScript.js" type="text/javascript"></script>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
Yukarıdaki script ve stil dosyalarını referans eden bir sayfaya istemciden gelen bir talep dört yeni talep daha yaparak her bir dosyayı da sunucudan talep eder (tabii eğer dosyalar cachelenmedi ise). Sayfamızda bulunan resim, video veya animasyon dosyaları gibi harici dosyaların da ayrı birer talep olarak sunucuya geldiği de düşünülürse bir web sayfası içerisinde kaç dosyaya referans veriyor ise sunucuya her biri için birer talep gidiyor demektir. Bu da web sayfalarımızın yüklenme zamanı performansını etkileyen kriterlerden biridir.
Yukarıdaki kod örneğindeki sayfamızı Google Chrome Developer Tools ile izler isek yukarıdaki gibi bir manzara ile karşılaşırız. Sayfamız ilk satırda yükleniyor, sonrasında stil ve script dosyaları (turuncu ve yeşil renkli) sunucudan talep ediliyor.
Bundlelar
ASP.NET MVC 4 template projesini açtığınızda bu projede bundle'ların kullanıldığını farkedeceksiniz. Aşağıdaki gibi App_Start dizini altındaki BundleConfig sınıfına gözatarsak projede kullanılan script ve stil bundlelarının bu sınıf içerisinde tanımlandığını görürüz. Global.asax.cs sınıfına da gözatarsak eğer Application_Start olayında App_Start dizinindeki tüm config sınıflarının metodları çağrılarak web uygulamamızın ayarlarının yapıldığını görebiliriz. Eğer ASP.NET MVC 3 veya daha önceki versiyondan upgrade ettiğiniz bir web MVC uygulaması üzerinde çalışıyorsanız NuGet ile Microsoft.AspNet.Web.Optimization paketini almayı unutmayın.
StyleBundle ve ScriptBundle sınıflarını kullanıp yaratacağımız yeni bundleları BundleCollection'a ekleyerek uygulamamız içerisinde kullanacağımız yeni bundleları tanımlayabiliriz.
bundles.Add(new ScriptBundle("~/bundles/SiteScripts")
.Include("~/Scripts/SiteScripts/*.js"));
Yukarıdaki örnekte joker karakterler (* wildcard karakteri) ile Scripts/SiteScripts dizini altındaki tüm javascript dosyalarını yeni tanımladığım bundle'a dahil ediyorum. Burada ufak bir kısıtımız var, joker karakterleri, dizindeki tüm dosyaları kapsayacak şekilde tanımlamama izin verilmiyor. Yani "Scripts/SiteScripts/*" şeklinde bir tanım çalışma zamanında aşağıdaki hata ile engelleniyor :
Yukarıdaki yarattığımız bundle'ı aşağıdaki gibi View'larımızda kullanabiliriz :
@Scripts.Render("~/bundles/SiteScripts")
@Styles.Render("~/Content/css")
Bu durumda sunucudan talep ettiğimiz sayfamızın kaynak koduna gözatarsak eğer aşağıdaki gibi bundle'ımızı tanımladığımız dizindeki script dosyalarının alfabetik olarak sıralı biçimde sayfamıza eklendiğini görebiliriz :
Hiyerarşik yapıda bir script veya stil dizinimiz var ve bunu bundle haline getirmek istiyorsak IncludeDirectory metodu daha çok işimize yarayacaktır. Metod bize aşağıdaki gibi alt dizinleri de yönetebileceğimiz bir esneklik sağlıyor :
bool includeSubDirectories = true;
bundles.Add(new ScriptBundle("~/bundles/SiteScripts").IncludeDirectory(
"~/Scripts/SiteScripts", "*.js", includeSubDirectories));
Minification
Şimdiye kadar yaptığımız bundle örneklernini tek dosya halinde toplayıp içerisindeki gereksiz satırları (yorum satırları, boşluklar, yeni satırlar, vb. ) atıp, değişken isimlerini kısaltıp yani script veya stil dosyamızı optimize edip istemciye gönderilecek dosya boyutunu ve talep sayısını azaltan sihir aşağıdaki gibi EnableOptimization propertisi ile sağlanıyor :
// BundleConfig.cs içerisine eklenecek.
BundleTable.EnableOptimizations = true;
Minification'ı aktif hale getiren yukarıdaki satırı eklediğimiz zaman aşağıdaki gibi bir sonuç ile karşılaşıyoruz :
Görüldüğü üzere üç script dosyası tek dosya halinde ve optimize edilmiş olarak 'SiteScripts?v=xyz-xyz-xyz' gibi bir dosya şeklinde istemciye gönderiliyor. Burada dikkat etmemiz gerene bir diğer nokta dosya isminin sonundaki v parametresi. Versiyon amaçlı kullanılan v parametresi sayesinde optimize ettiğimiz script dosyalarımız 1 sene boyunca istemcide cachelenmiş oluyor. Bu zaman zarfında eğer script dosyalarımız değişir ise yeni bir versiyon numarası otomatik olarak verilerek yeni bir dosya oluşturulup, istemcinin bu yeni dosyayı kullanması sağlanıyor.
Toplam boyutu 160KB olan ve 3 script dosyasından oluşan örneğimin 89KB'a ve tek dosyaya indirmemi sağlayan Bundling and Minification özelliği performans açısından getirdiği artıların yanı sıra uygulamamızda kullandığımız script ve stil dosyalarını derleyip toparlayıp ve daha okunabilir bir kod sağlıyor.
Güncelleme
16 Şubat 2014
Eğer ASP.NET MVC 3 veya daha önceki versiyondan upgrade ettiğiniz bir web ASP.NET MVC uygulaması üzerinde çalışıyorsanız NuGet ile Microsoft.AspNet.Web.Optimization paketini almayı unutmayın. Bu sayede System.Web.Optimization isim alanına ve yazımda bahsettiğim bundling sınıflarına erişebilirsiniz.