原文链接:http://www.hulufei.com/post/grunt-introduction

安装


  • 如果之前有装过grunt,卸载之

    npm uninstall -g grunt
  • 安装grunt运行工具

    npm install -g grunt-cli
  • 一个grunt项目需要两个文件:package.json和Gruntfile.js,前者用于nodejs包管理,比如grunt插件安装,后者是grunt配置文件,配置任务或者自定义任务。
    1. 先生成一个package.json文件,在grunt项目的目录下运行npm install就可以生成一个空的package.json。
    2. 安装grunt到当前目录:npm install grunt --save-dev
    3. 再生成一个Gruntfile.js的模板文件,这时候可以用grunt-init,或者直接手写一个:
    module.exports = function(grunt) {
    grunt.initConfig({
    // 任务配置
    });
    // 加载插件
    grunt.loadNpmTasks('grunt-contrib-uglify');
    // 默认的任务
    grunt.registerTask('default', ['uglify']);
    });

关于插件


grunt利用不同的插件完成不同的任务,比如用uglifyJS压缩js对应的插件就是grunt-contrib-uglify。

使用插件(以grunt-contrib-uglify为例):

  1. 在grunt项目目录下安装对应的插件 npm install grunt-contrib-uglify --save-dev
  2. 在 Gruntfile.js 中加载插件 grunt.loadNpmTasks('grunt-contrib-uglify')
  3. 在 Gruntfile.js 中配置对应的插件任务,指定要压缩的js文件
  • 这里可以看到可用的插件,基本上大部分你能想到或没想到的任务都能找到对应的插件,需要做什么就装什么。
  • 以后如果要重用一个grunt项目的配置,只需要有package.json和Gruntfile.js这两个文件,然后npm install即可安装所有依赖的插件。
  • 一个插件就是对应一个任务,一般来说,所有插件都会遵循下面将要说到的任务配置规则,很多插件的文档都不会很详细,所以你只能根据插件提供的示例套用这些规则看有没有更多配置的可能性。

关于任务


任务分为两种:"Basic" Tasks和"Multi" Tasks

  1. Multi-tasks有所谓的target(目标目录),比如下面的concat任务有foo和bar两个targets,而uglify任务有一个叫bar的target

        grunt.initConfig({
    concat: {
    foo: {
    // 合并任务 foo 目标选项和文件转到此处。
    },
    bar: {
    // 合并任务 bar 目标选项和文件转到此处。
    }
    },
    uglify: {
    bar: {
    // 混淆任务 bar 目标选项和文件转到此处
    }
    }
    });

    target的名字可以任意指定,因为target只是为了用特定配置运行指定的任务,比如grunt concat:foo或者grunt concat:bar会分别运行foo或者bar指定的concat任务。如果只运行grunt concat将会遍历所有concat下的targets按顺序运行。

    但是任务的名称比如concat和uglify是固定的,由对应的插件指定,在插件的使用文档里面都会有说明。

    每个multi task都必须有至少一个target.

  2. 不需要配置的任务就是Basic Task,你可以这样来定义一个Basic Task,grunt.registerTask(taskName, [description, ] taskFunction)

    // foo task
    grunt.register('foo', function(a, b) {
    // do something
    });

    这样运行:grunt foo,或者grunt foo:a:b,a和b就是传递给foo的参数

模板变量

grunt可以通过类似<%= k.sub.k %>这种格式插入配置的其他属性值

Options

在一个任务配置里面,option属性可以用来覆盖默认的配置,另外,每个target都可以有自己的option属性。target的option优先级高于task的。options是可选的。

grunt.initConfig({
concat: {
options: {
// Task-level options may go here, overriding task defaults.
},
foo: {
options: {
// 'foo' target options may go here, overriding task-level options.
},
},
bar: {
// No options specified; this target will use task-level
options.
},
},
});

不一定所有的任务都会有option的。

指定文件

这应该是刚接触grunt时最让人不知所措的地方了,想想这么多插件,每个插件都需要指定对应要应用到的文件,但是咋一看好像每个插件都有一套自己配置文件的方式,配置方式看上去很随意,所以总是会觉得有一丝不靠谱。

就像之前提到的,其实是有一套通用的规则的:

Grunt提供了几种不同的格式定义src-dest形式的文件映射。任何multi-task都支持这几种格式。

文件映射可以有3种格式:Compact Format, Files Object Format和File Array Format, 其中"Compact"和"File Array"这两种形式提供了一些额外的属性可用:

  • filter 过滤,接受fs.Stats方法定义的名字,比如isFile, isDirectory,或者自定义函数接受一个源文件名做为参数,返回true or false
  • nonull Retain src patterns even if they fail to match files. Combined with grunt's --verbose flag, this option can help debug file path issues.
  • matchBase Patterns without slashes will match just the basename part.
  • ......(剩下几个看文档吧)
  • 另外还有一个动态文件列表生成(批量匹配文件)

