跳到主要內容
黯羽輕揚每天積累一點點

Grunt 教程

免費2015-05-22#Tool#grunt#grunt教程#grunt指南

沒多少廢話的 Grunt 教程,篇幅不長,簡單明了

寫在前面

特別注意:如果覺得本文不夠詳盡,強烈建議去看 Grunt 英文官網 的教程,因為 中文版 的對註釋做了部分翻譯,不如不翻譯(容易被翻譯誤導)

  1. Grunt 是什麼?

Grunt 是自動構建工具,類似的東西還有 Ant、Buildy、Gmake 等等,更多的信息請查看 [黯羽輕揚:JS 自動化](/articles/js 自動化/)

  1. Grunt 有什麼用?

自動構建工具能把自動化工具整合起來,以任務的形式管理,所以 Grunt 官網的副標題是 The JavaScript Task Runner。

簡單解釋一下,構建項目 -> 模塊化開發 -> 復用 -> 測試 -> 調試 -> 驗證 -> 發布 -> 版本控制,這整個流程中需要用很多自動化工具,比如 Require、QUnit、JSHint、Uglify 等等。幾乎每次修改源碼都需要手動把某些工具按特定的順序 run again。。。

有了 Grunt 這樣的自動構建工具後就可以簡化 run again 的操作,寫好配置文件之後用命令行運行自定義任務即可,甚至可以配合 grunt-contrib-watch 插件監聽文件修改,自動運行任務

  1. Grunt 哪裡好?
  • 火:Twitter、JQuery、Adobe、Mozilla 等等都在用 Grunt

  • 插件多:目前(2015.5.22)已經有 4560 個 Grunt 插件了,包括常用的 JSHint、Require、Sass 等等,大大地夠用,實在不行還可以自己寫插件

  • 好用:配置文件比較簡單,插件文檔齊全(npm 官網提供統一管理)

一.安裝 grunt

  1. 安裝 NodeJS

Windows 直接去http://nodejs.org/下載安裝包就好了,自帶 npm

其它平台的 安裝教程

裝好之後命令行輸入 node -v 測試一下

  1. 安裝 npm

命令行輸入 npm -v 測試一下,如果出錯的話,自己想辦法去裝 npm

  1. 安裝 Grunt-CLI(命令行工具 Command Line Interface)

命令行輸入 npm install -g grunt-cli 等待安裝完成即可

二.配置文件

需要兩個配置文件:

  • package.json:用於 Nodejs 包管理,聲明項目依賴模塊(grunt 以及 grunt 插件)

  • Gruntfile.js:Grunt 配置文件,用來定義任務,可以叫 Gruntfile.js 或者 Gruntfile.coffee

注意:package.json 和 Gruntfile.js 都要放在項目的根目錄下,與項目的源代碼一起提交

說白了,學 Grunt 就是學怎麼寫配置文件

三.package.json

一般格式如下:

{
    "name": "項目名稱",
    "version": "項目版本號",
    "description": "項目描述",
    "author": "項目創建者",
    "license": "項目版權",
    "devDependencies": {
        // 項目依賴插件
    }
}

例如一個小項目的 package.json:

{
  "name": "world",
  "version": "0.4.0",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-contrib-jshint": "~0.6.3",
    "grunt-contrib-uglify": "~0.2.2",
    "grunt-contrib-watch": "^0.6.1"
  }
}

寫好 package.json 後,命令行 cd 進來,執行 npm install,下載剛才聲明的各個依賴項,會被放在當前目錄下的 node_modules 文件夾里

需要添加依賴項的時候直接 npm install grunt-contrib-XXX --save-dev 就可以了,能夠自動更新 package.json 的內容

注意

  1. 不能有註釋,否則 npm install 解析失敗(無論是哪種形式的註釋,無論放在文件首尾部分還是其它。。都不行)

  2. version 必須是 X.X.X 形式,X.X 報錯

其實 version 的格式有複雜的標準,請查看http://semver.org/

  1. 命令行輸入 npm install grunt-contrib-XXX --save-dev 這樣的命令可以自動更新 package.json

