Özgür Özer

Junior full stack developer

Gulp.js ile Otomasyon

Gulp; geliştirme ortamımızdaki tüm işlerimizi otomatik bir şekilde yapabilmemizi sağlayan, JavaScript ile yazılmış, açık kaynak bir araçtır.

Gulp.js ile otomasyon

Bölümler

  1. Gulp Kurulumu ve İlk Görev
  2. Gulp API’ları
  3. Örnek Proje

1. Gulp Kurulumu ve İlk Görev

Gulp kullanmaya başlayabilmek için sistemimizde Node.js ve npm‘in kurulu olması gerekmektedir.

Terminalden proje klasörümüze geçiyoruz ve npm i ile Gulp’ı kuruyoruz.

# Projemizin olduğu klasöre geçiyoruz
$ cd proje/

# Gulp'ı projemize lokal olarak kuruyoruz
$ npm i gulp

Projemizin ana dizinine gulpfile.js isminde, Gulp komutlarını yazacağımız dosyayı oluşturuyoruz ve içine aşağıdakileri yapıştırıp kaydediyoruz.

/* Gulp modülünü yüklüyoruz */
var gulp = require('gulp')

/* Görevimizi tanımlıyoruz */
gulp.task('gorev', function () {
  /* Görev çalıştırıldığında ekrana mesaj yazdırıyoruz */
  console.log('görev çalışıyor!')
})

Terminalden gulp gorev komutunu çalıştırdıktan sonra aşağıdaki gibi bir çıktı almış olmamız gerekiyor.

[14:59:08] Using gulpfile ~/Desktop/proje/gulpfile.js
[14:59:08] Starting 'gorev'...
görev çalışıyor!
[14:59:08] Finished 'gorev' after 119 μs

İlk görevimizi başarıyla çalıştırdık. Şimdi Gulp API’larını tanıyalım.

2. Gulp API’ları

Gulp yazarken kullanacağımız ve kullanabileceğimiz 4 API var. Bunlar: gulp.src, gulp.dest, gulp.task, gulp.watch.

gulp.src

Bu API belirlediğimiz dosyaları üzerlerinde istediğimiz işlemleri yapabilmek üzere stream olarak geri döndürür. Dosyalarımızı glob desenleri kullanarak tanımlayabiliriz.

Örneğin;

/* belirli bir dosyayı, */
gulp.src('dev/css/style.scss')
/* belirli dosyaları, */
gulp.src(['dev/css/style.scss', 'dev/css/reset.scss'])

/* belirli bir uzantıya sahip tüm dosyaları, */
gulp.src('dev/css/*.scss')
/* belirli bir dosya haricindeki belirli bir uzantıya sahip tüm dosyaları, */
gulp.src(['dev/css/*.scss', '!dev/css/variables.scss'])
/* veya tüm alt klasörler içindeki belirli bir uzantıya sahip tüm dosyaları */
gulp.src('dev/**/*.scss')

glob kullanarak tanımlayabiliriz. Daha fazla desene şuradan ulaşabiliriz.

gulp.dest

Bu API üzerinde işlemler yaptığımız dosyaları belirlediğimiz konumlara yeniden oluşturmak için kullanılır. Verdiğimiz konumdaki klasörler dizinde yoksa otomatik olarak oluşturulur.

Aşağıdaki görevi çalıştırdığımızda dev/css/style.scss dosyası prod/css/ klasörü içine aynı isimde yeniden oluşturulur.

gulp.task('gorev', function () {
  gulp.src('dev/css/style.scss')
    .pipe(gulp.dest('prod/css/'))
})

gulp.task

Bu API görev tanımı için kullanılır. Görevleri Orchestrator syntax’inde tanımlamamız gerekir.

gulp.task('gorev1', function () {
  /* yapılacaklar */
})
gulp.task('gorev2', function () {
  /* yapılacaklar */
})

Gulp tüm görevleri aynı anda çalıştırır. Eğer bir görevin çalışabilmesi için farklı bir görevin veya görevlerin tamamlanması gerekiyorsa, task() fonksiyonuna dizi olarak ikinci bir parametre eklememiz gerekir.

