快速上手grunt
此文的目標(biāo)是幫助快速上手grunt,適用的grunt版本為0.4.x,本文只是大致介紹,如果想做深入了解請閱讀grunt官方文檔。
安裝grunt命令行工具
首先確保你的node版本在0.8以上(暫時不建議適用0.10.0),命令:
node -v
然后安裝grunt命令行工具grunt-cli
npm install -g grunt-cli
可能需要前面加上sudo(例如 OSX, *nix)。
如果你只前裝過grunt的老版本的話則需要卸載:
npm uninstall -g grunt
安裝grunt模板
grunt模板的作用是幫助你生成初始的Gruntfile.js文件,當(dāng)然你也可以直接把其它項目的Gruntfile.js文件拷貝過來使用。
首先要安裝命令行工具grunt-init:
npm install -g grunt-init
然后安裝模板,目前有三種模板是由grunt官方做維護(hù)的,還有別的可在github上找到,或者你自己實現(xiàn)一個。
官方模板的安裝命令如下:
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/三種分別對應(yīng)默認(rèn)grunt模板,jquery插件的grunt模板,node包的grunt模板。
然后就可以適用grunt-init命令來初始化你的Gruntfile.js文件了,例如你要安裝默認(rèn)模板:
grunt-init grunt-init-gruntfile #最后一個參數(shù)也可以是模板所在的文件夾
它會問你一些問題,然后根據(jù)你的答案創(chuàng)建當(dāng)前項目的Gruntfile.js文件。
新的grunt project-scaffolding
新的grunt在0.4版本后,添加了project-scaffolding
安裝所需node包
首先是創(chuàng)建package.json文件(npm的包管理配置文件)。
你可以使用npm init命令創(chuàng)建這個文件或者直接拷貝其它項目的。
然后在項目的根目錄下安裝你開發(fā)依賴的各種grunt包,首先是grunt:
npm install grunt --save-dev
–save-dev可以將你所安裝的包自動保存到package.json文件中的devDependencies屬性中去,如果你的項目使用時(不僅僅是開發(fā))也需要用到某個包,
你應(yīng)該使用–save將其保存在dependcies屬性中。
你肯定要用到需要其它grunt模塊來幫你完成構(gòu)建任務(wù),這時你就可以用這種方法把他們都加到項目中,例如最常用的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
install來安裝。
我們以本站當(dāng)前使用的Gruntfile.js為例來了解一下grunt設(shè)置中最重要的部分。
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 servergrunt.registerTask('server', ['livereload-start', 'connect', 'regarde']);};- module.exports指向調(diào)用該模塊時將返回的對象,而當(dāng)你使用grunt命令的時候這個名為Gruntfile.js的文件就會被grunt找到(0.4.0以上會找Gruntfile.js,而之前是grunt.js,具體的找法也很簡單,就是從運行命令的目錄開始一直往上找,直到找到為止),然后以grunt對象為參數(shù)執(zhí)行該模塊返回的函數(shù)。
- grunt.initConfig方法接受一個Plain Object做為參數(shù),該對象的每個屬性名代表一個頂層task名字,而值則是具體的配置。配置任務(wù)時要注意不能把子任務(wù)名配置成任務(wù)要讀取的配置屬性,例如uglify需要options做為配置屬性,這時就不能把子任務(wù)名也設(shè)置成options。如果任務(wù)是multitask則可以為一個任務(wù)配置多個子任務(wù),例如配置多個合并文件的任務(wù):
這樣你就可以通過grunt concat來順序執(zhí)行兩個合并任務(wù),或者grunt
concat:dist只執(zhí)行dist任務(wù)。上面用到的任務(wù)都是multitask,具體實踐的時候從文檔或者源碼都可以判斷。此外,grunt還支持文件名的模式匹配和模板替換的功能,例如匹配所有js文件可以用*.js,想引用concat:dist任務(wù)的dist屬性可以用<%=
concat.dist.dest %>, 詳細(xì)的說明還請閱讀官方文檔task。
grunt.loadNpmTasks負(fù)責(zé)載入npm模塊定義的任務(wù),grunt 0.4.0之后沒有了核心任務(wù),所以每個任務(wù)都需要開發(fā)者寫代碼載入(還有一個grunt.task.loadTasks方法用來加載指定目錄task文件,具體參閱官方文檔task。
grunt.registerTask用來注冊新的任務(wù),它最簡單的形式如下:
grunt.task.registerTask(taskName, taskList)
名為taskname的任務(wù)出發(fā)后,tasklist數(shù)組(grunt 0.4.0之前是空格分格的字符串)中的任務(wù)將被順序執(zhí)行, 比較特殊的是名為default的任務(wù),它將在命令行輸入grunt后被調(diào)用。grunt.registerTask和grunt.registerMultiTask還可通過傳入函數(shù)的方式創(chuàng)建新的任務(wù),具體參閱創(chuàng)建官方文檔task。
最后重點介紹一下livereload模塊,這個模塊分兩個任務(wù)liveload-start和liveload ,前一個任務(wù)啟動livereload服務(wù),后一個任務(wù)負(fù)責(zé)通知瀏覽器進(jìn)行刷新。livereload本身不提供文件的web服務(wù),所以我們需要connect任務(wù)插件來提供。然后通過require('grune-contrib-livereload/lib/utils').livereloadSnippet獲取到livereload插件提供的中間件函數(shù)(實質(zhì)上就是參數(shù)為req,
res, next的函數(shù)),然后配置到connect的middleware參數(shù)中,這時請求connect服務(wù)
(http://localhost:8000) 得到的html就會被動態(tài)的加入負(fù)責(zé)與livereload服務(wù)端通訊的一段代碼。grunt-regarde模塊負(fù)責(zé)監(jiān)控文件變化(不用grunt-watch是因為那個獲得不了變化的文件名),這里我們根據(jù)需要配置成每當(dāng)文件變化后就執(zhí)行default任務(wù)和livereload任務(wù)。最后,配置如下的server任務(wù)
就可以通過grunt server命令同時啟用livereload, connect, 和regarde服務(wù)(順序可以任意)
grunt已經(jīng)開始被越來越多的知名項目所使用了(例如jquery和AngularJS),而且它的任務(wù)插件也在不斷的擴展之中(例如coffeescript, jade, stylus)。雖說相比Makefile笨拙了一些,但更容易滿足團隊中各種操作系統(tǒng)下開發(fā)的需要。
總結(jié)
- 上一篇: 分析师:因库克运营能力强悍 苹果公司不会
- 下一篇: js模块化之模块依赖处理