Bootstrap’i Grunt ile kullanma

Bilmeyenler için kısa açıklamalarla başlamak istedim.

Bootstrap, linkte de inceleyebileceğiniz gibi Twitter geliştiricileri tarafından yaratılan bir front-end framework.

Grunt ise resmi açıklaması ile bir “JavaScript task runner”. Yani sizin front-end geliştirmeleriniz sırasında düzenli olarak yapmak zorunda olduğunuz işlemleri arkaplanda otomatik olarak yapan bir araç, diyebiliriz.

Şimdi Bootstrap ile Grunt birleşimini nerede ve nasıl kullanmamız gerekebilir, bundan bahsedelim.

E-ticaret sitesi, emlak sitesi, haber sitesi gibi geniş kapsamlı ve fazlaca kod yazılacak bir proje geliştirdiğinizi düşünelim.

Birincisi, artık CSS size çok uzun ve vakit kaybı olarak geliyor ve bu yüzden SASS veya LESS kullanarak CSS kodlarınızı yazmak istiyorsunuz.
Kodlarınızı yazarken aynı anda arkaplanda bu SASS, LESS kodlarınızı compile edip CSS’e çevirecek bir araca ihtiyacınız olacak.

İkincisi, parçalara ayrılmış olan CSS ve JavaScript kodlarınızı birleştirmek ve minify edip tek bir dosya haline getirmek isteyeceksiniz.

Üçüncüsü de siz proje üzerinde çalışırken, örneğin bir butonun rengini değiştirdiğinizde tüm bu işlemlerin arkaplanda tıkır tıkır işlemesi gerekecek.

(Bu ihtiyaç listesi çok daha fazla uzayabilir tabi şimdilik temel ihtiyaç gibi düşünebilirsiniz 🙂

Ve işte tüm bunları yapacak isim karşımızda: Grunt

grunt-logo

Şimdi birlikte arkaplanda Grunt’ın çalıştığı bir Bootstrap projesi oluşturalım. (Yazının sonunda projenin download linkini de bulacaksınız)

Grunt, Node.js üzerinde çalıştığı için, öncelikle Node’u indirip kurmanız gerekiyor. Bu linkten kurulumu yapabilirsiniz.

Command prompt veya terminalinize aşağıdaki node -v komutunu yazdığınızda hata almayıp Node’un versiyon numarasını görüyorsanız, Node.js’i sorunsuz yüklemişsiniz demektir.

aykan.burcak at aykanburcak in ~
$ node -v
v0.12.0

Grunt arayüzünü kurmak için de aşağıdaki komutu çalıştırın.

npm install -g grunt-cli

Şimdi sıra projenize Grunt’ı kurmaya geldi.

Öncelikle projenizin dizinine, yine Terminal veya Command Prompt kullanarak gidin.

aykan.burcak at aykanburcak in ~
$ cd htdocs/bootstrap-grunt-pack

aykan.burcak at aykanburcak in ~/htdocs/bootstrap-grunt-pack
$

Projenizin dizinindeyken aşağıdaki komutu çalıştırın.

npm init

Bu komutu yazdıktan sonra projenizin içinde package.json dosyası oluşacak ve bu dosyayı doldurmak için komutu yazdıktan sonra çıkan adımları doldurmanız gerekiyor.

Doldurduktan sonra şöyle bir görüntüyle karşılaşmanız gerekiyor. Enter’a bastıktan sonra package.json dosyanız hazır demektir.

aykan.burcak at aykanburcak in ~/htdocs/bootstrap-grunt-pack
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (bootstrap-grunt-pack)
version: (1.0.0)
description: Bootstrap Grunt Project
entry point: (index.js)
test command:
git repository: https://github.com/aykanburcak/Bootstrap-Grunt-Package.git
keywords: bootstrap, grunt, sass
author: Aykan Burçak
license: (ISC)
About to write to /Users/aykan.burcak/htdocs/bootstrap-grunt-pack/package.json:

{
  "name": "bootstrap-grunt-pack",
  "version": "1.0.0",
  "description": "Bootstrap Grunt Project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/aykanburcak/Bootstrap-Grunt-Package.git"
  },
  "keywords": [
    "bootstrap",
    "grunt",
    "sass"
  ],
  "author": "Aykan Burçak",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/aykanburcak/Bootstrap-Grunt-Package/issues"
  },
  "homepage": "https://github.com/aykanburcak/Bootstrap-Grunt-Package"
}


Is this ok? (yes)

Burada benden farklı olarak girmeniz gereken tek bölüm git repository’si… Eğer oluşturmak isterseniz kendi Git repository’nizi oluşturup linkini sorulan adımda yazabilirsiniz.


 

Şimdi sıra kullanacağımız modülleri eklemeye geldi. Grunt ile ihtiyacımız olan işlemleri yapabilmemiz için bu işlemleri yapan modülleri projemize kurmamız gerekiyor.

