Modern Web Uygulaması Gelistirme

Modern web uygulaması geliştirme denildiğinde, hemen hemen herkes artık javascript’ten bahsedildiğinin farkında. Benimde değinmek istediğim kısım burası zaten. JavaScript o kadar hızlı değişen bir teknoloji ki artık tamamen kendine has development ortamı ve ideleri bulunuyor. Bu yazıda da ben bu development ortamının nasıl olduğuna ve hangi araçların kullanıldığına değineceğim.

Eskiden Nasıldı?

Örğencilik yıllarından beri server tarafında kod yazan biri oldum. Genellikle servis tabanlı mimariler ile iş yapan şirketlerde çalıştım. Bu şirketlerde hemen hemen hep Enterprise diye tabir ettiğimiz kurumsal uygulamalar geliştirirdi. Bu sebepten olsa gerek client tarafında hep Java Frameworkleri kullandım. Bu Framework yer yer Apache Wicket oldu yer yer ise JSF oldu. JavaScript tarafına mecbur kaldıkça değimdim, Ajax ile bazı özel işler yapmam gerektiğinde ya da bazı özel durumları JavaScript ile kotarmam gerektiğinde javascript kullandım. Kullandığımda okadar yüklü bir javascript olmadı. Bazen istediğim bazı bileşenleri frameworkler desteklemiyor diye Jquery kullanırdım. Bazende sitenin uyumluluğunu arttırmak için Bootstrap ya da Foundation, artık tasarım hangisine daha uyumluysa onu, kullanırdım. Onları da ya internetten indirip projeye dahil ederdim ya da Google CDN adresi üzerinden tanımlardım, artık duruma göre. Böyle javascript dosyalarını minified edeyim, Less ya da SaaS üzerinde yazayım CSS’imi gibi ihtiyaçlarım hiç olmadı. Ya da aslında oldu ama ben farkına varmadım.

Simdi Nasıl Olmalı?

Her ne kadar JavaScript kütüphanelerini hakkını vererek kullanmasamda uzun zamandır developmentın nasıl yapıldığını elimden geldiğince takip ediyorum. Kimler hangi kütüphaneleri kullanıyor, hangi kütüphaneler nelere çözüm getiriyor fırsat buldukça inceliyorum. Bildiğiniz üzere, uzun zamandır webde client tarafı sadece JavaScript, CSS ve HTML başka bir şeye ihtiyaç olmuyor. JavaScript’te sizinde bildiğiniz gibi tek başına kullanılmıyor. AngularJS olsun Backbone olsun Ember olsun bir çok kütüphane var. yeoman-grunt-bower

Sizde takdir edersiniz ki eskiden geliştirdiğim gibi bir AngularJS uygulaması geliştirmeye kalksam altından kalkamam. Nasıl minified edeceğimden nasıl projeye ekleyeceğime tutun, uygulamam güncellendiğinde browser cache’ini nasıl temizlemem gerektiğine kadar bir çok konu var. Hele CoffeeScript ya da TypeScript gibi JavaScript’e derlenen diller kullanmaya kalksam hiç altından kalkamam. Bunu farkedince araştırma yapmaya başladım. Development ortamının nasıl olması geretiğiyle ilgili. Bu araştırmam da aşağıdaki sorulara cevap bulmayı umuyordum. Sorular ağırlıklı olarak, Java’da nasıl yapılması gerektiğini bildiğim şeyleri JavaScript ortamında nasıl yapacağıma yönelik oluyor.

  • Proje yapısı nasıl olmalı? Java’da Maven ya da Gradle kullandığınızda size IDE bağımsız bir yapı sağlıyor. Bunun JavaScript karşılığı nedir? Ortak, herkesin üzerinde anlaştığı bir proje yapısı olmalı.
  • Sahi Maven’ın JavaScript karşılığı ne ki?
  • JavaScript’te build nasıl alınır? Build’ten kastım, CofeeScript ya da TypeScript kullanacak olursam (hani kullanmam ama) nasıl JavaScript kodu üretirim ya da JavaScript kodunu nasıl minified ederim? Amacım production için kod üretmek. Jquery mesela, biz tek bir dosya olarak kullanıyoruz ama tek bir dosya olarak üretilmiyor (yani umarım) olmalı.
  • JavaScript’ta bağımlılıklarımı nasıl yönetirim? Bootstrap ekleyeceğim mesela projeme, AngularJS ekleyeceğim nasıl eklerim? Kaynak kod repository’mde bunlar olsun istemem, herkes kendi kütüphanesini kendi indirsin. Bir de versiyonu falan arttırıcam, tek bir yerden arttırabilmem lazım.
  • JavaScript’te UnitTest ya da E2E test nasıl çalıştırırım? Yine Jquery’i düşünün, build öncesi bazı test koşuyor olmsı lazım. Elle, manuel koşmuyorlardır ya illa ki bir toolu bişeyi vardır.
  • JavaScript iyi hoş yazıyoruz da bunun bir standartı bir Coding Convention ya da Naming Convention’ı yok mu? “;” koysam da oluyor koymasam da, bence konulmalı ama dilin standartı ne diyor. Ben Java’cı gibi JavaScript yazmak istemiyorum, JavaScript’çi gibi JavaScript yazmak istiyorum.

