Grunt入门(一)
什么是grunt
Grunt
就和photoshop
里面的插件一样,它能够帮我们自动完成一些反复重复的任务
ps插件里,我们经常会用动自动切图,自动导出切片这样的工具。grunt
里面,就可以使用自动编译LESS
、压缩CSS
、JS
这样的工具。
Grunt
是一个平台,没有插件,Grunt
什么事也不能做。它是提供了一个标准,任何插件都要去遵守的一个机制和规则。就和USB接口一样,接在USB插口的,有可能是U盘,摄像头这些完成不同功能的外设。
为什么要用Grunt
Grunt
有一个庞大的生态圈, 里面有各种各样现成的插件,可以满足大部分的日常需要。无需额外开发。
快速安装
- 安装
Node.js
- 使用
npm
安装Grunt
npm install -g grunt-cli
Gruntfile.js与package.json
每一个Grunt
项目都会带上这两个文件,接下来分别讲解这两个文件的用途。
package.json
npm
命令运行时会读取当前目录的 package.json
文件和解释这个文件,这个文件基于Packages/1.1
规范。
在这个文件里你可以定义你的应用名称( name )、应用描述( description )、关键字( keywords )、版本号( version )、应用的配置项( config )、主页( homepage )、作者( author )、资源仓库地址( repository )、bug的提交地址( bugs ),授权方式( licenses )、目录( directories )、应用入口文件( main )、命令行文件( bin )、应用依赖模块( dependencies )、开发环境依赖模块( devDependencies )、运行引擎( engines )和脚本( scripts )等。
下面是一份完整的package.json
:
{
"name": "test",
"version": "0.1.0",
"description": "A testing package",
"author": "A messed author <messed@example.com>",
"dependencies": {
"express": "1.x.x",
"ejs": "0.4.2",
"redis": ">= 0.6.7"
},
"devDependencies": {
"vows": "0.5.x"
},
"main": "index",
"bin": {
"test": "./bin/test.js"
},
"scripts": {
"start": "node server.js",
"test": "vows test/*.js",
"preinstall": "./configure",
"install": "make && make install"
},
"engines": {
"node": "0.4.x"
}
}
当在项目的根目录中运行npm install
时,npm会自动去安装dependencies中定义的依赖包,在项目的根目录中生成一个node_modules的文件夹,这个项目所需要的node库就安装在这个目录下。
其余关于package.json的含义暂时不说。
Gruntfile.js
这个文件与package.json一样,放在文件的根目录下。
一个Gruntfile.js包含以下几个部分:
- "wrapper" 函数
- 项目与任务配置
- 加载grunt插件和任务
- 自定义任务
一份完整的Gruntfile文件
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
// 加载包含 "uglify" 任务的插件。
grunt.loadNpmTasks('grunt-contrib-uglify');
// 默认被执行的任务列表。
grunt.registerTask('default', ['uglify']);
};
"wrapper" 函数
每一份 Gruntfile (和grunt插件)都遵循同样的格式,写的Grunt代码必须放在此函数内:
module.exports = function(grunt) {
// Do grunt-related things in here
};
项目与任务配置
大部分的Grunt任务都依赖某些配置数据项,这些数据被定义在一个Object内,作为参数传递给grunt.initConfig()
方法。
在下面的案例中,
grunt.file.readJSON('package.json')
将存储在package.json
文件中的JSON元数据引入到grunt config
中。 由于<% %>
模板字符串可以引用任意的配置属性,因此可以通过这种方式来指定诸如文件路径和文件列表类型的配置数据,从而减少一些重复的工作。
你可以在这个配置对象中(传递给initConfig()
方法的对象)存储任意的数据,只要它不与你任务配置所需的属性冲突,否则会被 忽略。此外,由于这本身就是JavaScript
,你不仅限于使用JSON
;你可以在这里使用任意的有效的JS
代码。如果有必要,你甚至可以以编程的方式生成配置。
与大多数task一样,grunt-contrib-uglify
插件中的uglify
任务要求它的配置被指定在一个同名属性中。在这里有一个例子, 我们指定了一个banner选项(用于在文件顶部生成一个注释),紧接着是一个单一的名为build
的uglify
目标,用于将一个js
文件压缩为一个目标文件。
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
当使用其他开发者开发的一些插件的时候,一般都会有说明这个配置格式,下面是从github
中找的一个关于雪碧图合并的插件:
// 自动雪碧图
sprite: {
allslice: {
files: [
{
//启用动态扩展
expand: true,
// css文件源的文件夹
cwd: 'css',
// 匹配规则
src: ['*.css'],
//导出css和sprite的路径地址
dest: 'tmp/',
// 导出的css名
ext: '.sprite.css'
}
],
options: {
// 默认使用GM图像处理引擎
'engine': 'gm',
// 默认使用二叉树最优排列算法
'algorithm': 'binary-tree',
// 给雪碧图追加时间戳,默认不追加
'imagestamp':false,
// 给样式文件追加时间戳,默认不追加
'cssstamp':true,
// 是否以时间戳为文件名生成新的雪碧图文件,默认不生成新文件
'newsprite':true
}
}
}
加载grunt插件和任务
插件的安装是定义在package.json中的dependencies对象里。如果我们已经我们要在后期继续添加插件,可以通过
npm install grunt-contrib-less --save-dev
的方式来安装。
安装好需要的grunt插件后,就需要把插件引入到项目中。比如我们要引入刚刚安装好的grunt-contrib-less
那我们就需要在gruntfile
中使用如下方法:
grunt.loadNpmTasks('grunt-contrib-less');
自定义任务
grunt允许开发者自定义参数来指定执行特定的任务。比如,当需要grunt-contrib-less这个插件来执行less编译的时候,可以用grunt.registerTask()
指定一个运行参数来自定义任务,如grunt.registerTask('less', ['less']);
。当执行less编译时,只需要运行这样的代码就行grunt less
。grunt也提供默认的执行方法, 如果只想运行grunt
命令,不加参数就能执行less编译的话,我们也可以这样来自定义任务grunt.registerTask('default', ['less']);
。方法的第二个参数是一个数组,那就说明,一个参数是可以来执行多个任务的。执行的顺序按照数组的顺序串联执行。举个例子,在less编译完之后,想做一下图片压缩和JS压缩,那我们可以这样做:
grunt.registerTask('publish', ['less', 'imagemin', 'uglify']);
那么问题来了,是不是每一次新建一个项目都要去重写这个gruntfile.js
和package.json
呢?答案肯定不是……
第二节,再继续讲讲脚手架(自动生成工具)yo
与Grunt
的关系和使用。