Şimdi o işlemleri yapalım. İhtiyacımız olan modüller ve işlevleri şöyle:

  • “grunt-contrib-concat”: Dosyaları birleştirmek ve tek bir dosya oluşturmak
  • “grunt-contrib-uglify”: JavaScript dosyalarının minify edilmesi
  • “grunt-contrib-watch”: Dosyalardaki anlık değişiklilerin izlenmesi ve bazı işlemlerin bu değişikliklerin ardından tekrar yapılması
  • “grunt-contrib-sass”: SASS dosyalarının compile edilip CSS’e çevrilmesi
  • “grunt-contrib-cssmin”: CSS dosyalarının minify edilmesi

Şimdi bu modülleri kurmak için sırasıyla aşağıdaki komutları çalıştıralım.

npm install grunt --save-dev
npm install grunt-contrib-concat --save-dev
npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-watch --save-dev
npm install grunt-contrib-sass --save-dev
npm install grunt-contrib-cssmin --save-dev

Eğer komutların çalışması sırasında hata alırsanız büyük ihtimalle yetki sorunu yaşıyorsunuz demektir. Aynı komutları başlarına sudo yazarak tekrar deneyin.

Package.json dosyanıza aşağıdaki bölüm eklendiyse, modülleri sorunsuz yüklemişsiniz demektir.

"devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "^0.5.1",
    "grunt-contrib-cssmin": "^0.12.3",
    "grunt-contrib-sass": "^0.9.2",
    "grunt-contrib-uglify": "^0.9.1",
    "grunt-contrib-watch": "^0.6.1"
  }

Şimdi Bootstrap’in sayfasından SASS dosyalarını indiriyoruz. Şu sayfada “Download SASS” butonunu göreceksiniz. Tıklayıp indirin.

Sıkıştırılmış dosyanın içinden çıkan “assets” klasörünü kopyaların ve projenize ekleyin. Bu klasörün içinde parçalanmış halde, Bootstrap içindeki tüm componentlerin .scss ve .js dosyalarını bulacaksınız. Yazının başında anlattığım gibi, Grunt kullanarak bu dosyaları birleştirecek, minify edecek ve compile edeceğiz.

Bu arada indirdiğimiz klasörlerde parçalı js ve scss dosyalarının birleştirilmiş halleri de bulunuyor. Bunları grunt ile yapacağımız için silmemiz gerekiyor.

Assets klasörünüzün içindeki javascripts ve stylesheets klasörünüzün içi şu şekilde olmalı. Burada görmediğiniz dosyaları silin.

Screen Shot 2015-06-25 at 10.48.00

Screen Shot 2015-06-25 at 10.48.12

Şimdi grunt konfigürasyonlarımızı yapacağımız dosyamızı oluşturmaya geldi sıra. Projenizin içinde gruntfile.js isimli bir dosya yaratın.

Aşağıdaki kodu dosyanızın içine yapıştırın. Boş alanları sırasıyla dolduracağız.

module.exports = function (grunt) {
    'use strict';

    grunt.initConfig({
        //Open the package.json
        pkg: grunt.file.readJSON('package.json'),

        //The Concat Task
        concat: {

        },

        //Task for js Minification
        uglify: {

        },

        //Task for change tracker
        watch:{

        },

        //Sass compiler
        sass: {

        },

        // Minify CSS
        cssmin: {

        }
    });
};

Concat Modülü

Şimdi öncelikle concat modülü için ayarlarımızı yapalım.

//The Concat Task
        concat: {
            dist: {
                options: {
                    separator: '\n\r',
                    banner: '/*\nConcatinated JS file \n' +
                            'Author: Aykan Burçak \n' +
                            'Created Date: <%= grunt.template.today("yyyy-mm-dd") %>' +
                            '\n */ \n'
                },
                // select the files to concatenate
                src: ['assets/**/*.js'],
                // the resulting JS file
                dest: 'assets/project.js'
            }
        },

Gördüğünüz gibi modülün içinde bazı parametreler var. Örneğin banner parametresi birleştirilen dosyanın en tepesine otomatik olarak yazılan açıklama kısmının şablonu. Bu bölümü istediğiniz şekilde düzenleyebilirsiniz. Kendi adınızı, web sitenizin url’ini yazabilirsiniz.

src alanına görmüş olduğunuz gibi js dosyalarımızın path’ini yazıyoruz. Yani Grunt’a assets klasörünün içinde gördüğün tüm js dosyaları ile çalış, diyoruz.

dest kısmı da oluşturulacak olan birleştirilmiş dosyanın adresi…  Ben dosyanın adını project.js yaptım. Siz kendi pojenize göre bunu özelleştirebilirsiniz.

Bu ayarları tamamladıktan sonra aşağıdaki komutu çalıştırın.

grunt concat

Aşağıdaki uyarıyı aldığınızda, assets dizininizde project.js dosyanız oluşacaktır.

$ grunt concat
Running "concat:dist" (concat) task
File assets/project.js created.

Done, without errors.

Uglify Modülü

Şimdi diğer taskımız olan uglify’ı ekleyelim.

//Task for js Minification
        uglify: {
            options: {
                //  banner for inserting at the top of the result
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
            },
            build: {
                src: ['assets/project.js'],
                dest: 'assets/project.min.js'
            }
        },

