Grunt上手指南<转>
原文链接: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配置文件,配置任务或者自定义任务。
- 先生成一个package.json文件,在grunt项目的目录下运行npm install就可以生成一个空的package.json。
- 安装grunt到当前目录:npm install grunt --save-dev
- 再生成一个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为例):
- 在grunt项目目录下安装对应的插件
npm install grunt-contrib-uglify --save-dev - 在 Gruntfile.js 中加载插件
grunt.loadNpmTasks('grunt-contrib-uglify') - 在 Gruntfile.js 中配置对应的插件任务,指定要压缩的js文件
- 在这里可以看到可用的插件,基本上大部分你能想到或没想到的任务都能找到对应的插件,需要做什么就装什么。
- 以后如果要重用一个grunt项目的配置,只需要有package.json和Gruntfile.js这两个文件,然后npm install即可安装所有依赖的插件。
- 一个插件就是对应一个任务,一般来说,所有插件都会遵循下面将要说到的任务配置规则,很多插件的文档都不会很详细,所以你只能根据插件提供的示例套用这些规则看有没有更多配置的可能性。
关于任务
任务分为两种:"Basic" Tasks和"Multi" Tasks
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.不需要配置的任务就是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,或者自定义函数接受一个源文件名做为参数,返回trueorfalsenonullRetain src patterns even if they fail to match files. Combined with grunt's --verbose flag, this option can help debug file path issues.matchBasePatterns without slashes will match just the basename part.- ......(剩下几个看文档吧)
- 另外还有一个动态文件列表生成(批量匹配文件)
以下示例中的属性名src和dest, 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上手指南<转>的更多相关文章
- Grunt上手指南(转)
Grunt , javascript 我想先花点时间回忆一下作为一个前端需要做的工作(Loading...) JS合并 JS压缩 CSS压缩 CSS Sprite 图片优化 测试 静态资源缓存(版本 ...
- Rancher 快速上手指南操作(1)
Rancher 快速上手指南操作(1)该指南知道用户如何快速的部署Rancher Server 管理容器.前提是假设你的机器已经安装好docker了.1 确认 docker 的版本,下面是 ubunt ...
- X下轻量级桌面WindowMaker上手指南
layout: post title: 轻量级桌面WindowMaker上手指南 tags: x11, cygwin, raspi --- 最近工作上需要在远程Linux上运行一个桌面(我需要跑Net ...
- UnityShader快速上手指南(三)
简介 这一篇还是一些基本的shader操作:裁剪.透明和法向量的应用 (纠结了很久写不写这些,因为代码很简单,主要是些概念上的东西) 先来看下大概的效果图:(从左到右依次是裁剪,透明,加了法向量的透明 ...
- Windows 8 系统完全上手指南 - 非常详尽的 Win8 系统入门学习手册与使用技巧专题教程!
每次当有新版本的操作系统发布的时候,市面上总会冒出各种从入门到精通类的学习书籍,这次最新的 Windows 8 也不例外!不过,今天给大家送上免费的大礼——<Windows 8 完全上手指南&g ...
- Resharper上手指南
原文http://www.cnblogs.com/renji/archive/2007/12/11/resharper.html Resharper上手指南 我是visual studio的忠实用户, ...
- grunt 上手
grunt 上手 开始上手 Grunt 和 grunt 插件都是通过 npm 安装, Node.js 包管理器管理的. Grunt 0.4.x 版本需要Node.js 版本号不低于0.8.0. 一.安 ...
- NewLife.XCode 上手指南2018版(二)增
目录 NewLife.XCode 上手指南2018版(一)代码生成 NewLife.XCode 上手指南2018版(二)增 NewLife.XCode 上手指南2018版(三)查 NewLife.XC ...
- NewLife.XCode 上手指南2018版(一)代码生成
目录 NewLife.XCode 上手指南2018版(一)代码生成 NewLife.XCode 上手指南2018版(二)增 NewLife.XCode 上手指南2018版(三)查 NewLife.XC ...
随机推荐
- l来自wentao:项目加入缓存(redis),实时调试时用 -----可视化缓存,flushdb
下文来自segmentfault,网站:一个交流网站:https://segmentfault.com/ 在做一个项目时如果加入缓存(例如redis),我如何进行实时调试呢? 缓存 高并发 架构 gz ...
- [原] Android持续优化 - 提高流畅度
一.形象的感官一下流畅度概念 1. 这是官方给出的概念:Android流畅运行,需要运行60帧/秒, 则需要每帧的处理时间不超过16ms. 2. 每秒帧数,实际上就是指动画或视频每秒放映的画面数.因此 ...
- 安卓(Android)手机如何安装APK?
我大天朝的安卓手机只能在一个被阉割的APP市场里玩耍,有些APP可能需要直接安装APK文件.APK 是 Android Package (安卓安装包)安卓手机如何安装APK呢? 在电脑上下载安装APK ...
- Mysql跨平台(Windows,Linux,Mac)使用与安装
MySQL其实是一个跨平台的轻量级数据库,平时开发会用到很多.有写程序可能要跨平台开发,接下来我就介绍一下如何跨平台使用Mysql. 这里所谓的跨平台就是Windows,Linux,Mac共同用一套M ...
- [codeforces 260]B. Ancient Prophesy
[codeforces 260]B. Ancient Prophesy 试题描述 A recently found Ancient Prophesy is believed to contain th ...
- move 和 CopyMemory的区别
Move(ABuffer,P, Sizeof(ABuffer)); //指针传递 Move(ABuffer^,P^, Sizeof(TArrayByte)); //复制内 ...
- 如何在linux中用命令产生一个范围内的随机数?
在shell中有一个环境变量RANDOM,它的范围是0--32767 如果我们想要产生0-25范围内的数,如何做呢?如下: $RANDOM%26 用这个环境变量对26取模,就可以得到最小是0,最大是2 ...
- iPhone取消软件更新上边的1
去除设置的更新+1小红点提示主要分为越狱和非越狱设备两种方法. 越狱状态下方法: 首先将你的设备进行越狱: 越狱后安装ifile(这个自行搜索安装): 用ifile打开/System/Library/ ...
- How to: Set up Openswan L2TP VPN Server on CentOS 6
Have you ever wanted to set up your own VPN server? By following the steps below, you can set up you ...
- 【Python】python list 迭代删除
最好方式使用filter,代码示例: def _filter(self, item): ): return False return True #lambda e:e%!= data['items'] ...