Node.js ile Uygulama Geliştirme – 2 : Temel Kavramlar

NodeJS ile uygulama geliştirmeye başlamadan önce, hem JavaScript , hemde Node dünyasinda ki bazi kavramlara biraz aşinalık gerekmek de. Bu yazıdaki kavramlar(ben özetlemeye çalışsamda) özellikle “yeni başlayan arkadaşlar için” biraz karışık ve bazen sadece okumakla anlaşılabilecek konular değiller.

İşin bir diğer tarafıda, bu konuların çoğunu, Node.js yada kullanacağımız freamework ün bizim için soyutlamış/kolaylaştırmış olması . Aşağıdaki kavramların bazılarını pratikde hiç bilmesekde olur diyebiliriz.(Event-loop, LibUv, Posix vb. gibi)

Ama bir geliştirici olarak üzerinde çalıştığımız sisteme en azından genel olarak aşinalık her zaman verimliliğimizi artıracaktır. O yüzden bu yazının amacını şu şekilde belirtmekte fayda var;

Bu yazıdaki kavramlara aşinalık, bu kavramları uygulama seviyesinde “yani kod içinde” kullandığımızda daha belirginleşip, geliştirme sürecinde verimlilik sağlayacaktır. Uygulama geliştirdiğimiz platforma biraz daha detaylı bakmaya çalışmak ve sonraki sürece bir hazırlık yada kod verimliliğini artırmak için bu yazıyı node.js içindeki bazı kavramları konuşmak olarak düşünebiliririz.

Sonraki yazılarda hep kod yazacağımız için bu kavramlar daha rahat bir şekilde yerine oturacaktır.

Platform Olarak Bilmemiz Gerekenler:

Single-Thread – Birim zaman da tek bir  iş

Genel olarak ve fazla kafa karıştırmadan, thread kavramı için genel olarak şunu söyleyebiliriz “uygulamamız içinden işlemciye ulaşmamıza imkan veren her ayrı yola/kanala bir thread olarak bakabiliriz“. Günümüzde işletim sistemleri ve işlemciler bir den fazla thread ile çalışmamıza imkan vermekteler. Başka bir değişle bilgisayarımızdaki işlemcilere erişmek için bir den fazla yol kullanabilmekteyiz. Buda en genel haliyle “concurent/eş zamanlı” olarak birim zamanda daha fazla işlem yapabilmek demek.

Thread kavramı, özellikle .NET yada Java ile çalışan yazılımcılar için tanıdıkdır. bu iki platformda, concurrency/eş zamanlılık için multi-thread mimarisini kullanır. Fakat thread kavramı özellike thread sayısı artıkça yönetilmesi zor bir hale gelmekte ve ayrıca kullanabileceğimiz azami thread sayısının da bir sınırı olmakta. Node.js ise .NET yada Java gibi concurency/eş zamanlılık sorunu nu “multi thread” yapıyla değil, “single thread”  +event loop +lib/uv  3 lüsü ile çözmeye çalışmakta.

Yani, Node.js her zaman için tek bir thread(bu da main thread dediğimiz ve direkt olarak işlemcimizdeki lead-core olarak adlandırdığımız ana işlem birimini) kullanacaktır.  Bu ilk bakışta performans olarak dez avantaj gibi gözüksede, node.js in üzerine inşa edildiği event loop mimarisi, asenkron yapı ve lib/uv alt yapısı ile ciddi bir performans kazanımına dönüşmektedir. 

Node.js için çıkış noktasın “yüksek performanslı ölçeklenebilir network temelli uygulamalar geliştirme” olduğunu düşünürsek, ve özelinde web sunucularının(http isteklerinin) genelde ise network üzerinden gelen diğer tüm isteklerin(websockets vs. dahil) hızlı ve yüksek oranda işlenmesi / kabul edilmesi diyebiliriz.