Peki ben bu sorulara nerelerden geldim? AngularJS örğeniyorum kendi kendime. Yani motivasyonum “AngularJS”. Bu sebepten vereceğim örnekler angularjs ile ilgili olacaktır.

[highlight1 variation=”steelblue”]tl;dr; $ npm install -g yo grunt-cli bower generator-angular && yo angular[/highlight1]

Development Ortamı

JavaScript denildiğinde akla aynı zamanda NodeJS geliyor artık. NodeJS bildiğiniz üzere sunucu tarafında JavaScript kodu çalıştırmaya yarıyor. Bildiğiniz gibi daha önce bir kaç yazımda nedir ne değildir, dilim döndüğünce anlatmaya çalıştım. Fakat benim düşüncem, NodeJS’in asıl başarısı sunucu tarafında JavaScript çalıştırması değil, bize JavaScript için development ortamı sağlamasıdır.

NodeJS’in hızla yayılmasıyla NodeJS üzerinde çalışacak bir çok JavaScript toolu geliştirildi. Bizde zaten modern web uygulamalarımızı geliştirirken bu toolları kullanacağız. Özetle Development ortamımız tamamen NodeJS olacak. Eğer NodeJS yüklü değilse, bu adresten sisteminize uyumlu olanı yükleyebilirsiniz.

NodeJS’i yüklediğinizde 2 temel komut elde edeceksiniz.

  • node: sunucu tarafında JavaScript dosyalarınızı kullanmanıza olanak sağlayan komut satırı aracı. Bu yazı boyunca çok işimize yaramayacak.
  • npm: Node.js sistemine yeni araçlar yüklemek için kullanacağız. npm, araçları isterseniz proje bazlı isterseniz global olarak yükleyebiliyor. Projenizde package.json dosyası varsa neleri yükleyeceğini buradan okuyarak yükleme yapabiliyor. Bu sayede tüm development ortamlarınız senkron oluyor. Benzer ürünler, mac sisteminde homebrew ya da Linux sisteminde sudo olarak verilebilir. Maven ile benzerlik gösteriyor ama tam olarak maven’ın yaptığını yapmıyor. Burada kullandığımız araçlar sisteme yükleniyor, development için gerekli, eğer client side uygulaması geliştiriyorsanız production’da gerekli değil. Bu yazı boyunca bol bol kullanacağız.

Proje Yapısı ve Yeoman

Proje yapısı ilk başta biraz karışık gelebilir ama alıştığınızda tüm JavaScript projelerinin bu mantıkta olduğunu göreceksiniz. Yine de Maven ve Gradle gibi uyumlu bir startdart beklemeyin. Hala projeden projeye değişiyor. Peki Yeoman’ın bunla ilişkisi nedir? Yemoman’ı proje hazırlayıcısı olarak düşünebilirsiniz. Hani Maven’da archetype mantığı var ya, sadece archetype mantığı için bir araç geliştirmişler. Bu araçta Yeoman.yeoman
Yeoman’ı sistem genelinde yüklemek için aşağıdaki komutu çalıştırmanız gerekiyor.

  • $ npm install -g yo

Şimdi Yeoman aracımızı yükledik. Sıra da ise ne tür bir uygulama geliştireceksek ona ait üreticiyi (generator) yüklemek gerekiyor. Peki hangi üreticiyi yüklemeniz gerektiğini nasıl bileceksiniz? Nasıl maven’da archetype’lar da gezinebiliyorsanız, yeoman için de site yapmışlar istediğiniz üreticiyi seçebiliyorsunuz. Ben AngularJS uygulaması geliştirmek istediğimden ilgili üreticiyi aşağıdaki komutla sistem geneline yüklüyorum.

  • $ npm install -g generator-angular
  • $ yo angular

Buradan sonra seçtiğiniz üreticiye göre size bir takım sorular soruluyor. İşte, SaaS kullanacak mısın? Bootstrap kullanacak mısın? Hangi AngularJS modüllerini yükleyeyim? gibi sorular bunlar. Bura da bir hata yapmaktan çekinmeyin. Sonrandan kullanılan araçlar üzerinden sizde istediğiniz değişikliği yapabilirsiniz. Örneğin üretici Less kullanmayı önermedi mi, kendiniz sonradan başka araç üzerinden ekleyebilirsiniz.

