這篇文章的目標是幫助你們快速上手grunt,適用的grunt版本爲0.4.x,本文只是大體介紹,若是想作深刻了解請閱讀grunt官方文檔。javascript
首先確保你的node版本在0.8以上(暫時不建議適用0.10.0),命令:css
node -v
而後安裝grunt命令行工具grunt-clihtml
npm install -g grunt-cli
可能須要前面加上sudo(例如 OSX, *nix)。java
若是你只前裝過grunt的老版本的話則須要卸載:node
npm uninstall -g grunt
grunt模板的做用是幫助你生成初始的Gruntfile.js文件,固然你也能夠直接把其它項目的Gruntfile.js文件拷貝過來使用。jquery
首先要安裝命令行工具grunt-init:git
npm install -g grunt-init
而後安裝模板,目前有三種模板是由grunt官方作維護的,還有別的可在github上找到,或者你本身實現一個。 官方模板的安裝命令以下:github
git clone git://github.com/gruntjs/grunt-init-gruntfile.git $HOME/.grunt-init/ git clone git://github.com/gruntjs/grunt-init-jquery.git $HOME/.grunt-init/ git clone git://github.com/gruntjs/grunt-init-node.git $HOME/.grunt-init/
三種分別對應默認grunt模板,jquery插件的grunt模板,node包的grunt模板。web
而後就能夠適用grunt-init命令來初始化你的Gruntfile.js文件了,例如你要安裝默認模板:shell
grunt-init grunt-init-gruntfile #最後一個參數也能夠是模板所在的文件夾
它會問你一些問題,而後根據你的答案建立當前項目的Gruntfile.js文件。
首先是建立package.json文件(npm的包管理配置文件)。
你可使用npm init
命令建立這個文件或者直接拷貝其它項目的。
而後在項目的根目錄下安裝你開發依賴的各類grunt包,首先是grunt:
npm install grunt --save-dev
--save-dev
能夠將你所安裝的包自動保存到package.json文件中的devDependencies
屬性中去,若是你的項目使用時(不只僅是開發)也須要用到某個包,
你應該使用--save
將其保存在dependcies
屬性中。
你確定要用到須要其它grunt模塊來幫你完成構建任務,這時你就能夠用這種方法把他們都加到項目中,例如最經常使用的concat
jshint
uglify
模塊:
npm install grunt-contrib-concat --save-dev npm install grunt-contrib-jshint --save-dev npm install grunt-contrib-uglify --save-dev
還有種方式就是先把依賴的包寫到package.json中的devDependencies
中去,而後直接使用npm nistall
來安裝。
咱們以本站當前使用的Gruntfile.js爲例來了解一下grunt設置中最重要的部分。
var path = require('path'); var snippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet; module.exports = function(grunt) { // Project configuration. grunt.initConfig({ // Task configuration. concat: { dist: { src: ['javascripts/common.js','javascripts/respond.js'], dest: 'javascripts/main.js' } }, uglify: { options: { banner: '/*script for site: http://chemzqm.me*/' }, dist: { src: '<%= concat.dist.dest %>', dest: 'javascripts/main.min.js' } }, cssmin: { compress:{ files:{ "stylesheets/styles.min.css":["stylesheets/styles.css"] } } }, jshint: { options: { curly: true, eqeqeq: true, immed: true, latedef: true, newcap: true, noarg: true, sub: true, undef: true, unused: false, boss: true, eqnull: true, browser: true, node: true, globals: { jQuery: true } }, all: ['javascripts/common.js','Gruntfile.js'] }, regarde: { livereload: { files: ['_posts/*.md', 'javascripts/common.js', 'stylesheets/styles.css', '*.html'], tasks: ['default', 'livereload'] } }, connect: { livereload: { options: { port: 8000, middleware: function(connect, options) { return [snippet, connect.static(path.resolve(process.cwd(), '_site'))]; } } } }, bgShell:{ jekyll:{ cmd: 'jekyll' } } }); // These plugins provide necessary tasks. grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-regarde'); grunt.loadNpmTasks('grunt-bg-shell'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-livereload'); // Default task. grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'cssmin', 'bgShell:jekyll']); // start livereload server grunt.registerTask('server', ['livereload-start', 'connect', 'regarde']); };
module.exports
指向調用該模塊時將返回的對象,而當你使用grunt
命令的時候這個名爲Gruntfile.js
的文件就會被grunt
找到(0.4.0以上會找Gruntfile.js,而以前是grunt.js
,具體的找法也很簡單,就是從運行命令的目錄開始一直往上找,直到找到爲止),而後以grunt
對象爲參數執行該模塊返回的函數。
grunt.initConfig
方法接受一個Plain Object作爲參數,該對象的每一個屬性名錶明一個頂層task名字,而值則是具體的配置。配置任務時要注意不能把子任務名配置成任務要讀取的配置屬性,例如uglify須要options作爲配置屬性,這時就不能把子任務名也設置成options。若是任務是multitask
則能夠爲一個任務配置多個子任務,例如配置多個合併文件的任務:
concat: { dist: { src: ['javascripts/common.js','javascripts/respond.js'], dest: 'javascripts/main.js' }, dist2:{ src: ['javascripts/*.js'], dest:'javascripts/all.js' } },
這樣你就能夠經過grunt concat
來順序執行兩個合併任務,或者grunt concat:dist
只執行dist
任務。上面用到的任務都是multitask
,具體實踐的時候從文檔或者源碼均可以判斷。此外,grunt還支持文件名的模式匹配和模板替換的功能,例如匹配全部js文件能夠用*.js
,想引用concat:dist
任務的dist
屬性能夠用<%= concat.dist.dest %>
, 詳細的說明還請閱讀官方文檔。
grunt.loadNpmTasks
負責載入npm模塊定義的任務,grunt 0.4.0以後沒有了核心任務,因此每一個任務都須要開發者寫代碼載入(還有一個grunt.task.loadTasks
方法用來加載指定目錄task文件,具體參閱task官方文檔)。
grunt.registerTask
用來註冊新的任務,它最簡單的形式以下:
grunt.task.registerTask(taskName, taskList)
名爲taskname
的任務出發後,tasklist
數組(grunt 0.4.0以前是空格分格的字符串)中的任務將被順序執行, 比較特殊的是名爲default
的任務,它將在命令行輸入grunt
後被調用。grunt.registerTask
和grunt.registerMultiTask
還可經過傳入函數的方式建立新的任務,具體參閱建立task文檔。
最後重點介紹一下livereload模塊,這個模塊分兩個任務liveload-start
和liveload
,前一個任務啓動livereload服務,後一個任務負責通知瀏覽器進行刷新。livereload自己不提供文件的web服務,因此咱們須要connect任務插件來提供。而後經過require('grune-contrib-livereload/lib/utils').livereloadSnippet
獲取到livereload
插件提供的中間件函數(實質上就是參數爲req, res, next
的函數),而後配置到connect
的middleware
參數中,這時請求connect服務
(http://localhost:8000) 獲得的html就會被動態的加入負責與livereload
服務端通信的一段代碼。grunt-regarde
模塊負責監控文件變化(不用grunt-watch
是由於那個得到不了變化的文件名),這裏咱們根據須要配置成每當文件變化後就執行default
任務和livereload
任務。最後,配置
grunt.registerTask('server', ['livereload-start', 'connect', 'regarde']);
就能夠經過grunt server
命令同時啓用liveload, connect, 和regard服務(順序能夠任意)
grunt已經開始被愈來愈多的知名項目所使用了(例如jquery和AngularJS),並且它的任務插件也在不斷的擴展之中(例如coffeescript, jade, stylus)。雖然說相比Makefile笨拙了一些,但更容易知足團隊中各類操做系統下開發的須要