Node.js e gelen tüm isteklerin kabul edilmesi tamamlandıktan sonra, diğer bir önemli sorunun da çözülmesi adına, node.js in libuv kütüphanesini kullandığını görüyoruz. Bu sorun “blocking I/O – diske yazma ve okuma işlemleri”  sorunu.  Diğer yazılarda bu konuya daha detaylı değinmeye çalıştığım için burada kısaca “libuv kütüphanesi sayesinde Node.js I/O işlemlerini bir bloklama olmadan yapabilmekte.” demekle yetinelim.

Node.js Event loop mimarisi ve Libuv alt yapısını, biz geliştiriciler için yönetmekte ve arka planda ciddi bir abstraction/soyutlama sağlamakta. Yani bu kavramları derinlemesine bilmek yada aktif olarak çalışma mantıklarına müdehale etmek gibi bir zorunluluğumuz yok.

Bir geliştirici olarak bizim için önemli olan kısım ise, hem javascript için hemde node.js için asenkron yapıyı iyi anlayıp düzgün bir şekilde kullanmak ve uygulama geliştirirken, Node.js in bu yapısını aklımızda bulundurup, asenkron yapıya bağlı kalmaya azami özen göstermek diyebiliriz.

Sonuç olarak ;

Node.js single thread bir yapı ve asenkron yapıya sadık kalmak performans için önemli.

diyerek bir sonraki başlığa bakalım.

Event-Loop

Yukarıda sıklıkla bahsettiğimiz, asenkron yapı ve single thread kavramının başladığı en önemli nokta “Event-Loop” . “Single thread” bir sistemin çözmesi gereken ilk problem, thread doluyken yani bir işlem yapıyorken sonraki işlemleri düzenli bir şekilde kabul edebilmesi yada sıraya koyabilmesi” diyebiliriz. Gerçek hayattan örneklerle devam edecek olursak; bir .NET web uygulamasını düşünün, sunucumuza yapılacak her bir istek için web sunucumuz (IIS) bir thread oluşturacaktır böylece olabildğince fazla isteği(http request) karşılama ve işlem birimine sevk etmeye çalışacaktır. Ama IIS in yada üzerinde çalıştığı platformun da azami bir thread sınırı olacaktır.

Örneğin, 500 thread den fazlasını kullanamayacağımız bir sistemde, 500+1. thread açılamayacağı için gelen istek cevaplanamaycaktır. Başka bir değişle, web sunucumuza gelen bu isteği kaybetmiş olacacağız.  Thread lardan biri boşalana kadar yeni bir istek almayacağız.

Şimdi aynı web uygulamasını Node.js ile geliştiridiğimizi düşünelim, single thread bir yapı yani birim zamanda sadece bir web isteğini kabul edip işlem yapabilme imkanı söz konusu gibi gelebilir fakat Node.js olabildiğince fazla web isteğini işleyebilme adına, üst katman olarak event-loop dediğimiz mimariyi  kullanmakta.

Aslında sadece web isteklerini düşünmek yanlış olacaktır, uygulamamızın, sırası gelen her bir iş parçasını işleme almasını düşünmek daha doğru olacaktır(bu bir web isteğide olabilir, bir DB sorugusu vs.) ama bugünlerde az çok her sistemin/uygulamanın web tarafı olduğu için en yaygın haliyle web istekleri(http requests) olarak örneklendirmeye çalıştım.

Bir web isteği , direkt olarak node.js tarafından değil üst katmanı olan Event-loop katmanı tarafında karşılanıp sıraya konulmakta, böylece multi thread yapıyla kıyaslanamayacak kadar daha fazla request/istek karşılanabilmektedir. Event-loop içinde sıraya konan her bir istek bir referans numarasıyla(teknik olarak bir c/c++ pointer) eşleştirilip, thread boşaldığında sırada bekleyen diğer işlemi event-loop dan  alınıp thread e aktarılmış olur. Aşağıdaki resim görsel olarak bu olayı güzel anlatmakta.

 