最後一個依賴模塊 grunt-contrib-watch 就是這樣添進去的

  1. 版本號前面的~和^是什麼意思?

沒看到有資料解釋這個,但我們可以猜:^表示會去找最新版本,而表示指定版本(和 git 的 HEAD^ 與 HEADn 可能一樣。。當然,只是猜測)

一般都用~指定具體版本,因為可能存在插件兼容性以及穩定性問題

P.S.如果知道靠譜的解釋的話請告訴我,謝謝

  1. 自動生成 package.json

命令行輸入 npm init 根據命令行提示一步一步完成,實測不好用,建議手寫,或者寫一份常用的模版,強行復用

三.Gruntfile.js

一般格式如下:

module.exports = function(grunt){
    // 1.  定義任務
    grunt.initConfig({
        // 1.  讀取 package.json
        pkg: grunt.file.readJSON('package.json'),

        // 2.  初始化各個任務的配置對象
        task1: {
            options: {
                // 設置配置選項
            },
            
            build: {
                // 設置輸入輸出路徑等等
            }
        },
        task2: {
            // ...
        }
    });

    // 2.  加載插件
    grunt.loadNpmTasks('Grunt 插件名');

    // 3.  註冊任務
    grunt.registerTask('default',['Grunt 任務']);
    grunt.registerTask('mytask',['task1', 'task3']);
};

例如一個小項目的 package.json:

module.exports = function(grunt) {
    
    // 1.  定義任務
    grunt.initConfig({
        // 1.  讀取 package.json
        pkg: grunt.file.readJSON("package.json"),
        
        // 2.  初始化各個任務的配置對象
        // 合併文件
        concat: {
            options: {
                // 防止合併出錯(上一個文件尾部少了分號)
                separator: ";",
                // 頂部信息(需要自帶註釋格式,不自動註釋,也不自動換行)
                banner: "/*<%= pkg.name %>_<%= pkg.version %> " +
                        // *注意*:yyyy-mm-dd 要加引號,表示字符串參數
                        "<%= grunt.template.today('yyyy-mm-dd') %>*/\r\n\r\n",
                // 底部信息
                footer: "\r\n\r\n/* author: http://ayqy.net/ */"
            },
            
            build: {
                src: ["src/w.js", "src/Const.js", "src/Item.js", "src/Map.js", "src/Util.js", "src/Core.js"],
                dest: "build/<%= pkg.name %>.js"
            }
        },
        // 代碼檢查
        jshint: {
            options: {
                eqeqeq: true,   // 要求===
                trailing: true, // 要求尾部無空格
                //unused: true,   // 要求警告沒用到的變量(模塊化代碼會報錯)
                forin: true,    // 要求 for-in 必須有 hasOwnProp 過濾
                curly: true     // 要求花括號
            },
            
            files: ["Gruntfile.js", "src/*.js"]
        },
        // 代碼瘦身
        uglify: {
            options: {
                // 不混淆變量名
                mangle: false,
                // 輸出壓縮率,可選的值有 false(不輸出信息),gzip
                report: "min",
                // 頂部信息(需要自帶註釋格式,不自動註釋,也不自動換行)
                banner: "/*<%= pkg.name %>_<%= pkg.version %> " +
                        "<%= grunt.template.today('yyyy-mm-dd') %>*/\r\n\r\n",
                // 底部信息
                footer: "\r\n\r\n/* author: http://ayqy.net/ */"
            },
            
            build: {
                files: {
                    // <%= concat.dist.dest %>表示 uglify 會自動瘦身 concat 任務中生成的文件
                    "build/<%= pkg.name %>.min.js": ["<%= concat.build.dest %>"]
                }
            }
        },
        // 監聽文件變動,自動執行任務
        watch: {
            files: ["<%= jshint.files %>"],
            tasks: ["default"]
        }
    });
    
    // 2.  加載插件
    grunt.loadNpmTasks("grunt-contrib-concat");
    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-watch");
    
    // 3.  註冊任務
    grunt.registerTask("default", ["jshint", "concat", "uglify"]);  // 默認任務
    grunt.registerTask("check", ["jshint"]);    // 自定義任務:代碼檢查
};

