文章梗概如下:
- 如何讓Grunt在項目跑起來
- 初識:Gruntfile.js
- 術語掃盲:task & target
- 如何運行任務
- 任務配置
- 自定義任務
- 文件通配符:glob模式
- 文件通配符:例子
- 常用API
- 如何初始化Gruntfile.js
- 通過模板初始化Gruntfile.js
- 獲取命令行參數
- 插件編寫
入門簡介:http://www.cnblogs.com/chyingp/p/what-is-grunt.html
如何讓Grunt在項目跑起來
搞定下面三點,就可以愉快地使用grunt了。
- 安裝grunt-cli:globally,命令行工具,所有項目共用
- 安裝grunt:locally,每個項目單獨安裝
- 項目根目錄下配置文件:Gruntfile.js
初識:Gruntfile.js
module.exports = function(grunt) { // 任務配置 grunt.initConfig({ concat: { // concat任務 foo: { // 一個任務可以包含多個子任務(官方術語叫做targetsample) src: ['a.js', 'b.js'], dest: 'ab.js' } } }); // 配置任務 grunt.loadNpmTasks('grunt-contrib-concat'); };
剩下的事情:
grunt concat
術語掃盲:task & target
task就是任務,target就是子任務。一個任務可以包含多個子任務。如下所示
grunt.initConfig({ concat: { // task foo: { // target src: ['a.js', 'b.js'], dest: 'ab.js' }, foo2: { src: ['c.js', 'd.js'], dest: 'cd.js' } } });
如何運行任務
首先需要配置任務,比如壓縮文件
grunt.initConfig({ uglify: { src: 'main.js' } });
然后運行任務
grunt uglify
任務配置
grunt里絕大多數都是文件操作,所以任務配置這一塊會重點講。簡單舉個例子,我們要將a.js
、b.js
合並成ab.js
,該怎么做呢。
有四種配置方式
- Compact Formate
- Files Object(不推薦)
- Files Array
- Older Formats(不推薦,已廢棄)
Compact Formate
特點:
- 每個target只支持一個
src-dest
- 支持除了
src
、dest
之外的參數concat: { foo: { src: ['a.js', 'b.js'], dest: 'ab.js' } }
File Object
特點:
- 每個target支持多個
src-dest
- 不支持除了
src
、dest
之外的參數concat: { foo: { files: { 'ab.js': ['a.js', 'b.js'] } } }
File Array
特點:
- 每個target支持多個
src-dest
- 支持除了
src
、dest
之外的參數concat: { foo: { files: [{ src: ['a.js', 'b.js'], dest: 'ab.js' }] } }
中級配置
下面配置的意思:將src
目錄下的所有swf
文件拷貝到dest
目錄下,並且與原來的目錄結構保持一致。
例子:src/flash/upload.swf
- dest/upload.swf
copy: {
dist:{
files: [{
expand:true, // 設置為true,表示要支持cwd等更多配置 cwd: 'src/flash', // 所有的源文件路徑,都是相對於cwd src:'**/*.swf', // 表示sr/flashc目錄下的所有swf文件,這里用了通配符 dest: 'dist' // 目標路徑 }] },
自定義任務
如果現有插件不能滿足你的需求,自己寫一個插件又太麻煩,可以考慮自定義任務
// 自定義任務 grunt.registerTask('hello', function(name){ console.log('hello ' + name); });
然后,運行任務
grunt hello:casper
輸出:
hello casper
文件通配符:glob模式
*
匹配任意多個字符,除了/
?
匹配除了/
之外的單個字符**
匹配任意多個字符,包括/
{}
匹配用逗號分割的or
列表!
用在模式的開通,表示取反
// You can specify single files: {src: 'foo/this.js', dest: ...} // Or arrays of files: {src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...} // Or you can generalize with a glob pattern: {src: 'foo/th*.js', dest: ...} // This single node-glob pattern: {src: 'foo/{a,b}*.js', dest: ...} // Could also be written like this: {src: ['foo/a*.js', 'foo/b*.js'], dest: ...} // All .js files, in foo/, in alpha order: {src: ['foo/*.js'], dest: ...} // Here, bar.js is first, followed by the remaining files, in alpha order: {src: ['foo/bar.js', 'foo/*.js'], dest: ...} // All files except for bar.js, in alpha order: {src: ['foo/*.js', '!foo/bar.js'], dest: ...} // All files in alpha order, but with bar.js at the end. {src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...} // Templates may be used in filepaths or glob patterns: {src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'} // But they may also reference file lists defined elsewhere in the config: {src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}
常用API
常用API:文件
文件操作
grunt.file.read(filepath [, options]) // 讀文件 grunt.file.readJSON(filepath [, options]) // 讀文件:json grunt.file.write(filepath, contents [, options]) // 寫文件 grunt.file.copy(srcpath, destpath [, options]) // 拷貝文件 grunt.file.delete(filepath [, options]) // 刪除文件
目錄操作
grunt.file.mkdir(dirpath [, mode]) // 創建 grunt.file.recurse(rootdir, callback) // 遍歷
文件類型
grunt.file.exists(path1 [, path2 [, ...]]) // 指定的路徑是否存在 grunt.file.isDir(path1 [, path2 [, ...]]) // 指定的路徑是否目錄 grunt.file.isFile(path1 [, path2 [, ...]]) // 指定的路徑是否文件
路徑
grunt.file.isPathAbsolute(path1 [, path2 [, ...]]) // 是否絕對路徑 grunt.file.arePathsEquivalent(path1 [, path2 [, ...]]) // 是否等價路徑 grunt.file.doesPathContain(ancestorPath, descendantPath1 [, descendantPath2 [, ...]]) // 后面的路徑是否都是ancestorPath的子路徑
API:日志
grunt.log.write(msg) grunt.log.writeln(msg) grunt.log.error([msg]) // 打印日志,並中斷執行 grunt.log.errorlns(msg) grunt.log.debug(msg) // 只有加了--debug參數才會打印日志
API:任務
主要有以下幾個
grunt.task.loadNpmTasks(pluginName) // 加載grunt插件 grunt.task.registerTask(taskName, description, taskFunction) // 注冊任務 || 給一系列任務指定快捷方式 grunt.task.run(taskList) // 代碼內部運行任務 grunt.task.loadTasks(tasksPath) // 加載外部任 grunt.task.registerMultiTask(taskName, description, taskFunction) // 注冊插件
定義任務
// 自定義任務 grunt.registerTask('hello', function(name){ console.log('hello ' + name); });
指定別名
指定默認task(運行grunt
任務時,如沒有指定任務名,默認運行grunt default
)
grunt.registerTask('default', ['concat']);
給一系列的任務指定別名
grunt.registerTask('dist', ['clean', 'concat', 'uglify']);
初始化Gruntfile.js
- 簡單拷貝:簡單粗暴有效
- 通過模板初始化:(推薦)
通過模板初始化Gruntfile.js
首先,你本地要確保安裝了grunt-init
,然后將 Gruntfile.js模板 下載到指定目錄。具體目錄參考這里。然后就很簡單了
grunt-init gruntfile
回答幾個簡單問題
Please answer the following:
[?] Is the DOM involved in ANY way? (Y/n) n
[?] Will files be concatenated or minified? (Y/n) y
[?] Will you have a package.json file? (Y/n) y
[?] Do you need to make any changes to the above before continuing? (y/N) n
Gruntfile.js生成了!
-rw-r--r-- 1 root staff 2.0K 6 20 00:52 Gruntfile.js -rw-r--r-- 1 root staff 287B 6 20 00:52 package.json
常用tips
獲取命令行參數
比如運行了如下命令,怎么獲取jshint
參數的值呢
grunt dist --jshint=true
很簡單
grunt.option('jshint');
插件編寫
@todo