onokumus

Matematik Öğretmeni

NODE.js-4-Broccoli

Bir önceki broccoli.js yazımızda broccoli ‘nin tanımı aslında biraz eksiktir.

Brokoli sebzesini düşünün. Kökte birleşen bir sürü dal. Bu dalları gulp.js nin task akışı, kökte birleşen dalları grunt.js nin taskları olarak düşünebiliriz. Broccoli.js de gulp gibi unix I/O streaming mantığında ilerlediği için grunt dan hızlı. Ama sevmediğim yönü build işlemi sonunda hepsini bir klasöre toplaması.

Şimdi örneğimize geçelim

Senaryomuzda meşhur Bootstrap ı projemize ekleyelim. Bunun için bower paket yöneticisini kullanacağız. Sistemimizde bower in global olarak kurulduğunu varsayıyoruz.

Bootstrap ekleme
1
bower install bootstrap

public klasörü içindeki ‘index.html’ yi şöyle güncelleyelim.

public/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>ilk sayfam</title>
  <link rel="stylesheet" href="bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-sm-6">
        <h1 class="text-primary">ilk sayfama hoş geldiniz</h1>
      </div>
      <!-- /.col-sm-6 -->
    </div>
    <!-- /.row -->
  </div>
  <!-- /.container -->
<script src=jquery/dist/jquery.min.js></script>
<script src=bootstrap/dist/js/bootstrap.min.js></script>
</body>
</html>

Konsolda broccoli serve deyip tarayıcımızda http://localhost:4200 yi açalım.

Hayaller mavi düzgün bir yazı, gerçekler siyah ve serif li bir yazı. Sebep bootstrap ın yüklenmemesi. Tarayıcımızda F12 tuşuyla baktığımızda görebiliriz. Sebep ise jquery ve bootstrap ın yolu yanlış. Brocfile.js dosyamızı güncelleyelim.

Brocfile.js
1
module.exports = 'bower_components';

Tekrar test edelim. Önce konsolda çalışan broccoli serve komutunu Ctrl+C ile durduralım. Broccoli.js kaynak dosyalarındaki güncellemeleri otomatik algılasa da Brocfile.js deki değişiklikleri algılamıyor.

Konsolda broccoli serve deyip tarayıcımızda http://localhost:4200 yi açalım. Bu safer de index.html yüklenmedi. FTP penceresine benzer şekilde jquery ve bootstrap ın tüm dosyaları (bower ile yüklendiği şekilde) gösteriyor. Burada broccoli nin mantığı ile ilgili bir şey öğrenmiş oluyoruz. Bize node.js nin yerleşik http paketiyle oluşturduğu http sunucusunda bower_components klasörünü kök olarak sunuyor.

Dalları Birleştirmek

Tek dallı brokoli sebzesi olmayacağına göre iki ayrı dal oluşturup bunları birleştirmeliyiz. Bunun için de bir plugin var.

broccoli-merge-trees
1
npm i -D broccoli-merge-trees

Artık iki ayrı dalı tek kökte birleştirebiliriz.

Brocfile.js
1
2
3
var birlestir = require('broccoli-merge-trees');

module.exports = new birlestir(['public', 'bower_components']);

Tekrar test ettiğimizde mavi yazımızı görebiliriz.

Peki ne oldu? broccoli.js public ve bower_components klasörlerini bize http sunucunun kökünde birleştirdi. Bunu ise otomatik oluşan tmp klasörünü inceleyerek görebilirsiniz.

broccoli.js index.html dosyasındaki değişiklileri otomatik algılasa da tarayıcımızı otomatik güncellemiyor.

sağlıcakla…

devam edecek …

NODE.js-3-Broccoli

Nedir?

broccoli.js node.js projelerini geliştirirken, projenin oluşturulması esnasında iş akışı sağlar. Mottoları da

Broccoli.js – The asset pipeline for ambitious applications.

Nedir?

broccoli.js node.js projelerini geliştirirken, projenin oluşturulması esnasında iş akışı sağlar. Mottoları da

Broccoli.js – The asset pipeline for ambitious applications.

şeklinde. Bu işi yapan tek modül değil elbette. Grunt.js , Gulp , componentjs, Brunch bazıları.

Artıları - Eksileri

  • [+] Çok hızlı
  • [+] Basit (Eğer mantığı kavranırsa)
  • [+] ember.js geliştiricileri geliştiriciler arasında
  • [-] Bir grunt.js veya gulp.js mantığında değil. (Tabi bu ikisine alışkınsanız)
  • [-] Çok tanınmıyor.
  • [-] Eklenti sayısı düşük

