Grunt 是近期很熱門的 Node.js 開發工具,
根據官方網頁的說法,
他是 JavaScript Task Runner,
柯南雖然看過了一些文章與介紹,
但一直沒有花太多時間,
試試看到底怎麼使用,
趁著新年假期,
我稍微試了一下之後工作流程可能會用到的 Grunt 與 其 套件 (plugin),
並記錄下來,
算是另類的新年禮物給自己跟需要範例的朋友。
安裝 Grunt
> npm install -g grunt-cli //安裝 grunt 前要安裝 Node.js 最低版本要求要大於 0.8
建立 Node.js Project
> mkdir grunt101 // grunt101 是 project name > cd grunt101 > npm init
安裝 grunt 套件
grunt 的套件目前約有 二千多個,我試了以下幾個
> npm install grunt --save-dev > npm install grunt-contrib-less --save-dev > npm install grunt-contrib-jshint --save-dev > npm install grunt-contrib-watch --save-dev > npm install grunt-nodemon --save-dev > npm install grunt-concurrent --save-dev > npm install grunt-shell --save-dev
package.json
以上的指令不僅會幫我們在專案下安裝 grunt 套件,也會在 package.json 產生對應設定
{
"name": "grunt-test",
"version": "0.0.1",
"description": "grunt test",
"dependencies": {
"mojito": ">0.8"
},
"devDependencies": {
"grunt": "0.4.2",
"grunt-contrib-less": "0.9.0",
"grunt-contrib-watch": "0.5.3",
"grunt-contrib-jshint": "~0.8.0"
"grunt-nodemon": "0.2.0",
"grunt-concurrent": "0.4.3",
"grunt-shell": "~0.6.4",
}
}
Grunt.js
Gruntfile.js 或 Gruntfile.coffee 是在專案目錄同一層的設定檔案,我們可以透過這個檔案設定 Grunt 要跑的 task 與 plugin。
目前我測試的完整 Gruntfile 如下:
/*jslint unparam:true */
'use strict';
var path = require('path');
module.exports = function (grunt) {
grunt.initConfig({
pkg: require('./package.json'),
less: {
development: {
options: {
compress: true
},
files: [{
expand: true, // Enable dynamic expansion.
cwd: 'less/',
dest: 'assets/',
src: ['**/*.less'], // Actual pattern(s) to match.
//flatten: true,
ext: '.css', // Dest filepaths will have this extension.
rename: function (dest, matchedSrcPath, options) {
return path.join(dest, matchedSrcPath.replace('les2', 'module/1'));
}
}]
}
},
nodemon: {
dev: {
script: 'server.js'
}
},
concurrent: {
target: {
tasks: ['less', 'jshint:myFile' ,'watch', 'nodemon'],
options: {
logConcurrentOutput: true
}
}
},
watch: {
styles: {
// Which files to watch (all .less files recursively in the less directory)
files: ['**/*.less'],
tasks: ['less'],
options: {
nospawn: true,
livereload: true
}
},
jshint: {
files: ['mojits/**/*.js'],
tasks: ['jshint:myFile']
}
},
shell: {
pkgname: {
options: {
stdout: true
},
command: 'echo <%= pkg.name %>'
},
ll: {
options: {
stdout: true
},
command: 'ls -al'
},
},
jshint: {
options: {
},
myFile: ['mojits/**/*.js']
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['concurrent']);
grunt.registerTask('ll', ['shell:ll']);
grunt.registerTask('pkg', ['shell:pkgname']);
};
執行
基本上在專案的根目錄執行
> grunt
就可以執行
grunt 會去執行 一個叫 default 的 task
grunt.registerTask('default', ['concurrent']);不過我們也可以自己寫其它的 task 在 gruntfile,例如:
grunt.registerTask('ll', ['shell']);如此一來,我們就可以下
grunt ll
來執行
grunt.registerTask('ll', ['shell']);
中對應的 shell 設定內容
取得其它檔案中的設定值
如果我們想要取得其它檔案(例如 package.json) 的設定值,可以用
pkg: require('./package.json'),
接著用
<%= pkg.name %>
就可以使用package.json 中 name 這個 key 的 value
grunt-contrib-less
這個外掛,可以幫助我們將 less 產生成 css,透過 files 這個 屬性,我們也可以指定 less 的來源與 css 的目的位置。
grunt-contrib-watch
watch 可以幫我們監視專案中的檔案,並在其變動後,執行設定的 task。
watch: {
styles: {
files: ['**/*.less'],
tasks: ['less'],
options: {
nospawn: true,
livereload: true
}
},
jshint: {
files: ['mojits/**/*.js'],
tasks: ['jshint:myFile']
}
},
例如,當 less 檔改變時,自動產生 css 檔,js 更新時,跑一下 jshint。
此外,watch 最神奇的地方是 live reload,一但設為 true,只要在 chrome 安裝 Livereload 的外掛
就可以邊改檔案(如less),然後瀏覽器自動反應修改後的狀態,我們不用再重新整理一次瀏覽器。
grunt-concurrent
這可以讓我們同一個task 執行好多子 grunt task
concurrent: {
target: {
tasks: ['less', 'jshint:myFile' ,'watch', 'nodemon'],
options: {
logConcurrentOutput: true
}
}
},
像上面設定,我們就執行了 less, jshint, watch, nodemon 這些子 task
grunt-nodemon
這個外掛,當我們改變了被監視的檔案,就會幫我們重新啟動程式。
grunt-shell
顧名思義,就是可以執行 os 的 shell 指令
grunt-contrib-jshint
grunt 也可以幫我們執行 jshint 檢查 js 有沒有錯誤。
所有的 外掛,要用 loadNpmTasks 來載入
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-nodemon');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt 實在是很有趣的一個開發工具,這個年假花了一些時間研究,真的一點都不浪費假期呢!
PS: 懶得打 code 的朋友,本文測試的 grunt project 放在 https://github.com/ddsakura/grunt101

留言列表