node.js event loop asenkron yapı call-back

Yukarıdaki resimde, Register call-back diye geçen tabir, asenkron yapının kullanılmasına işaret etmekte. Her bir istek için bir call-back(sırası gelen istek için ne yapacağımızı tanımladığımız fonksiyonlar) yukarıda bahsettiğimiz referans ile(c/c++ pointer) takip edilip gelen istek doğru bir şekilde ve bloklanmadan işlenmiş olmakdatır.

Kısaca: Event-Loop sayesinde, yapılacak işlemler  yada karışılanacak web istekleri bir havuzda toplanıp, sırası gelen işlemin tamamlanması ve olabildiğince fazla isteği karşılayabilme imkanı sunulmaktadır. Blogdaki bu konuyla ilgili daha teknik olan yazıya bakabilirsiniz.

Single Thread ve Event-Loop yapısından bahsettik şimdi yine yukarıda sıkça bahsettiğimiz asenkron yapı ve call-back kavramına bakalım.

1 –  Asynchronous Programing and The callback pattern  – Asenkron programlama ve call-back ler

Yukarıdaki başlığı türkçeye cevirmektense, genel olarak ne ifade ettiğini anlamaya çalısarak başlayalım. Asenkron işlemler dediğimizde genel olarak “bir işlemin programın akışını blok etmeden gerçekleştirilmesi” ni anlayabiliriz. Programın “akışının blok edilmesiyle” neyi kast ediyoruz? Şöyle düşünebiliriz;

Bir web uygulamasını düşünün, bir butona tıkladığımızı ve bunun sonucunda, bir web isteği oluşturulduğunu düşünün. Bu web isteğine cevap gelmesinin 3 saniye sürdüğünü düşünün, yada bir windows uygulamasında bir butona tıkladığınızı ve bu tıklama neticesinde, 5-10 saniye sürmesi muhtemelen bir işlem yapılacağını düşünün(büyük miktarda bir verinin sıralanması vs. gibi) .

İster web örneğinde olsun, ister windows form örneğinde, eğer senkron bir yapımız varsa, kullanıcı bu işlem bitene kadar başka bir şey yapamaycaktır. Örneğin web sayfasındaki butona tıkladğında, işlem bitmeden başka bir şey yapma imkanı olmayacaktır. Aynı şekilde windows örneğinde de, sıralama işlemi bitmeden başka bir işlem yapılamayacaktır.

Her iki örnektede kullanıcın kullandığı ekranlar en basit haliyle işlemler bitene kadar donacaktır. İşte bu tür sorunları aşmak için 2 alternatifimiz var, biri multi-thread kullanımı(böylece, örneğin sıralama işlemimiz için bir thread ayırıp, kullanıcının ana thread ile başka işlemler yapmasına izin vermek gibi) diğeri ise Asenkron yapıyı kullanmak.

Multi thread mimarisine sahip dillerde, ana thread doluyken başka bir işlem yapabilmek adına, yeni bir thread oluşuturup bu thread i diğer işlemlerimiz için kullanabilmekteyiz dedik.  Multi-thread bir yapıda aşağıdakine benzer bir yapıyı düşünebiliriz;

işlem 1 – ana thread,

işlem 2 – alt thread,

işlem n – n thread

yukarıda n in maksimum bir sınırı olmak kaydıyla, sistemin/kullandığımız programlama dilinin bize verdiği imkanlar dahilinde birden fazla işi aynı anda yapabilmekteyiz. Başka bir değişle, işlem 2 nin gerçekleşmesi için , işlem 1 in bitmesini beklemek zorunda değiliz. (non-blocking until thread n-max. / azami thread sayısına ulaşana dek bloksuz iş akışı)