寫好 Gruntfile.js 後不需要執行 num install 之類的命令,直接用 grunt TaskName 執行對應的任務即可,比如:grunt 執行 default 任務,grunt jshint 執行代碼檢查,grunt mytask 按順序執行一連串的任務等等

如果有多個 target 的話可以用 grunt TaskName*:(英文半角冒號)*TargetName 執行指定的 target,在註冊任務的時候也可以用 TaskName:TargetName 指定 target

P.S.至於 target 是什麼,請往下看,配置 Gruntfile.js 可能有點麻煩,不過好在只用配置一次,以後直接用就可以了,可能對某些細節還不太理解,請務必看完下面的注意部分

注意

  1. dist 和 build 到底用哪個?

常見的有 options-dist 和 options-build 兩種,都可以用,因為名字無所謂

只有 options 是有所謂的,比如我們可以這樣搞:

    concat: {
        options: {
            separator: ";"
        },
        
        xx: {
            src: "src/*.js",
            dest: "<%= pkg.name %>.js"
        }
    }
    

當然還可以這樣搞:

    concat: {
        options: {
            separator: ";"
        },
        
        xx: {
            src: "src/*.js",
            dest: "<%= pkg.name %>.js"
        },
        
        xxx: {
            src: "src/*.js",
            dest: "<%= pkg.name %>.js"
        }
    }
    

然後執行 grunt concat,會依次執行 xx 和 xxx,所以如果只有一個 target(xx 和 xxx 都叫 target)的話,用 build 和 dist 沒什麼區別,因為不需要語義區分

如果有多個 target,最好取一些語義友好的名字

P.S.個人更傾向於 build,當然,名字不重要,所以某些教程里甚至出現了 bar、foo 之類的,讓人費解

  1. 關於 options

上面的例子說明 grunt 只認 options(注意:少 1 個 s 都不行喲~),名字不是 options 的都一律當作 target 來執行

前面例子里都是 target 級的 options,其實也可以有 task 級的 options,可以對 task 下所有的 target 起作用,當然,不知道這個也沒關係,多寫點代碼而已

  1. 註冊同名任務會造成死遞歸

    grunt.registerTask("concat", ["concat"]);
    
  2. 可以給任務取別名

    grunt.registerTask("check", ["jshint"]);    // 自定義任務:代碼檢查
    
  3. 更多的例子

如果需要更多的例子幫助理解,建議自己寫個小項目,慢慢測試

如果實在沒多少時間,請查看 博客園:grunt 使用小記之 uglify:最全的 uglify 使用 DEMO

四.在線資源

  1. 不知道哪個插件能滿足需求,穩定,好用

http://www.gruntjs.net/plugins

鏈接頁面給出了 30 天內下載量 top100 的插件,附有功能簡介、最後更新時間等等,點擊即可跳轉至對應的 npm 官網插件主頁。此外還支持搜索,非常方便

  1. 不知道 XX 插件有哪些配置選項

https://www.npmjs.com/

鏈接頁面是 npm 官網,在搜索框里填插件名即可,例如 grunt-contrib-watch

插件主頁提供了詳細的配置說明以及例子,比如 watch 的配置選項:

最簡單的用法:

    watch: {
        files: ['**/*'],
        tasks: ['jshint']
    }
    

或者複雜的:

    watch: {
        sass: {
            // We watch and compile sass files as normal but don't live reload here 
            files: ['src/sass/*.sass'],
            tasks: ['sass']
        },
        livereload: {
            // Here we watch the files the sass task will compile to 
            // These files are sent to the live reload server after sass compiles to them 
            options: { livereload: true },
            files: ['dest/**/*']
        }
    }
    

3. Grunt API

http://gruntjs.com/api/grunt

鏈接頁面有 Grunt 的所有 API,比如 grunt.log、grunt.initConfig 等等等等,看到新東西就去查吧

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論