Aşağıdaki gibi bir senaryoda gulp gorev3 deyip üçüncü görevi çalıştırmak istediğimizde, Gulp ilk iki görevi çalıştırdıktan sonra üçüncü görevi çalıştırır.

gulp.task('gorev1', function () {
  /* yapılacaklar */
})
gulp.task('gorev2', function () {
  /* yapılacaklar */
})
gulp.task('gorev3', ['gorev1', 'gorev2'], function () {
  /* yapılacaklar */
})

Görevleri gulp gorevAdi şeklinde çalıştırabileceğimiz gibi sadece gulp komutuyla da çalıştırabiliriz. Bunun için default isminde bir görev oluşturup, bir önceki örnekte olduğu gibi ikinci parametre olarak çalışmasını istediğimiz görevleri dizi şeklinde tanımlamamız gerekir.

gulp.task('gorev1', function () {
  /* yapılacaklar */
})
gulp.task('gorev2', function () {
  /* yapılacaklar */
})
gulp.task('gorev3', function () {
  /* yapılacaklar */
})
gulp.task('default', ['gorev1', 'gorev2', 'gorev3'])

Artık sadece gulp diyerek belirlediğimiz görevleri aynı anda çalıştırabiliriz.

gulp.watch

Bu API belirlediğimiz dosyaları dinleyerek, dosya değişimleri sonrasında istediğimiz görevleri çalıştırabilmemiz için kullanılır.

watch isminde bir görev oluşturuyoruz ve dev/css/ içindeki tüm .scss dosyalarını gerçek zamanlı dinlemeye başlıyoruz. Artık herhangi bir .scss dosyasının içeriğini güncellediğimizde gorev isimli görev otomatik olarak çalıştırılacak.

gulp.task('gorev', function () {
  /* yapılacaklar */
})
gulp.task('watch', function () {
  gulp.watch('dev/css/*.scss', ['gorev'])
})
gulp.task('default', ['watch'])

3. Örnek Proje

CSS için SCSS, HTML için Pug ve JavaScript için CoffeeScript preprocessor‘larıyla çalıştığımızı varsayalım. .scss, .pug ve .coffee uzantılı dosyaları compile ve minify edip, source map dosyalarını hazırlamak, ayrıca görüntü dosyalarımızı sıkıştırmak istiyoruz.

Klasör yapımızı aşağıdaki gibi hayal edelim. dev klasöründe çalışacağız ve tüm çıktılar prod klasörüne gidecek.

proje/
├── dev/
│   ├── css/
│   │   └── style.scss
│   ├── html/
│   │   └── index.pug
│   ├── img/
│   │   ├── 1.gif
│   │   ├── 2.jpg
│   │   └── 1.png
│   └── js/
│       └── init.coffee
├── prod/
│   ├── css/
│   │   ├── style.min.css
│   │   └── style.min.css.map
│   ├── img/
│   │   ├── 1.gif
│   │   ├── 2.jpg
│   │   └── 1.png
│   ├── js/
│   │   ├── init.min.js
│   │   └── init.min.js.map
│   └── index.html
├── gulpfile.js
└── package.json

package.json dosyasına aşağıdakileri yapıştırıyoruz ve terminalden npm install komutunu çalıştırarak gerekli modülleri proje klasörümüze lokal olarak kuruyoruz.

{
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-coffee": "^2.3.4",
    "gulp-imagemin": "^3.3.0",
    "gulp-plumber": "^1.1.0",
    "gulp-pug": "^3.3.0",
    "gulp-rename": "^1.2.2",
    "gulp-sass": "^3.1.0",
    "gulp-server-livereload": "^1.9.2",
    "gulp-sourcemaps": "^2.6.1",
    "gulp-uglify": "^3.0.0"
  }
}

gulpfile.js dosyamızın içeriğini üretiyoruz.