Node.js yukarıda bahsettiğimiz gibi, “single thread” kullanabildiği için, birden fazla thread kullanma imkanı yok ama  senkron yapinin uygulamamiza getireceği “bloklanma” sorunu aşabilmek için asenkron yapıyı kullanmakta. Asenkron yapı node.js için de Event-Loop, Event-Queue ve Call-Back ler aracılığıyla yönetilmekte. Bu 3 kavram karışık ve ya kompleks gibi gelebilir ama uygulamamız içinde yapmamız gerekn tek şey call-back leri kullanmak tan ibaret diyebiliriz.

Öncelikle, kısa bir hatırlatma yaparak devam edelim; Node.js içinde hemen hemen herşey asenkron yapıya uygun tasarlanmıştır. Hemen hemen herşeyden kastım, node.js in bize sunduğu “API / Uygulama geliştirme alt yapısı” asenkron fonksiyonlarla donatılmıştır. Ama bazi fonksiyonlarin senkron versiyonlarida mevcuttur.

Bazi fonskiyonlarin senkron versiyonlarinin bulunmasinin sebebi genel oalrak “bazı durumlarda, işlem yapmadan önce mutlaka ama mutlaka öncelikli olarak yapmamız gereken işlemin tamamlanmasını garanti altın almak” yani uygulamanın akışını bilerek ve isteyerek blok altına almak isteyeceğimiz bazı durumların olması.

Örneğin, bir web uygulaması yazarken, SSL sertifikasının yüklenme işlemini ele alalım. SSL sertifikası yüklenmeden uygulamanın akışının devam etmesini istemeyeceğimiz durum en yaygın örnek olarak verilebilir. Şimdi, asenkron yapının kullanışına(SSL sertifikasını örneğiyle) bakalım;

1- senkron yapı

const fs = require('fs') 
let ssl;
try { 
 ssl = fs.readFileSync('public.cert')
} catch (ex) { console.log(ex) }
 console.log("sertifika yüklendi")

yukarıdaki ki örnekte, bir ssl sertifikasını senkron bir şekilde yüklüyoruz, eğer kod a dikkatli ce bakarsanız “Sync” son eki ile biten “readFileSync()” metodunu kullandığımızı görebilirsiniz. Node.js içinde sonu “Sync” ile biten metodlar, senkron olarak çalışır yani işlem bitene kadar uygulamanın akışını blok ederler.

O yüzden mecburiyetler dışında “örneğin SSL sertifikasın daki durum gibi”  bu metodları kullanmaktan kaçınmamız gerekir.  Yukarıda SSL sertifikamızın yüklenmeden bir başka işleme geçmemeyi “özellikle ” istemekteyiz ve bu yüzden readFileSync()  metodunu kullandık.

2- asenkron yapı

Hem node.js içinde hemde node.js için yazılmış diğer modüller/kütüphaneler içinde bir kaç istisna dışında,  tüm fonskiyonlar asenkron olarak çalışır diyebiliriz. bir fonskiyonun asenkron olarak çalışması ne demek?

En basit hali ile(yada pratik deki karşılığı ile), eğer bir fonksiyona, son parametre olarak “başka bir fonksiyonu” call-back olarak geçiyorsak o fonksiyon a asenkron fonksiyon demekteyiz. Eğer daha önce hiç Javascript kullanmadıysanız “Javascript, fonksiyonlarımıza parametre olarak başka bir fonksiyonu” geçmemize imkan vermekte.

 call-back nedir?

call-back  dediğimiz fonksiyonların, yapı olarak diğer fonksiyonlardan hiç bir farkı yoktur. Call-Back diye adlandırmamızın nedenini aşağıdaki örnekle anlamaya çalışalım. Yukarıdaki SSL örneğini asenkron olarak yazacak olursak;

const fs = require('fs')
fs.readFile('public.cert', function (err, sertifika) {
    if (err) { // hata kontrolu
        return console.log(err)
    }
    console.log("Sertifika Yuklendi...")
})

