Javascript command line tool GruntJS 介紹

Update: 補上一張執行後的截圖 2013.03.27
gruntlogo
GruntJS 是一套 JavaScript Task Runner,為什麼官網會這樣寫呢?網站上線之前,是不是需要經過測試,壓縮,及品質控管,這些 Task 該如何實現,在 GruntJS 還沒出現之前,大家可以透過 Linux command 的方式來達成,但是對於前端工程師而言,多學習 command line 真的是要他們的命,所以 GruntJS 解決了此問題,將所有的 Task 用 Javascript 方式設定就可以自動佈署或測試。GruntJS 的 Plugin 也非常多且完整,像是大家常用的 CoffeeScriptHandlebarsJadeJsHintLessSassCompassStylus…等都有支援。更多好用的 Plugin 可以在官網搜尋頁面上找到。

安裝方式

Grunt 可以透過 Node.js 的管理工具 npm 方式來安裝,Windows 只要到 Node.js 官網下載安裝包,直接按下一步即可安裝完畢,Linux 可以透過 NVM 方式來管理 Node.js 版本,可以參考作者之前寫的 Node Version Manager 版本管理 NVM。需要注意的是 Grunt 0.4.x 需要 Node.js >= 0.8.0 版本才可以。 如果之前已經安裝 Grunt 請先移除安裝
$ npm uninstall -g grunt
Linux 請切換到 root 使用者來安裝
$ npm install -g grunt-cli

準備新專案

在使用 Grunt 指令前,請在專案目錄內新增 package.jsonGruntfile.js 檔案 package.json: 此檔案紀錄專案 metadata 以便將來做成 npm module,另外也會記載專案內所用到 Grunt plugins 版本資訊,像是 devDependencies 設定。 Gruntfile.js: 此檔案可以用 Coffscript.coffee 撰寫,用來紀錄工作內容及相關 Plugins 載入. PS. 如果是用 Grunt 0.3.x 版本,請命名為 grunt.js

package.json

此檔案記載專案相關資訊,也包含了 GruntJS 所需要用到的 Plugins,範例如下(官網提供)
{
  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-jshint": "~0.1.1",
    "grunt-contrib-nodeunit": "~0.1.2"
  }
}
建立此檔案後,在專案目錄內,執行 npm install,會發現專案內多了 node_modules 目錄。可以將此目錄名稱加入到 .gitignore,免的不小心 commit 到伺服器。如果不想手動更改 devDependencies 資訊,其實可以透過 npm install grunt –save-dev 方式加入到 devDependencies 裡。

Gruntfile.js

可以透過 Gruntfile.coffee 或 Gruntfile.js 來產生檔案,此命名適用於 0.4.x 版本,如果是 0.3.x 版本請命名為 grunt.js。此檔案會包含底下部份
* wrapper 寫法
* 專案及任務設定
* 載入 Grunt Plugins 和任務內容
* 定義特定任務
拿官網的例子來介紹:
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Default task(s).
  grunt.registerTask('default', ['uglify']);

};
在 package.json 裡面設定安裝 grunt-contrib-uglify 套件,uglify 任務就是將 Javascript 檔案壓縮,當我們執行 grunt 指令時,Grunt 會執行預設的任務 uglify。上面有提到四點 Grunt 檔案會包含的項目,其中第一點是 wrapper 寫法,也就是上面例子內的
module.exports = function(grunt) {
  // Do grunt-related things in here
};
接著注意專案的設定,也就是底下內容
// Project configuration.
grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    build: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'build/<%= pkg.name %>.min.js'
    }
  }
});
所有的工作項目設定都會寫在 grunt.initConfig 裡面,看到第一行 grunt.file.readJSON("package.json"),將 package.json 內容讀到 pkg 變數,接著參數設定就可以使 <% %> 方式讀取。uglify 工作項目內的 options 設定可以直接參考 grunt-contrib-uglify,我們可以定義多個 target 來區分多個工作內容,範例如下
// Project configuration.
grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    build: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'build/<%= pkg.name %>.min.js'
    },
    my_target_1: {
      options: {
        sourceMap: 'path/to/source-map.js'
      },
      files: {
        'dest/output.min.js': ['src/input.js']
      }
    },
    my_target_2: {
      options: {
        sourceMap: 'path/to/source-map.js',
        sourceMapRoot: 'http://example.com/path/to/src/',
        sourceMapIn: 'example/coffeescript-sourcemap.js'
      },
      files: {
        'dest/output.min.js': ['src/input.js']
      }
    }
  }
});
完成基本 Grunt Plugin 設定,接著將此 Plugin 載入
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
最後定義預設的任務
// Default task(s).
grunt.registerTask('default', ['uglify']);
Grunt 設定檔就完成了,可以來進行測試,我們可以直接下 grunt 指令,系統會自動跑預設任務,也就是 uglify,也或者如果有多個任務時,你只想執行 uglify 任務,請將指令改成 grunt uglify,如果是想要執行 uglify 任務內的 my_target_2 項目呢?請直接下 grunt uglify:my_target_2。 基本介紹到這裡,大家對於 Grunt.js 應該都有基本的瞭解。最後補張執行後的圖
GruntJS