Biraz da oluşan proje dizininden bahsedeyim.

  • .bowerrc: Bower, birazdan kendisinden detaylı olarak bahsedeceğiz, ayarlarının yapıldığı dosya
  • .editorconfig: EditorConfig, JS formatlama için kullanılan bir araç. SublimeText’ten tutunda Intellij’e kadar bütün IDE ve editorler destekliyor
  • .gitattributes: GIT ayarları icin kullanılıyor
  • .gitignore: GIT ignro dosyası
  • .jshintrc: JavaScript code quality aracı. Her build öncesi burada belirtilen kontroller yapılıyor. EditorConfig dosyası ile uyumlu.
  • .travis.yml: Travis bir Continuous Integration ortamı. Hudson ya da Jenkins alternatifi olarak düşünebilirsiniz. Bu dosyada ise onunla ilgili ayarlar bulunuyor.
  • app/ : AngularJS uygulamamız bu dizinin altında
  • bowercomponents/ : Bower, yukarıda ayarlarından bahsetmiştik, tarafından yüklenen client tarafı bağımlılıkları burada bulunuyor. Bu klasörü tabikide GIT’e yüklemiyoruz.
  • dist/ : Build aldığımızda, projemizin production ortamında kullanacağımız hali bu klasörde bulunuyor.
  • nodemodules/ : Az önce bahsetmiştim. NPM hem sistem genelinde hem proje özelinde çalışabiliyordu. Proje özelinde yüklenen paketler burada bulunuyor. Bu klasörü tabikide GIT’e yüklemiyoruz.
  • test/ : Testlerimiz burada bulunuyor. Peki bunları kim koşuyor derseiniz, ona birazdan değineceğiz.
  • Gruntfile.js : Grunt, birazdan kendisinden detaylı olarak bahsedeceğiz, ayarlarının yapıldığı dosya
  • bower.json : Bower’ın hangi client tarafı bağımlılıklarını yükleyeceği bu dosyada belirtiliyor.
  • package.json : NPM’in proje özelinde hangi araçları yüklemesi gerektiği bu dosyada belirtiliyor.
  • README.md: GIT için oluşturulmuş Readme dosyası.

Gördüğünüz gibi projenin hemen hemen tüm detayları düşünülmüş. Git’e projenizi yüklediğinizde yazacağınız Readme.md dosyası bile hazırlanmış.

Proje yapımızı genel olarak konuştuğumuza göre şimdi belirttiğimiz araçları konuşalım.

Bower ile Client Tarafı Bagımlılıkları

Bower’da client’ tarafı bağımlılıklarımızı yönetiyoruz. Bower’ı yüklemek için aşağıdaki komutu çalıştırıyoruz.

  • bower$ npm install -g bower

Bower’ı yükledikten sonra proje içerisinde bağımlılıklarımızı yüklemek için aşağıdaki komutları kullanıyoruz.

  • $ bower install : bower.json içerisindeki bağımlılıkları yükler. Yüklerken, .bowerrc’deki ayarları dikkate alır.
  • $ bower install <package> : bower.json içerisinde bulunmayan yeni paket yüklenir.
  • $ bower install <package> —save : bower.json içerisinde bulunmayan yeni paket yüklenir ve paket bilgisi bower.json dosyasına kaydedilir.
  • $ bower init : interaktif olarak bower.json dosyası oluşturulur.

Grunt ve Task Yönetimi