Teknik olarak bakacak olursak, gerçekleştirmek istediğimiz işlemi, bir fonksiyon halinde yazıp, readFile() metoduna son parametre olarak veriyoruz. senkron versiyonuyla karşılaştırdığımızda ilk fark fonksiyon isimlendirmesi diyebiliriz(sync son eki);

readFile(”dosya_yolu’,call_back) – Asenkron şekli

readFileSync(“dosya_yolu”)  – Senkron şekli

Node.js araka planda, event-loop ve LibUv mimarisini kullanarak işlemi non-blocking/ bloksuz bir şekilde yerine getirmekte. Teknik olarak, blog da bu konuyu anlatan başka yazı olduğu için detaylara girmemize gerek yok ayrıca  zaten uygulama geliştirme adına teorik olarak bu süreci bilmeninde bir zorunluluğu yok.

Pratik deki iş akışı açısından ise olup biten şey gayet basit;

  1. Node.js e bir dosyayı okumasını söylüyoruz,
  2. dosyayı diskten okuma sürecini beklemek yerine,
  3. dosyayı okuduğun zaman yapılması gereken işleri  taşıyan fonksiyonu call-back olarak sağlıyoruz
  4. işlem bittiğinde node.js e, “sana parametre olarak verdiğim fonksiyonu geri çağır va çalıştır diyoruz ” “call-back

Önemli bir başka mesele ise, call-back fonksiyonuna geçtiğimiz iki parametre;

function (err, sertifika)

Node.js içinde standart olarak bütün call-back fonksiyonlarına, ilk parametre olarak bir hata varmı yok mu anlayabilmek adına bir “Error” nesnesi sağlanmakta. Bu standart tüm node.js ekosistemi için geçerli diyebiliriz. Bu yüzden aşağıdaki kontrolü yaptık,

 if (err) { // hata kontrolu
        return console.log(err)
    }

Eğer, err  nesnesi bir değer taşıyorsa (null değilse), bu if bloğu tarafından yakalanmış olacak. Ve hata durumunda gerekli işlemi yapabilme imkanımız olacak.  İkci parametre olarak ise bizim ihtiyacımız olan gerçek değer call-back a taşınmış olacak.

Bizim örneğimiz de bir dosyayı okumaya çalıştığımız için “ssl sertifikamız” geri dönecek. Örneğin, bir veri tabanından kayıtları sorgulaycak olsaydık, bu değer veri tabanından gelecel kayıtları taşıyacaktı. Bu parametrelerin sıralaı önemli, ilk parametre her zaman hata kontrolü, ikincisi ise gerçek veriyi taşıaycaktır.

Sıralamaya uydğunuz sürece, istediğimiz gibi islendirmek de özgürüz. ama genel kullanım şekliyle ilk parametre genelde “err” şeklinde kullanılmaktadır. Aşağıdaki kullanımda tamamen geçcerlidir;

fs.readFile('public.cert', function (ali, veli) {
    if (ali) { // hata kontrolu
        return console.log(ali)
    }
    console.log("Sertifika Yuklendi...")
})

Yukarıda ali değişkeni hata varsa ona karşılık gelecekken, veli de dosyamıza referans olmaktadır. Ama tabiki isimlendirmeyi yaparken daha net kullanımlar, hem bizim hemde kodu okuyan diğer kişilerin  işini kolaylaştıracaktır.

Gördüğünüz gibi, asenkronyapı ve call-back kavramı gayet basit bir kullanıma sahip, ilgili fonksiyona son parametre olarak “call-back diye adlandırdığımız” bir fonksiyonu geçiyoruz. Bu call-back fonskiyonu yaptığı işe göre node.js tarafından bazı parametreler alıyor. İlk parametre bir hata nesnesi , diğer parametre ise ihtiyacımız olan gerçek bilgiyi/veriyi içermekte.