Kurulum

Öncelikle broccoli-cli global olarak kurulmalı.

broccoli-cli
1
npm install --global broccoli-cli

Proje Oluşturma

Bir web projesi oluşturalım.

proje kurulumu
1
2
3
mkdir broccoli101
cd broccoli101
npm init -y

Son kod bize pek soru sormadan package.json oluşturmak için. Eğer sorduğu sorulara kendi cevaplarınızı konsoldan yazmak isterseniz sondaki -y parametresini yazmayın.

Şimdi html sayfalarımızın bulunduğu klasörü ve html sayfamızı oluşturalım.

web sayfası ekleme
1
2
mkdir public
echo "ilk sayfam" >> public/index.html

broccoli101 klasörü içinde public klasörü ve içinde de index.html web sayfamızı oluşturduk.

Projeye Broccoli ‘yi Ekleme

Öncelikle broccoli yi geliştirme bağımlılığı olarak kuralım.

Bağımlılık ekleme
1
npm install broccoli --save-dev

package.json dosyasının sonuna şöyle şey eklenmiş olması gerek.

package.json
1
2
3
"devDependencies": {
  "broccoli": "^0.16.4"
}

Şimdi de broccoli101 klasörü içinde Brocfile.js dosyası oluşturup, içine şunları yazalım.

Brocfile.js
1
module.exports = 'public';

Test Zamanı

Konsolda aşağıdaki komutu verelim.

Konsol
1
broccoli serve

Eğer http://localhost:4200/ ta

Browser
1
ilk sayfam

görüyorsak tamamdır. Bu kadar

sağlıcakla …

Devam edecek …

NODE.js - 2 - Modül Yazma

Giriş

Bu yazımızda less kullanarak less dosyalarımızı otomatik derleyen bir modül yazacağız.

Poje Oluşturalım

Öncelikle /home/ono dizininde proje2 klasörü oluşturalım.

proje oluşturma
1
2
mkdir proje2
cd proje2

Artık proje2 klasörürümüz oluştu ve içindeyiz. Bu kalsörün içinde manuel olarak package.json dosyası oluşturabiliriz. Fakat aşağıdaki komutla otomatik oluşmasını da sağlayabiliriz.

npm init
1
npm init

Bize bazı sorular soracaktır. İsterseniz kendi cevaplarınızı yazabilirsiniz. Her cevaptan sonra enter tuşuna basarsanız sonraki soruya geçecektir. Hepsini enter la geçebilirsiniz. package.json dosyasının son hali şuna benzer olacaktır.