Bu task da project.js dosyasını alıyor ve minify edip project.min.js adıyla yeni bir dosya kaydediyor.

$ grunt uglify
Running "uglify:build" (uglify) task
>> 1 file created.

Done, without errors.

SASS Modülü

assets/stylesheets klasörünüzün içindeki _bootstrap.scss dosyasını görmüşsünüzdür. Bu dosya bir partial dosyasıdır. Yani başka bir .scss dosyasının içine çağrılabilir. Bu dosyanın içine girdiğinizde de Bootstrap’a ait diğer partial dosyalarını göreceksiniz.

İleride farklı .scss dosyaları da oluşturacağımızı düşünerek bu dosyanın adını project.scss olarak değiştirelim ve ileride oluşturacağımız yeni .scss dosyalarını da bu dosyanın içine çağırarak devam edelim.

SASS modülümüzün ayarlarını da aşağıdaki şekilde yapalım.

//Sass compiler
        sass: {
            dist: {
                options: {
                    style: 'expanded'
                },
                files: {
                    'assets/project.css': 'assets/stylesheets/project.scss'
                }
            }
        },

Bu task da gördüğünüz gibi project.scss dosyasını (ve içinde çağrılan partialları) alıp, compile edip, assets klasörünün içinde project.css adında yeni bir dosya oluşturacak.

CSSmin Modülü

CSSmin modülü için aşağıdaki kodu gruntfile.js dosyamıza ekleyerek SASS modülü tarafından oluşturulan project.css dosyasını minify edip project.min.css adıyla yeni bir dosya oluşturuyoruz.

// Minify CSS
        cssmin: {
            target: {
                files: [{
                    expand: true,
                    cwd: 'assets',
                    src: ['project.css'],
                    dest: 'assets',
                    ext: '.min.css'
                }]
            }
        },

Watch Modülü

Şu ana kadar her şey iyi hoş da, biz her yazdığımız koddan sonra ilgili modülü bulup onun komutunu mu gireceğiz dediğinizi duyar gibiyim; tabiki hayır…
Watch modülünü aşağıdaki şekilde yazıyoruz ve bu modülün .scss dosyalarında değişiklik yaptığımızda sass ve cssmin; .js dosyalarında değişiklik yaptığımızda ise concat ve uglify tasklarını çalıştırmasını istiyoruz.

//Task for change tracker
        watch:{
            scripts: {
                files: ['assets/javascripts/**/*.js'],
                tasks: ['concat','uglify']
            },
            styles: {
                files: ['assets/stylesheets/**/*.scss'],
                tasks: ['sass','cssmin']
            }
        }

Son olarak yapmamız gereken 2 iş kaldı.

Gerekli eklentileri yüklemek ve grunt komutuyla çalışacak olan default task’ı belirlemek

//The Required Plug-Ins which will be loaded for Task
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    //The array of default tasks
    grunt.registerTask('default', ['concat', 'uglify','sass','cssmin','watch']);

Böylelikle çalışırken tek yapmanız gereken projenizin olduğu dizine gidip grunt komutunu 1 kez çalıştırmak.
Sonrasında kodda yaptığınız tüm değişiklikler watch taskı ile izlenecek ve diğer modüller de sonrasında üzerine düşeni yapacak.

İşte gruntfile.js dosyasının son hali:

module.exports = function (grunt) {
    'use strict';

    grunt.initConfig({
        //Open the package.json
        pkg: grunt.file.readJSON('package.json'),

        //The Concat Task
        concat: {
            dist: {
                options: {
                    separator: '\n\r',
                    banner: '/*\nConcatinated JS file \n' +
                            'Author: Aykan Burçak \n' +
                            'Created Date: <%= grunt.template.today("yyyy-mm-dd") %>' +
                            '\n */ \n'
                },
                // select the files to concatenate
                src: ['assets/**/*.js'],
                // the resulting JS file
                dest: 'assets/project.js'
            }
        },

        //Task for js Minification
        uglify: {
            options: {
                //  banner for inserting at the top of the result
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
            },
            build: {
                src: ['assets/project.js'],
                dest: 'assets/project.min.js'
            }
        },

        //Sass compiler
        sass: {
            dist: {
                options: {
                    style: 'expanded'
                },
                files: {
                    'assets/project.css': 'assets/stylesheets/project.scss'
                }
            }
        },

        // Minify CSS
        cssmin: {
            target: {
                files: [{
                    expand: true,
                    cwd: 'assets',
                    src: ['project.css'],
                    dest: 'assets',
                    ext: '.min.css'
                }]
            }
        },

        //Task for change tracker
        watch:{
            scripts: {
                files: ['assets/javascripts/**/*.js'],
                tasks: ['concat','uglify']
            },
            styles: {
                files: ['assets/stylesheets/**/*.scss'],
                tasks: ['sass','cssmin']
            }
        }
    });

    //The Required Plug-Ins which will be loaded for Task
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-cssmin');

    //The array of default tasks
    grunt.registerTask('default', ['concat', 'uglify','sass','cssmin','watch']);
};

Projenin son halini de buradan indirebilirsiniz.