/* Gulp modülünü yüklüyoruz */
var gulp = require('gulp')
/* Watch modunda çalışırken hata oluştuğunda Gulp'ın otomatik olarak kapanmasını engelleme modülünü yüklüyoruz */
var plumber = require('gulp-plumber')
/* CSS ve JS dosyaları için source map oluşturma modülünü yüklüyoruz */
var sourcemaps = require('gulp-sourcemaps')
/* SCSS dosyalarını compile etme modülünü yüklüyoruz */
var sass = require('gulp-sass')
/* Dosya ismi değiştirme modülünü yüklüyoruz */
var rename = require('gulp-rename')
/* Pug dosyalarını compile etme modülünü yüklüyoruz */
var pug = require('gulp-pug')
/* Görüntü dosyalarını sıkıştırma modülünü yüklüyoruz */
var imagemin = require('gulp-imagemin')
/* CoffeeScript dosyalarını compile etme modülünü yüklüyoruz */
var coffee = require('gulp-coffee')
/* JS dosyalarını sıkıştırma modülünü yüklüyoruz */
var uglify = require('gulp-uglify')
/* Sunucu oluşturma ve dosya değişimlerinde tarayıcıya yenileme komutu gönderme modülünü yüklüyoruz */
var server = require('gulp-server-livereload')

/* Hangi dosyaları dinleyeceğimizi ve çıktılarının hangi klasörlere gideceğini belirliyoruz */
var yol = {
  scss: { kaynak: 'dev/css/*.scss', hedef: 'prod/css/' },
  pug: { kaynak: 'dev/html/*.pug', hedef: 'prod/' },
  img: { kaynak: 'dev/img/*.{gif,jpg,jpeg,png,svg}', hedef: 'prod/img/' },
  coffee: { kaynak: 'dev/js/*.coffee', hedef: 'prod/js/' }
}

/* SCSS dosyalarını compile ve minify edip, source map'lerini oluşturma görevini tanımlıyoruz */
gulp.task('scss', function () {
  /* SCSS dosyalarının yolunu gösteriyoruz */
  gulp.src(yol.scss.kaynak)
    /* Hata oluştuğunda Gulp'ın otomatik olarak kendisini kapatmasını engelliyoruz */
    .pipe(plumber())
    /* Source map oluşturma zincirini başlatıyoruz */
    .pipe(sourcemaps.init())
      /* SCSS dosyalarını compile ve minify edip, CSS dosyaları üretiyoruz */
      .pipe(sass({ outputStyle: 'compressed' }))
      /* CSS dosyalarının uzantılarını değiştiriyoruz */
      .pipe(rename({ extname: '.min.css' }))
    /* Source map dosyalarını kaydediyoruz */
    .pipe(sourcemaps.write('.'))
    /* CSS dosyalarını kaydediyoruz */
    .pipe(gulp.dest(yol.scss.hedef))
})

/* Pug dosyalarını compile etme görevini tanımlıyoruz */
gulp.task('pug', function () {
  /* Pug dosyalarının yolunu gösteriyoruz */
  gulp.src(yol.pug.kaynak)
    /* Hata oluştuğunda Gulp'ın otomatik olarak kendisini kapatmasını engelliyoruz */
    .pipe(plumber())
    /* Pug dosyalarını compile edip, HTML dosyaları üretiyoruz */
    .pipe(pug())
    /* HTML dosyalarını kaydediyoruz */
    .pipe(gulp.dest(yol.pug.hedef))
})

/* Görüntü dosyalarını sıkıştırma görevini tanımlıyoruz */
gulp.task('img', function () {
  /* Görüntü dosyalarının yolunu gösteriyoruz */
  gulp.src(yol.img.kaynak)
    /* Hata oluştuğunda Gulp'ın otomatik olarak kendisini kapatmasını engelliyoruz */
    .pipe(plumber())
    /* Görüntü dosyalarını sıkıştırıyoruz */
    .pipe(imagemin({ optimizationLevel: 5 }))
    /* Görüntü dosyalarını kaydediyoruz */
    .pipe(gulp.dest(yol.img.hedef))
})