package.json
1
2
3
4
5
6
7
8
9
10
11
{
  "name": "proje2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "onokumus <onokumus[at]gmail.com> (http://onokumus.com/)",
  "license": "MIT"
}

Less Modülü Yükleme

Projemizde less dosyalarını otomatik derleme işlemi yapacağımız için less modülünü yüklememiz gerekiyor. Bunun için konsolda

less yükleme
1
npm i -S less

komutunu veriyoruz. Bu komutun uzun şekli npm install --save less şeklindedir. Böylelikle package.json dosyamızda modülümüzün less modülünü kullanacağını belirttik.

Script Yazma

proje2 klasöründe index.js dosyası oluşturalım. İçeriği de şöyle olsun.

proje2/index.js
1
2
3
var less = require('less') // less modülünü çağır

console.log(less.data.colors.aliceblue); // aliceblue renginin hex kodunu verir

Konsol çıktısı aşağıdaki şekilde ise hata yoktur.

konsol
1
#f0f8ff

Kodumuzu değiştirelim ve less in gerçekten derleme yaptığını görelim. index.js nin son hali şöyle.

proje2/index.js
1
2
3
4
5
6
7
8
9
10
11
var less = require('less') // less modülünü çağır

//console.log(less.data.colors.aliceblue); // aliceblue renginin hex kodunu verir

less.render('@renk: #069; a {color: @renk;}', function(hata, sonuc){
  if(hata) {
    console.log(hata);
  } else {
    console.log(sonuc.css);
  }
});

Konsol çıktısı şöyle ise hata yoktur.

konsol
1
2
3
a {
  color: #006699;
}

Fakat biz harici bir less dosyasının derlenmesini istiyoruz.

Less Dosyası Oluşturma

proje2 klasörü içinde less klasörü, less klasörü içinde de style.less dosyası oluşturalım. İçeriği de şöyle olsun.

proje2/less/style.less
1
2
3
4
5
6
7
8
9
10
@renk: #069;

a {
  color: @renk;
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
}

Şimdi ise style.less dosyasının içeriğini okutup less.render fonksiyonuna göndermeliyiz. Bunun için fs modülünü kullanacağız. index.js dosyasının son hali şöyle.

proje2/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var less = require('less') // less modülünü çağır
var fs = require('fs'); // file system modülünü çağır

var lessFile = fs.readFileSync('./less/style.less', 'utf8');

//console.log(less.data.colors.aliceblue); // aliceblue renginin hex kodunu verir

// less.render('@renk: #069; a {color: @renk;}', function(hata, sonuc){
//   if(hata) {
//     console.log(hata);
//   } else {
//     console.log(sonuc.css);
//   }
// });

less.render(lessFile, function(hata, sonuc){
  if(hata) {
    console.log(hata);
  } else {
    console.log(sonuc.css);
  }
});

Konsol çıktısı şöyle ise hata yoktur.

konsol
1
2
3
4
5
6
7
a {
  color: #006699;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

Son olarak konsoldaki çıktıyı style.css içine yazdırmamız gerekiyor. Hatta css klasörü içine yazdıralım. index.js dosyamızın son hali şöyle.

proje2/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var less = require('less') // less modülünü çağır
var fs = require('fs'); // file system modülünü çağır

var lessFile = fs.readFileSync('./less/style.less', 'utf8');

//console.log(less.data.colors.aliceblue); // aliceblue renginin hex kodunu verir

// less.render('@renk: #069; a {color: @renk;}', function(hata, sonuc){
//   if(hata) {
//     console.log(hata);
//   } else {
//     console.log(sonuc.css);
//   }
// });

// less.render(lessFile, function(hata, sonuc){
//   if(hata) {
//     console.log(hata);
//   } else {
//     console.log(sonuc.css);
//   }
// });

less.render(lessFile, function (hata, sonuc) {
  if (hata) {
    console.log(hata.line + '. Satırda "' + hata.message + '" Hatası var');
  } else {
    fs.exists(__dirname + '/css', function (varmi) {
      if (varmi !== true) {
        fs.mkdir(__dirname + '/css');
      }
      fs.writeFile(__dirname + '/css/style.css', sonuc.css, function (err) {
        if (err) {
          console.log('Bir Hata Oluştu :' + err);
        } else {
          console.log('işlem başarılı');
        }
      });
    });
  }
});

Kontrol amacıyla konsolda node index komutunu verelim ve css klasörü içinde style.css dosyamızın oluştuğunu görelim. Bu script proje2 dizininde css klasörü yoksa otomatik oluşturmakta ve içine style.css dosyasını yazmakta.

Sonuç

Son olarak package.json dosyamızı aşağıdaki gibi düzenleyelim ki node index komutu yerine npm start komutu aynı işi yapsın.

package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "name": "proje2",
  "version": "1.0.0",
  "description": "Less dosyalarını otomatik derleme scripti",
  "main": "index.js",
  "scripts": {
    "start": "node index"
  },
  "author": "onokumus <onokumus@gmail.com> (http://onokumus.com/)",
  "license": "MIT",
  "dependencies": {
    "less": "^2.1.1"
  }
}

Kodlar

Dersimizdeki örnek kodları https://github.com/onokumus/node-ders adresinden inceleyebilirsiniz.

NODE.js - 1 - Bismillah

Başlarken

Öncelikle bunun bir yazı dizisi olmasını planlıyorum. Fakat okuyucular bir ders olarak telakki etmesinler. Ders verecek yeterlilikte olduğumu düşünmüyorum. Olsa olsa benim gibi acemiler için bir başlangıç rehberi olur.

Kurulum

İlk önce node.js ‘yi bilgisayarımıza kurmalıyız. Bunun için node.js sayfasından işletim sistemize uygun olan paketi kuruyoruz.

archlinux node.js kurulum
1
sudo pacman -S nodejs

Test

Kurulumu test etmek için konsol da aşağıdaki komutu verelim.

node test
1
node -v

Benim bilgisayarımda 0.10.29 versiyonu kuruluymuş. Şimdi de npm nin kurulu olup olmadığını test edelim.

npm test
1
npm -v

npm nin 1.4.16 versiyonu kuruluymuş.

node.js ile konsol üzerinde denemeler yapalım. Konsolda;

node aritmetik
1
node

komutunu verdiğimizde şöyle bir;

node konsole
1
>

çıktısı olmalı. Çeşitli matematik işlemleri yapalım.

node aritmetik
1
2
3
> 5+4 // 9
> Math.PI // 3.141592653589793
> Math.cos(Math.PI) // -1

kafi.

JavaScript Yazalım

Artık node.js ile javascript yazalım. Bunun için bir proje1 klasörü oluşturalım. Bu klasörün tam yolunu iyi bilmemiz gerekiyor. Ben kolaylık olsun diye /home/ono dizininde proje1 klasörü oluşturuyorum. İçinde de index.js dosyasını oluşturalım.

proje1/index.js
1
console.log("node.js çalıştı");

Oluşturduğumuz index.js nin çalışmasını test edelim.

konsol
1
node index

Eğer node.js çalıştı çıktısını alıyorsak sorun yok demektir. Burada

node index

yerine

node index.js

komutunu da verebilirsiniz. Farketmez.

Modül Yükleme

node.js moduler bir yapıdadır. Yani başka birilerinin hazırladığı modülleri de, kendimizin hazırladığı modülleri de kullanabiliriz. Bunun için node.js ‘nin require modülünü kullanacağız. Bu sınıfı kullanmak için ekstra bir şey yapmamıza gerek yoktur. Sadece çağıracağız.

Örneğimize geçelim. proje1 klasörü içinde cember.js dosyasını oluşturalım.

proje1/cember.js
1
2
3
4
var PI = Math.PI;
function alan (r) {
  return PI * r * r;
}

Şimdi index.js dosyasını güncelleyelim. Son hali şöyle olmalı.

proje1/index.js
1
2
3
4
// console.log("node.js çalıştı");
var cember = require("./cember"); // cember modülünü çağır

console.log("Yarıçapı 5 olan çemberin alanı : " + cember.alan(5));

Şimdi test yapalım.

konsol
1
node index

Sonuç: hata! Çağırılan nesnenin içinde alan diye bir metod yok diyor. Aslında vardı? Neden? Aslında sebep basit. cember.js dosyası içindeki alan fonksiyonu sadece çember sınıfına ait. Dışarıdan erişilemez. Bir anlamda private. Dışarıdan kullanıma açmak için exports etmeliyiz. cember.js dosyasını güncelliyoruz. Son hali aşağıda.

proje1/cember.js
1
2
3
4
5
6
var PI = Math.PI;
function alan (r) {
  return PI * r * r;
}

module.exports.alan = alan;

Tekrar test yapalım.

konsol
1
node index

Sonuç:

konsol
1
Yarıçapı 5 olan çemberin alanı : 78.53981633974483

Tamam. Peki index.js dosyamızdaki 2. satırda çağırma esnasında ./cember şeklinde değilde neden sadece cember şeklinde çağırmadık? node.js modülleri çağırırken ön tanımlı olarak iki klasöre bakar.

  • node.js kurulurken otomatik yüklenen /usr/lib/node_modules klasörüne
  • proje1 klasöründe node_modules klasörüne

node.js için index.js ile cember.js nin aynı klasörde olması önemsizdir. Bizden tam yolu söylememizi ister. Bu yüzden cember modülünü çağırırken başına ./ koymamız gerekir.

Bir deneme daha yapalım. proje1 klasörü içinde lib klasörü oluşturalım ve içinde dikdortgen.js dosyası oluşturalım.

proje1/lib/dikdortgen.js
1
2
3
4
function alan (en, boy) {
  return en * boy;
}
module.exports.alan = alan;

index.js dosyamızı güncelleyelim. Son hali :

proje1/index.js
1
2
3
4
5
6
7
8
// console.log("node.js çalıştı");
var cember = require("./cember"); // cember modülünü çağır

console.log("Yarıçapı 5 olan çemberin alanı : " + cember.alan(5));

var dikdortgen = require("./lib/dikdortgen");

console.log("Eni 5 boyu 4 olan dikdörtgenin alanı : " + dikdortgen.alan(5,4));

Çıktımız şöyle ise sorun yok demektir.

konsol
1
2
Yarıçapı 5 olan çemberin alanı : 78.53981633974483
Eni 5 boyu 4 olan dikdörtgenin alanı : 20

Demek ki yukarıdaki iddiamız doğru. node.js ön tanımlı olarak node_modules klasörüne bakar dedik. Test edelim. Bunun için proje1 klasörü içinde node_modules klasörü ve içinde de kare.js dosyası oluşturalım.

proje1/node_modules/kare.js
1
2
3
4
function alan (kenar) {
  return kenar * kenar;
}
module.exports.alan = alan;

index.js dosyamızı güncelleyelim. Son hali :

proje1/index.js
1
2
3
4
5
6
7
8
9
10
11
12
// console.log("node.js çalıştı");
var cember = require("./cember"); // cember modülünü çağır

console.log("Yarıçapı 5 olan çemberin alanı : " + cember.alan(5));

var dikdortgen = require("./lib/dikdortgen");

console.log("Eni 5 boyu 4 olan dikdörtgenin alanı : " + dikdortgen.alan(5,4));

var kare = require("kare");

console.log("Bir kenarı 6 olan karenin alanı : " + kare.alan(6));

Çıktımız şöyle olmalı.

konsol
1
2
3
Yarıçapı 5 olan çemberin alanı : 78.53981633974483
Eni 5 boyu 4 olan dikdörtgenin alanı : 20
Bir kenarı 6 olan karenin alanı : 36

kare.js dosyası aslında fazla kalabalık. İçindeki alan metoduna gerek yok. Direkt kendisini export edebiliriz. Fakat biz başka bir modülle deneme yapalım. Bunun için proje1 klasörü içinde node_modules klasörü ve içinde de elips.js dosyası oluşturalım.

proje1/node_modules/elips.js
1
2
3
4
var PI = Math.PI;
module.exports = function (a, b) {
  return PI * a * b;
}

index.js dosyamızı güncelleyelim. Son hali :

proje1/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// console.log("node.js çalıştı");
var cember = require("./cember"); // cember modülünü çağır

console.log("Yarıçapı 5 olan çemberin alanı : " + cember.alan(5));

var dikdortgen = require("./lib/dikdortgen");

console.log("Eni 5 boyu 4 olan dikdörtgenin alanı : " + dikdortgen.alan(5,4));

var kare = require("kare");

console.log("Bir kenarı 6 olan karenin alanı : " + kare.alan(6));

var elips = require("elips");

console.log("Eksenleri 5 ve 4 olan elipsin alanı : " + elips(5, 4));

Çıktımız şöyle olmalı.

konsol
1
2
3
4
Yarıçapı 5 olan çemberin alanı : 78.53981633974483
Eni 5 boyu 4 olan dikdörtgenin alanı : 20
Bir kenarı 6 olan karenin alanı : 36
Eksenleri 5 ve 4 olan elipsin alanı : 62.83185307179586

Görüldüğü üzere elips sınıfını doğrudan export ettik ve kullanırken de elips(5,4) şeklinde kullandık. Tabii bu sadece tek dönüş (return) olduğu için.

Temel Modül Yapısı

node.js ‘de modüller bir klasör içinde yer alır ve modülün açıklama dosyası package.json dosyası içinde yer alır. Hem bu şekilde daha düzenli olur ve de js dosyası modül adından bağımsız olur. Şimdi gerçek bir modül yapalım.

Bunun için proje1/node_modules klasörü içinde parabol klasörü ve içinde de index.js ile package.json dosyası oluşturalım.

proje1/node_modules/parabol/index.js
1
2
3
4
5
6
module.exports = function(a,b,c) {
  var r = - b/(2 * a);
  var k = a * r * r + b * r + c;

  return "(" + r + "," + k + ")";
}
proje1/node_modules/parabol/package.json
1
2
3
4
5
6
{
  "name": "parabol",
  "version": "0.0.1",
  "description": "Parabolün tepe noktasının koordinatlarını verir",
  "main": "index.js"
}

index.js dosyamızı güncelleyelim. Son hali :

proje1/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// console.log("node.js çalıştı");
var cember = require("./cember"); // cember modülünü çağır

console.log("Yarıçapı 5 olan çemberin alanı : " + cember.alan(5));

var dikdortgen = require("./lib/dikdortgen");

console.log("Eni 5 boyu 4 olan dikdörtgenin alanı : " + dikdortgen.alan(5,4));

var kare = require("kare");

console.log("Bir kenarı 6 olan karenin alanı : " + kare.alan(6));

var elips = require("elips");

console.log("Eksenleri 5 ve 4 olan elipsin alanı : " + elips(5, 4));

var parabol = require("parabol");

console.log("f(x)=2x^2+8x+3 şeklindeki parabolün tepe noktası : " + parabol(2, 8, 3));

Çıktımız şöyle olmalı.

konsol
1
2
3
4
5
Yarıçapı 5 olan çemberin alanı : 78.53981633974483
Eni 5 boyu 4 olan dikdörtgenin alanı : 20
Bir kenarı 6 olan karenin alanı : 36
Eksenleri 5 ve 4 olan elipsin alanı : 62.83185307179586
f(x)=2x^2+8x+3 şeklindeki parabolün tepe noktası : (-2,-5)

Kodlar

Dersimizdeki örnek kodları https://github.com/onokumus/node-ders adresinden inceleyebilirsiniz.