Grunt, JavaScript uygulamarlı için geliştirilmiş bir task yönetim aracı. Java tarafında tam olarak Ant’ın yaptığını yapıyor. Bağımlılıkları yönetmek için Ant nasıl Ivy’e ihtiyaç duyuyorsa, Grunt’ta Bower’a ihtiyaç duyuyor. Grunt içerisinde istediğiniz taskları tanımlayabiliyorsunuz. Fakat her task için ayrı bir npm modülü yüklemeniz gerekebilir. Tabi bu modüller proje özelinde olduğunda project.json dosyasına ekleniyor. Tüm Grunt tasklarını ise Gruntfile.js dosyasında tanımlıyoruz. Peki Grunt, örnek projede hangi tasklar için kullanılıyor?

  • Testlerin çalıştırılması: Grunt test klasörü altındaki testleri ilgili test araçlarını kullanarak (ki bizim örneğimizde bu Jasmine ve Karma) çalıştırıp rapor üretiyor.
  • Static Serverın Ayağa Kaldırılması: Grunt geliştirdiğimiz JavaScript dosyalarının anında görütülenmesi için bir sunucu ayağa kaldırıyor. Bu sunucu LiveReload denilen bir mekanizmaya da sahip oluyor. Grunt tüm development dosyalarını takip ediyor. Bir değişiklik olduğunda sizin belirttiğiniz işlemleri tekrar ediyor ve LiveReload eklentisi üzerinden Browser’ınıza komut gönderiyor. Bu komut sayesinde sayfanız otomatik olarak güncelleniyor.grunt
  • Minified-Uglified: JavaScript dosyalarınızı minified ediyor.
  • Saas ya da Less üzerinden CSS üretilmesi: SaaS ya da Less dosyaları üzerinden CSS üretiyor. Örnek projemizde ben bu özelliği kullanmadım.
  • CoffeeScript ya da TypeScript üzerinden JS üretilmesi
  • Kod Sitili Kontrolü: Projemizdeki .jshintrc dosyasını okuyarak, tüm dosyaların buna uygun geliştirilip geliştirilmediğini kontrol ediyor.
  • Vendor.#hash.js ve Script.#hash.js dosyalarının oluşturulması: Grunt tüm istemci tarafı bağımlılıklarını bizim için Vendor.#hash.js dosyası içerisinde paketleyip minified ediyor. Aynı şekilde kendimizin geliştirdiği tüm JavaScript dosyalarınıda birleştirip Script.#hash.js isminde bir dosya oluşturuyor. Buradaki #hash ise minified edilmiş dosya üzerinden üretiliyor. Yani kodda ya da bağımlılıklarda değişiklik yapıldığında, kullandığınız JS dosyası da otomatik olarak değişiyor. Bu sayede Browser cache’i ile uğraşmak durumunda kalmıyorsunuz. Ayrıca tüm html dosyalarınıda buna göre otomatik olarak güncelliyor.

Yeoman tarafından oluşturulan projede ise aşağıdaki taskları çalıştırabilirsiniz.

  • $ grunt build : Projenizi build eder. dist klasöründen projenizin build edilmiş haline erişebilirsiniz.
  • $ grunt task : Karma ve Jesmine testlerini çalıştırır
  • $ grunt serve : Projenizi development için LiveReload ve Watch ile ayağa kaldırır.

Bu tasklar, birden fazla subtaskın birleşmesinden oluşmaktadır. Örneğni build aldığınızda javascript dosyalarınız minified edilir.

Karma, Jasmine ve Testlerkarma_jasmine

Karma ve Jasmine değişik bir konsept. Dilim döndüğünce açıklamaya çalışayım. Java dünyasını düşünün, JUnit ile unit testlerinizi yazarsınız ve çalıştırırsınız. Fakat JavaScript dünyasında durum bu kadar basit değil. Neden? Çünkü Java dünyasında kodunuzu geliştirdiğiniz ortam ile çalıştırdığınız ortam aynıdır. Fakat JavaScript dünyasında, eğer client tarafına proje geliştiriyorsanız, kodunuzu geliştirdiğiniz ortam ile çalıştırdığınız ortam aynı değildir. Kodunuzu NodeJS ortamında geliştirirsiniz fakat Browser ortamında çalıştırırsınız. NPM ile yüklediğiniz modüller, browser ortamında yoktur sadece development ortamında vardır. Bu nedenle testlerinizin sağlıklı olması için testlerinizi bir browser ortamında çalıştırmalısınız. İşte Karma bize bu browser ortamını sağlıyor. Jasmine ise bizim Unit testlerimizi yazdığımız ortam. Grunt sağolsun ikisinide güzel güzel çalıştırıyor bizim adımıza.

  • Karma için sadece ayarları yapmanız gerekiyor. Bu test/karma.conf.js dosyasında yapıyoruz. Hangi browser üzerinde testlerimizi yapacağımızı belirtiyoruz. Madem bir browser ortamımız var istediğimiz baştan başa testlerimizi de geliştirebiliriz.
  • Jasmine’de ise çok bişey yapmamıza gerek yok, AngularJS zaten Jasmine için bazı kolaylıklar sağlıyor. Bunları kullanarak testlerimizi yazabiliriz.

 Son olarak, JavaScript’çi Gibi JavaScript Yazmak

Bu biraz zaman alacak tabi. Ben tuts+ üzerinden ve Youtube üzerinden videolar izleyerek başladım. Sonrasında ise google’ın aşağıdaki iki standartına göz attım, hala yazarken sık sık göz atmaya devam ediyorum. Bir zamandan sonra Java’cı gibi JavaScript yazmaktan kurtulup, JavaScript’çi gibi JavaScript yazmaya geçeceğimi umuyorum

End Of Line