/* CoffeeScript dosyalarını compile ve minify edip, source map'lerini oluşturma görevini tanımlıyoruz */
gulp.task('coffee', function () {
  /* CoffeeScript dosyalarının yolunu gösteriyoruz */
  gulp.src(yol.coffee.kaynak)
    /* Hata oluştuğunda Gulp'ın otomatik olarak kendisini kapatmasını engelliyoruz */
    .pipe(plumber())
    /* Source map oluşturma zincirini başlatıyoruz */
    .pipe(sourcemaps.init())
      /* CoffeeScript dosyalarını compile edip, JS dosyaları üretiyoruz */
      .pipe(coffee())
      /* JS dosyalarını sıkıştırıyoruz */
      .pipe(uglify())
      /* JS dosyalarının uzantılarını değiştiriyoruz */
      .pipe(rename({ extname: '.min.js' }))
    /* Source map dosyalarını kaydediyoruz */
    .pipe(sourcemaps.write('.'))
    /* JS dosyalarını kaydediyoruz */
    .pipe(gulp.dest(yol.coffee.hedef))
})

/* Dosyaları gerçek zamanlı dinleme görevini tanımlıyoruz */
gulp.task('watch', function () {
  /* SCSS dosyalarını dinleyip, değişimleri sonrasında `scss` görevini çalıştırıyoruz */
  gulp.watch(yol.scss.kaynak, ['scss'])
  /* Pug dosyalarını dinleyip, değişimleri sonrasında `pug` görevini çalıştırıyoruz */
  gulp.watch(yol.pug.kaynak, ['pug'])
  /* Görüntü dosyalarını dinleyip, değişimleri sonrasında `img` görevini çalıştırıyoruz */
  gulp.watch(yol.img.kaynak, ['img'])
  /* CoffeeScript dosyalarını dinleyip, değişimleri sonrasında `coffee` görevini çalıştırıyoruz */
  gulp.watch(yol.coffee.kaynak, ['coffee'])
})

/* Sunucu oluşturma görevini tanımlıyoruz */
gulp.task('server', function () {
  /* Sunucunun çalışacağı kaynak klasörün yolunu gösteriyoruz */
  gulp.src('prod')
    /* Hata oluştuğunda Gulp'ın otomatik olarak kendisini kapatmasını engelliyoruz */
    .pipe(plumber())
    /* Sunucuyu çalıştırıyoruz */
    .pipe(server({
      open: true,
      port: 9471,
      livereload: true,
      defaultFile: 'index.html'
    }))
})

/* Terminalden `gulp` dediğimizde çalışacak görevleri belirliyoruz */
gulp.task('default', ['scss', 'pug', 'img', 'coffee', 'watch', 'server'])

Terminalden gulp komutunu çalıştırdığımızda aşağıdaki gibi bir ekran alıyoruz.

[12:47:48] Using gulpfile ~/Desktop/proje/gulpfile.js
[12:47:48] Starting 'scss'...
[12:47:48] Finished 'scss' after 8.57 ms
[12:47:48] Starting 'pug'...
[12:47:48] Finished 'pug' after 1.4 ms
[12:47:48] Starting 'img'...
[12:47:48] Finished 'img' after 1.86 ms
[12:47:48] Starting 'coffee'...
[12:47:48] Finished 'coffee' after 980 μs
[12:47:48] Starting 'watch'...
[12:47:48] Finished 'watch' after 8.86 ms
[12:47:48] Starting 'server'...
[12:47:48] Finished 'server' after 18 ms
[12:47:48] Starting 'default'...
[12:47:48] Finished 'default' after 16 μs
[12:47:48] Webserver started at http://localhost:9471
[12:47:48] Livereload client connected
[12:47:48] gulp-imagemin: Minified 6 images (saved 4.19 MB - 10.7%)

SCSS, Pug ve CoffeeScript dosyalarımız compile/minify edildi ve source map dosyalarımız oluşturuldu; görüntü dosyalarımız sıkıştırıldı; sunucumuz belirlediğimiz port’ta çalışmaya başladı ve open: true ile http://localhost:9471 adresi tarayıcımızda otomatik olarak çalıştırıldı. Artık kod yazarken dosyalarımızı her kaydedişimizde Gulp bizim yerimize tüm işleri halledip tarayıcıyı otomatik olarak yenileyecek.

Gulp ile yapılabileceklerin sınırı yok. Şuradan 3.000’den fazla Gulp eklentisine ulaşabilir, şuradan da kendi eklentimizi nasıl yazabileceğimizi öğrenebiliriz.