以下示例中的属性名srcdest, files都是固定的key名,一开始就不必纠结了。

Compact Format

这种形式只允许单个src-dest映射在一个target里面,只有src属性是必须的,可以没有dest,这种形式一般用在只读的task,比如jshint

```javascript
grunt.initConfig({
jshint: {
foo: {
src: ['src/aa.js', 'src/aaa.js']
},
},
concat: {
bar: {
src: ['src/bb.js', 'src/bbb.js'],
dest: 'dest/b.js',
},
},
});
```

Files Object Format

这种形式支持指定多个src-dest对应多个target,属性名(key)是要输出的目标文件名,value值是源文件列表。不支持额外的属性

```javascript
grunt.initConfig({
concat: {
foo: {
files: {
'dest/a.js': ['src/aa.js', 'src/aaa.js'],
'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'],
},
},
bar: {
files: {
'dest/b.js': ['src/bb.js', 'src/bbb.js'],
'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'],
},
},
},
});
```

Files Array Format

同上,只是支持额外的属性

```javascript
grunt.initConfig({
concat: {
foo: {
files: [
{src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'},
{src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'},
],
},
bar: {
files: [
{src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true},
{src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'},
],
},
},
});
```

通配符支持

由nodejs内置的node-glob库支持,这些都可以用在上面所说的各种文件配置中

  • *匹配任何字符,除了/
  • ?匹配单个字符,除了/
  • **匹配任何字符,包括/,所以用在目录路径里面
  • {}逗号分割的“或”操作(逗号后面不要有空格)
  • ! 排除某个匹配
// You can specify single files:
{src: 'foo/this.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 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'}

动态生成文件名

  • expand 设置为true打开以下选项
  • cwd 所有src指定的文件相对于这个属性指定的路径
  • src 要匹配的路径,相对与cwd
  • dest 生成的目标路径前缀
  • ext 替换所有生成的目标文件后缀为这个属性
  • flatten 删除所有生成的dest的路径部分
  • rename 一个函数,接受匹配到的文件名,和匹配的目标位置,返回一个新的目标路径
grunt.initConfig({
minify: {
dynamic_mappings: {
// Grunt will search for "**/?.js" under "lib/" when the "minify" task runs
files: [
{
expand: true, // Enable dynamic expansion.
cwd: 'lib/' // Src matches are relative to this path.
src: ['**/?.js'], // Actual pattern(s) to match.
dest: 'build/', // Destination path prefix.
ext: '.min.js', // Dest filepaths will have this extension.
}
]
}
}
});

自定义任务


获取/设置配置(模板变量)

  • 可以读取json配置文件:config: grunt.file.readJSON('config.json')
  • 获取json对象的属性:grunt.config('config.key.subkey')
  • 对应的模板变量:'<%= config.key.subkey %>'
  • 设置配置段:grunt.config('config', 'value')

动态更改任务配置,循环执行某个任务

grunt的任务都会放入一个队列顺序执行,但是队列本身是异步执行的,所以下面的这种做法是不会如预期输出:

grunt.registerTask('demo', function() {
for (var i = 0; i < 5; i++) {
grunt.task.run('t');
}
// 期望执行完5次`t`任务之后打印输出
// 实际上会立即输出,在`t`任务开始之前
console.log('run after t');
// 执行5次`t`任务之后才会执行这个`final`任务
grunt.task.run('final');
});

动态更改任务配置可以利用模板变量来做,由于如上所说的异步,所以不能直接在循环中给模板变量赋值,而是要额外做一个任务来接受配置:

// 假如有这样的一个配置
t: {
target: 'some <%= param %>'
}
// 在这个demo任务中需要多次调用t任务,每次都要设置param
grunt.registerTask('demo', function() {
for (var i = 0; i < 5; i++) {
// 要一个额外任务去更改配置
grunt.task.run('t_wrapper:' + i);
}
});
// 更改`t`配置并运行
grunt.register('t_wrapper', function(i) {
grunt.config('param', i);
grunt.task.run('t');
});

还有一种方法可以克隆一个新的target,然后直接更改这个cloned target的配置

grunt.config和grunt.option的区别

grunt.config如上所述可以用来动态更改模板变量,但是grunt.option不能这样,如果在配置中直接使用grunt.option,则option在运行时就已经确定了,不能再更改,假设这样配置:

t: {
target: 'some ' + grunt.option('param')
}
```javascript 运行`grunt t --param=0`,则target对应就是`'some 0'`,不能再通过`grunt.option(param, 1)`这样来更改配置
`grunt.option`和`grunt.config`都可以用来在任务之间共享一些信息,但`option`更多用来接受额外的任务参数。
###设置输出文字颜色
直接在字符串后面点一个颜色:`grunt.log('test color'.green)`
##参考 ---
* Grunt API
* gruntjs
* workflow-vips 假如你已经熟悉了Grunt,可以去看看Yeoman,也许能为你提供更多灵感。

Grunt上手指南<转>的更多相关文章

  1. Grunt上手指南(转)

    Grunt ,  javascript 我想先花点时间回忆一下作为一个前端需要做的工作(Loading...) JS合并 JS压缩 CSS压缩 CSS Sprite 图片优化 测试 静态资源缓存(版本 ...

  2. Rancher 快速上手指南操作(1)

    Rancher 快速上手指南操作(1)该指南知道用户如何快速的部署Rancher Server 管理容器.前提是假设你的机器已经安装好docker了.1 确认 docker 的版本,下面是 ubunt ...

  3. X下轻量级桌面WindowMaker上手指南

    layout: post title: 轻量级桌面WindowMaker上手指南 tags: x11, cygwin, raspi --- 最近工作上需要在远程Linux上运行一个桌面(我需要跑Net ...

  4. UnityShader快速上手指南(三)

    简介 这一篇还是一些基本的shader操作:裁剪.透明和法向量的应用 (纠结了很久写不写这些,因为代码很简单,主要是些概念上的东西) 先来看下大概的效果图:(从左到右依次是裁剪,透明,加了法向量的透明 ...

  5. Windows 8 系统完全上手指南 - 非常详尽的 Win8 系统入门学习手册与使用技巧专题教程!

    每次当有新版本的操作系统发布的时候,市面上总会冒出各种从入门到精通类的学习书籍,这次最新的 Windows 8 也不例外!不过,今天给大家送上免费的大礼——<Windows 8 完全上手指南&g ...

  6. Resharper上手指南

    原文http://www.cnblogs.com/renji/archive/2007/12/11/resharper.html Resharper上手指南 我是visual studio的忠实用户, ...

  7. grunt 上手

    grunt 上手 开始上手 Grunt 和 grunt 插件都是通过 npm 安装, Node.js 包管理器管理的. Grunt 0.4.x 版本需要Node.js 版本号不低于0.8.0. 一.安 ...

  8. NewLife.XCode 上手指南2018版(二)增

    目录 NewLife.XCode 上手指南2018版(一)代码生成 NewLife.XCode 上手指南2018版(二)增 NewLife.XCode 上手指南2018版(三)查 NewLife.XC ...

  9. NewLife.XCode 上手指南2018版(一)代码生成

    目录 NewLife.XCode 上手指南2018版(一)代码生成 NewLife.XCode 上手指南2018版(二)增 NewLife.XCode 上手指南2018版(三)查 NewLife.XC ...

随机推荐

  1. sql 联合查询并更新

    update sales set sales.adminId = t.adminIdfrom (select a.adminId,a.realName from sales ,admin_admini ...

  2. POJ 2442 Sequence

    Pro. 1 给定k个有序表,取其中前n小的数字.组成一个新表,求该表? 算法: 由于  a1[1] < a1[2] < a1[3] ... <a1[n] a2[1] < a2 ...

  3. 支付宝也要上"服务号"?斗战微信继续升级

    微信着实火了一阵,特别是微信服务号,在商户和消费者之间形成闭环,O2O领先了一步,作为曾经的电商支付老大支付宝来说是一种心头之痛,迫于压力,支付宝将于5月在支付宝钱包中上线服务窗功能,同时支付宝钱包将 ...

  4. lvs之ip-tun(ip隧道)技术的学习与实践

    1.配置测试环境 修改IP windows 200.168.10.4 lvs server  ip:200.168.10.1 因为IP隧道模式只需要一个网卡  所以就停掉其他网卡 web server ...

  5. Decompiled .class file,bytecode version:51.0(Java 7) Source for 'Android API 23 Platform' not found

    今天在Android Studio中访问Java源码的时候,代码上方出现如下提示: 而且方法体中显示介样内容: throw new RuntimeException("Stub!" ...

  6. CSS clearfix

    The problem happens when a floated element is within a container box, that element does not automati ...

  7. 13.第一个只出现一次的字符[FindFirstNotRepeatingChar]

    [题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] 这道题是2006年google的一道笔试题. 看到这道题时,最直观的想法是从头开始扫描这个字符串中的 ...

  8. 桐桐的贸易--WA

    问题 A: 桐桐的贸易 时间限制: 1 Sec  内存限制: 64 MB提交: 15  解决: 2[提交][状态][讨论版] 题目描述 桐桐家在Allianceance城,好友ROBIN家在Horde ...

  9. ubuntu修改文件访问权限

    遇到“bash .....权限不够”的问题时, 从控制台进入到那个文件夹 chmod 777 * -R 全部子目录及文件权限改为 777

  10. rdesktop remember

    整个地球都知道rdesktop,有了它,我们可以从Solaris或者Linux使用Windows,当然Windows要开启Windows Terminal Service.虽然也有基于GTK+的tsc ...