Bu arada, node.js in sağladığı fonksiyonların dışında kendi fonksiyonlarımızı da “asenkron” bir şekilde yazabilnekteyiz. Örneğin aşağıda bir veri tabanına bağlanmak için kullandığımızı bir fonksiyonumuz  olsun;

function veritabaniniSorgula(baglantiYolu, callback) {
    var db = veriTabaninaBaglan(baglantiYolu);
    var veriler = db.sorgulamayiYap();
    callback(veriler)
}

Yukarıdaki fonksiyonu aşağıdaki gibi çağırabiliriz;

veritabaniniSorgula("baglantiYolu", function (err,veriler) {
    console.log("Veriler : ",veriler)
})

Asenkron yapıya kendi yazdığımız, fonksiyonlar içinde de olabildiğince sadık kalmaya çalışmalıyız. Serinin diğer yazılarında bol bol kullanacağımız için daha fazla uzatmayalim

Kısacası,

  1. Yapacağımız işlemleri taşıyan ve başka bir fonksiyona son parametre olarak geçtiğimiz fonksiyonlara “call-back” diyoruz

  2. Node.js içinde bu şekilde call-backlari kullanarak, bloksuz bir uygulama akışınada “Asenkron” programala diyoruz.

Node.js in arka planda asenkron yapıyı , event-loop ve LibUv entegrasyonu ile yağtığını da bir kez daha hatırlatalım.

2 – The Module Pattern  / Node.js modül kavramı

Javascript in dil ile ilgili en önemli eksiklerin başinda, namespacing / isim alanlarinin eksikliği yada , yazdığımız kod  ların, eğer dikkat etmezsek, tamamının global scope da çalışma riskinin olması geliyor diyebiliriz. Burada bu konuyu detaylandirmadan,(Bu konu ile ilgili bir detay yazısi blogda mevcut) Node.js in bu konuyu nasil yönettiğine bakalim.

Yukarida kısaca bahsettigimiz, namespace ve global scope problemini aşmak icin CommonJS isimli bir grup yada vakif, bir standart calışmasına giderek, ” CommonJS module pattern”  isimli bir standartlaştirma örneği yayınlar ve bu standart , javascript dünyasında ciddi anlamda kabul görür.

Node.js de , işte bu CommenJs Modules standart larıni temel alan modül / namespace yapısi ile, bize kodlarimizi, daha modüler bir yapıda yazmak, ve kodlarimizin hangi kısmini , uygulamamizin diger kısimlarina açagimizi organize etme imkanı verir.

Bu yapı oldukça basittir, simdi asağida, bir veri tabani bağlantısi yağtığımızı düşünün,

veritabani.js

var mysql = require('mysql')
 var paşword ='123456';
 var user='admin'
 var baglanti = mysql.connect('localhost',user,paşword,'urunlerDB')
 exports.baglan = function(){
 baglanti.open()
 }
 exports.baglantiKapat = function(){
 baglanti.close()
 }
 exports.veriGetir = function(tabloIsmi){
 var veri = mysql.query('select * from '+tabloIsmi)
 return veri;
 }

Oncelikle, Node.js yazdiginiz her bir .js dosyasini bir nevi  bir module olarak kabul ediyor diyebilirz.  yukarıdaki veritabani.js içinde, exports.xx seklinde(exports.baglan() gibi) dısari acilmayan hersey private dir. exports.baglan() seklinde, tanimladigimiz hersey, (fonkisyonlar, nesneler, degiskenler) ise diger modüllerden(her bir .js dosyasi bir module olarak kabul ediliyor diye tekrar edelim) çagrilabilir, degistirilebilir vs.  Örnegin  dosyanin en başındaki require(‘mysql’) seklindeki tanimlama ile, mysql tarafindan yazildigini var saydigimiz, veritabani sürücüsünü bu dosyaya dahil etmis olduk.

mysql.connect(), methodunun, mysql.js isimli modülde, exports.connect()  seklinde ihraç edildigini düsünebiliriz.

Node.js , her bir .js uzantili dosyayi bir modül olarak kabul eder  dedik,  Her bir .js uzantıli dosyamiz, node.js tarafindan çalıştırılmadan önce,  bazi ekstra eklemelere maruz kalır, node.js her bir dosyanın içindeki kodu bir IIFE (Immediately Invoked Function Expreşion – kendi kendini çagıran bir fonksiyon) ile sarmalar, ve bir module.exports nesnesini geri döndürür. Gerçekte, bir namespace olmasada, javascript e has bazi yeteneklerle, bir namespace etkisi oluşturur. (tarayicilarda bu durum farklıdir, browser bir javascript dosyasıni nasıl bulduysa o şekilde işleme koyar. her hangi bir değişiklik yapmaz.)

CommonJS  tasarım kalıbı işimizi kolaylaştırsada, Javascript içinde dahili olarak bulunan “native” bir yetenek değil. Javascript in en yeni sürümü ES2015 bu eksikliği kapatmak için artık native bir modül sistemi barındırmakta. Başka bir değişle artık Javascript in de bir modül sistemi var. Node.js ES2015 ile gelen bir çok yeniliği içnde barındırsada henüz resmi olarak bu yeni modül sistemini desteklememekte. Muhtemelen 2-3 ay içinde , bu yeni modül sistemi de desteklenir hale gelecektir.

Node.js yeni modül sistemini en azından şuan desteklemesede, bir kaç küçük yardımla biz uygulamalarımızda bugün de kullanabilme imkanına sahibiz. Biz serinin diğer yazılarında bu yeni Modül sistemini kullanacağız. Yeni modül sistemi genel olarak şu şekilde bir söz dizimine sahip;

Modül ithali için import u kullanacağız

import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";

Modül ihracı için export u kullanacağız

export const sqrt = Math.sqrt;
export function square(x) {
 return x * x;
}
export function diag(x, y) {
 return sqrt(square(x) + square(y));
}

Modül sistemini örnekler de bolca kullancağımız için, detayları ilerideki yazılara bırakalım.

3 – NPM  / Node.js paket – modül yöneticisi ve Package.json 

Node.js içinde kullanacağimiz, başkalari tarafindan yazılan, paketleri / modülleri uygulamamıza kolayca dahil etmemize yarayan, yada kendi yazdığımız modülleri, paketleyip paylaşmak icin kullanabilecegimiz bir paket yoneticisi npm. PHP icin composer, .NET dünyasindaki nuget  ile kıyaslayabiliriz.

npm in ayrıca bir otomasyon aracı olarak da kullanıldığını da belirtelim. Yapacağımız bazı işlemler için bir Task Runner olarak da kullanabilmekteyiz.

packages.json dosyası ise uygulamamızın genel ahvalini içinde tutan bir özet dosyası diyebiliriz. Ayrıca, uygulamamızınz içinde kullanacağımız node.js modüllerinin de bir listesini tutup uygulamamızın bağımlılıklarını da yönetme imkanı vermekte.

Bu yazı çok uzadığı için bir de, bazı kavramların örnek kullanımıyla daha rahat anlaşılacağını düşündüğüm için aşağıdaki konulara burada değinmedim. Bir sonraki yazıyla birlikte kod yazmaya ve örnek bir web uygulaması geliştirmeye başlayacağımız için bu konulara yeri geldikçe değinmiş olacağız.

  1. Event Emmiter
  2. Promises
  3. Babel/Typescript vb. araçların  node.js dünyasındaki yeri
  4. Clustering

Yukarıdaki konuları serinin devamında pratikde kullanımlarıyla ele almaya çalışacağız.

Bir sonraki yazıda node.js ile ilk web uygulamamızı yazarak devam edelim inş.

Kolay Gelsin.

Leave a Reply

Your email address will not be published. Required fields are marked *