为什么80%的码农都做不了架构师?>>>
#0 系列目录#
- AngularJs学习笔记
- 【AngularJs学习笔记一】Bower解决js的依赖管理
- 【AngularJs学习笔记二】Yeoman自动构建js项目
- 【AngularJs学习笔记三】Grunt任务管理器
#1 初涉Grunt# ##1.1 Grunt是什么## Grunt是一个基于JavaScript上的一个很强大的任务管理器(task runner),或许这么一说让很多人觉得费解,简单来说就是你可以在你的终端机上,用JavaScript去执行一些程序来完成一些任务。比如说验证HTML、CSS、JavaScript的语法,压缩CSS、JavaScript、图像,Sass、LESS和Stylus编译成CSS等等,这些东西佛教徒吧很适合用Grunt来解决。
Grunt其实就是一个基于NodeJS,可用于自动化构建、测试、生成文档的项目管理工具。他可以更好的帮助一个团队更好的提高效率、减少错误率。
简单点来说,Grunt不仅仅是构建工具,实际上他只是任务运行器,管理每个子任务的自动化运行,我们还能使用他做更多东西。
##1.2 为什么要用Grunt## 或许有很多要都像我一样,会问“为什么要用Grunt”?其实用一句话可以概括出来:为了自动化
。对于前端项目,为了明确模块分工,我们可以会将JavaScript、CSS代码拆解成很多个模块,他们都有独立的一个个文件,但这样一来原来页面上,增加了文件个数,同时也产生过多的Http请求,可从性能的角度来考虑,不利于页面优化。所以我们需要合并这些JavaScript和CSS文件。这样一来,也期望有一种工具能代替我们手工操作,去完成这些任务。
大家都非常清楚,在项目发布之前,我们都需要做一个步骤,那就是尽可能的将项目中的文件进行尽可能压缩,比如JavaScript、CSS、images甚至是HTML文件,主要目的是减小加载文件的带宽
。另外,在很多情况为了安全性考虑,我们需要对我们项目的源代码做一些单元测试和回归测试。然而这些工作都是一些重复性的、乏味的工作。对于一个小型项目来说,或许没有太大的感觉,但对于一个大中型的项目,特别的参与人员过多的项目时,这些工作就显得更重要了。同时让大家更觉得自动化工具是多么的重要。
##1.3 Grunt能做什么## Grunt就是一个工具箱,就像一个百宝箱,拥有非常丰富的任务插件,可以帮助开发人员实现各式各样的构建目标。在Grunt工具箱中,按任务目标我们可以分为:
编译文档型:比如编译LESS、Sass、Stylus、Coffeescript等;
文件操作型:比如说合并、压缩JavaScript、CSS、图片等;
质量保障型:比如JSHint、Jasmin、Mocha等;
类库构建型:比如说Backbone.js、ember.js、angular.js等。
这些任务都依赖于给Grunt提供的插件来完成的
,但很多工作依旧需要在命令终端手工输入命令来完成这些操作。为此在Grunt中可以使用watch任务来实现一些监听文件改变、自动触发构建等功能
。从而减少人工去每次操作任务。
##1.4 运行Grunt需要什么## 前面也说过,Grunt是基于Node.js基础上运行的。需要能正常运行Grunt,必先在你的系统上正确安装[Node.js](http://nodejs.org/)和[NPM](https://npmjs.org/)
。如果你从未接触过node.js并不用太担心,只需要根据教程可以很容易帮助您在系统上安装Node.js。
环境好了之后,可以通过终端命令中安装grunt运行工具:
$ npm install -g grunt-cli
Grunt的运行工具有两个版本,一个是服务器端的版本(grunt),另一个是客户端版本(grunt-cli)
。而我们在项目中需要安装的是客户端版本。也就是上面所示的安装命令。这条命令将会把grunt命令植入到你的系统路径中,这样就允许你从任意目录来运行它(定位到任意目录运行grunt命令)。
一个Grunt项目还有两个文件特别的重要:package.json和Gruntfile.js
,前者用于Nodejs包管理,比如Grunt插件安装,后者是Grunt配置文件,配置任务或者自定义任务。
package.json:这个文件被用来存储已经作为npm模块发布的项目元数据(也就是依赖模块)。你将在这个文件中列出你的项目所依赖的Grunt(通常我们在这里配置Grunt版本)和Grunt插件(相应版本的插件)。
Gruntfile.js:通常这个文件被命名为Gruntfile.js或者Gruntfile.coffee,它是用于配置或者定义Grunt任务和加载Grunt插件的。
值得注意的是,package.json和Gruntfile.js两个文件都放置在项目的根目录中
,并且应该与项目的源代码一起被提交。
##1.4 创建package.json的方式## package.json是一个JSON文件,而这个文件是每个Grunt项目必备的文件
,因此在首要条件需要先创建这个文件。创建package.json文件方式有很多种:
根据grunt-init模板自动创建一个特定的package.json文件;
在命令终端通过npm init命令自动创建一个基本的package.json文件;
从官网上复制或者下载一个package.json文件;
手工创建一个package.json文件;
在Grunt项目的根目录下运行npm install创建一个空的package.json文件(不过我没有成功过,一直有错误信息提示,不知道是不是我的系统还是node环境有问题,正在查找中)
##1.5 package.json文件模板## 我采用了一种最简单的方式——手工创建package.json文件。而这个文件又是Grunt项目中必备文件之一,因此如何创建package.json文件内容就非常的重要,那么这里,向大家显示一个最简单的package.json文件模板:
{"name":"项目名称","version":"项目版本号","description":"项目描述","author":"项目创建者","license":"项目版权","devDependencies": {//项目依赖插件}
}
来看看一个测试项目的package.json文件中的真正内容:
{"name": "testGrunt","version": "0.1.0","description": "this is test project with grunt.","author": "airen","license": "BSD","devDependencies": {"grunt": "~0.4.1"}
}
可以手动在package.json中添加Grunt的插件,也可以通过以下命令的方式向package.json文件中添加:
$ npm install grunt插件名 --save-dev
这不仅会在本地安装Grunt插件,它还会使用一个波浪形字符的版本范围自动将所安装的Grunt插件添加到项目依赖中。
##1.6 创建Gruntfile.js文件## package.json文件搞定之后,就可以在项目根目下创建Gruntfile.js文件,这个时候你可以使用grunt-init或者直接手工创建一个。我们先来看一个Gruntfile.js的文件模板:
module.exports = function(grunt){// 构建任务配置grunt.initConfig({//读取package.json的内容,形成个json数据pkg: grunt.file.readJSON('package.json'),//Grunt 任务配置});//加载Grunt插件grunt.loadNpmTasks('Grunt插件名');//默认的Grunt任务grunt.registerTask('default',['Grunt任务']);
};
我们来看一个简单的示例:
module.exports = function(grunt) {// 构建任务配置grunt.initConfig({//读取package.json的内容,形成个json数据pkg: grunt.file.readJSON('package.json'),uglify: {//文件头部输出信息options: {banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'},//具体任务配置build: {//源文件src: 'src/hello-grunt.js',//目标文件dest: 'build/hello-grunt-min.js'}}});// 加载指定插件任务grunt.loadNpmTasks('grunt-contrib-uglify');// 默认执行的任务grunt.registerTask('default', ['uglify']);
};
到此,Grunt项目所需的package.json和Gruntfile.js文件都算是创建完成。有了这两个文件之后,Grunt项目算是万事具备,只欠东风了。你只需要在你的Grunt项目下运行:
$ npm install
执行完后,你将会在你的命令终端看到一大串类似于下面的一些信息:
...
npm http 200 https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz
npm http GET https://registry.npmjs.org/wordwrap
npm http GET https://registry.npmjs.org/amdefine
npm http 304 https://registry.npmjs.org/amdefine
npm http 304 https://registry.npmjs.org/wordwrap
grunt@0.4.1 node_modules/grunt
├── which@1.0.5
├── dateformat@1.0.2-1.2.3
├── eventemitter2@0.4.13
├── colors@0.6.2
├── hooker@0.2.3
├── async@0.1.22
├── coffee-script@1.3.3
├── underscore.string@2.2.1
├── findup-sync@0.1.2 (lodash@1.0.1)
├── iconv-lite@0.2.11
├── lodash@0.9.2
├── nopt@1.0.10 (abbrev@1.0.4)
├── rimraf@2.0.3 (graceful-fs@1.1.14)
├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
├── minimatch@0.2.12 (lru-cache@2.3.1, sigmund@1.0.0)
└── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.15)grunt-contrib-uglify@0.2.5 node_modules/grunt-contrib-uglify
├── grunt-lib-contrib@0.6.1 (zlib-browserify@0.0.1)
└── uglify-js@2.4.1 (uglify-to-browserify@1.0.1, async@0.2.9, source-map@0.1.31, optimist@0.3.7)
这个时候表示你的Grunt项目创建完成。你的项目结构也将变化成:
|--testGrunt
|----Gruntfile.js
|----node_modules
|--------grunt
|--------grunt-contrib-uglify
|----package.json
#2 开始使用Grunt# Grunt是一个任务管理器,能大大提高您运行前端开发工作流程。使用大量的Grunt插件可以自动执行任务,例如编译Sass和CoffeeScript,优化图像和验证您的JavaScript代码与JSHint。
##2.1 安装Grunt CLI## 我们第一件是要做的就是安装Grunt CLI。这是在你的项目上安装Grunt和加载Gruntfile.js。Grunt和Grunt插件安装都需要使用npm,和Node.js包管理。如果你的机器上没有安装Node.js,可以访问下载页面为您的操作系统安装程序。按照安装向导中的步骤,你可以在任保时间启动并运行npm安装。
一旦你安装好了Node.js和npm,你可以安装grunt-cli包。
npm install -g grunt-cli
使用-g标记安装grunt-cli表示全局安装
,你可以在任何项目中使用这个命令。
##2.2 创建package.json文件## 现在,您已经完成了Grunt CLI安装,可以使用Grunt管理任务。
为了更好的管理项目的依赖关系,需要给项目创建一个package.json
。如果您熟悉Rails开发,这个就类似于一个Gemfile。
package.json文件需要放置在你项目的根目录下
。这文件定义了项目的数据,如项目名,版本和作者。package.json文件还负责项目任务所需的依赖关系。devDependencies属性定义了您的应用程序所需要的任务包
。
{"name": "project-name","version": "0.1.0","author": "Your Name","devDependencies": {"grunt": "~0.4.1","grunt-contrib-jshint": "~0.6.3","grunt-contrib-watch": "~0.5.3","grunt-contrib-compass": "~0.6.0"}
}
注:这是一个非常基本的例子中的package.json文件。为了全面了所有属性,可以点击文档查阅。
一旦你创建好了package.json文件,你可以在终端如此头发下面的命令,安装任务所需要的依赖关系:
$ npm install
这个命令将获取所有的包,并把他们存储在项目根目录下的node_module目录中
。你可能要在这个目录下添加.gitignore文件(或类似),这样才不至于将他们签入版本控制器中。确保你的package.json文件添加到你的版本控制器中,用来确保其他开发人员在将使用这个项目需要的安装包
。
如果你想安装任务包,你可以在命令行中运行npm install进行安装。你可以通过指定任务包安装你想要的任务。
$ npm install <module> --save-dev
使用--save-dev可以通过npm自动将任务包安装所需要依赖的关系添加到你的package.json文件中
。安装之后确认更新你自己的文件。
##2.3 在Gruntfile中定义任务## 接下来你要在你的项目根目中创建一个叫Gruntfile.js文件。这个文件用来定义和配置你想在Grunt运行的任务
。
我们来看一个例子,配置你的package.json文件中指定的Grunt插件。
module.exports = function(grunt) {// 项目配置grunt.initConfig({pkg: grunt.file.readJSON('package.json'),watch: {css: {files: ['**/*.sass','**/*.scss'],tasks: ['compass']},js: {files: ['assets/js/*.js','Gruntfile.js'],tasks: ['jshint']}},compass: {dist: {options: {sassDir: 'assets/sass',cssDir: 'assets/css',outputStyle: 'compressed'}}},jshint: {options: {jshintrc: '.jshintrc'},all: ['Gruntfile.js', 'assets/js/*.js']}});// 加载Grunt插件grunt.loadNpmTasks('grunt-contrib-compass');grunt.loadNpmTasks('grunt-contrib-watch');grunt.loadNpmTasks('grunt-contrib-jshint');// 注册grunt默认任务grunt.registerTask('default', ['watch']);
};
**第一部分:所有代码都必须放置在Gruntfile文件中的wrapper函数中。**这个约定了Grunt所有插件在这里配置。
module.exports = function(grunt) {// 配置任务和插件
};
**第二部分:在Gruntfile中配置项目。**这是通过grunt.initConfig方法来配置。这种方法通过一个对象来实现,其中包含了项目配置以及任务配置。pkg.grunt.file.readJSON('package.json'),直接从之前创建的package.json文件导入配置数据
。依赖关系中提供了插件的名称和版本。
grunt.initConfig({pkg: grunt.file.readJSON('package.json'),task: {...},task_two: {...}
});
第三部分:配置任务。每个Grunt任务都在grunt.configInit中有自己配置的信息。属性的名称包含了任务的配置,包括Grunt任务的名称和任务。允许通过你的Gruntfile文件配置运行指定的任务
。
watch任务是用来监控文件被改变时执行的任务
。这个任务是有用的,例如,Sass文件修改保存后保存,这个任务会自动监控,将Sass文件编译成CSS文件。具体的配置如下:
watch: {css: {files: ['**/*.sass','**/*.scss'],tasks: ['compass']},js: {files: ['assets/js/*.js','Gruntfile.js'],tasks: ['jshint']}
},
在这个任务中,我们指定了两个不同的子任务。一个是处理Sass文件发生的变化,另一个是处理JavaScript文件发生的变化。files属性用来监控任务中指定的两种目标文件
。你可以使用*来匹配文件列表中的每个文件。tasks属性定义了Grunt任务的数组,执行改变项目目标中的文件
。
Gruntfile使用了grunt-contrib-compass插件来编译Sass,你也可以添加[Compass](http://compass-style.org/)
。如果你不使用Compass,还有一个Sass插件。你需要安装Ruby,Sass和Compass才能安装正常运行。
compass: {dist: {options: {sassDir: 'assets/sass',cssDir: 'assets/css',outputStyle: 'compressed'}}
},
配置Compass插件非常简单。里面的options属性定义了Sass文件的目录和你想编译出来的CSS文件目录。outputStyle属性指定了Sass代码要如何编译。指定compressed值,编译出来的CSS将被压缩
。
接下来,我们看看JSHint任务。如果你之前没有使用过,现在告诉你,[JSHint](http://www.jshint.com/)是一个很好的工具,可以检测你的JavaScript代码是否有错误
。它也可以用来帮助你统一代码风格,以便你的代码易于阅读,方便团队更好的做一个项目。
jshint: {options: {jshintrc: '.jshintrc'},all: ['Gruntfile.js', 'assets/js/*.js']
}
这里的all属性用于指定哪些文件用JSHint来检查
。再次使用通配符(*)来指定选择assets/js目录下的所有JavaScript文件。你可以指定options属性,指定JSHint应该运行的options属性
。你可以直接在Gruntfile文件中列出这些选项或者把他们提出来放到一个.jshintrc文件中。
这里有一个简单的.jshintrc文件的示例,他看起来像这样:
{"node": true,"esnext": true,"curly": false,"smarttabs": true,"indent": 2,"quotmark": "single","globals": {"jQuery": true}
}
注意:有关于JSHint中所有的选项列表,可以查阅文档。
在本节中我们只触及了我们所使用的Grunt任务的一些基本配置。更多的信息可以查看每个插件的文档:
- Watch文档
- Compass文档
- JSHint文档
第四部分:加载插件。 第二部分在Gruntfile.js文件中加载你想使用的Grunt插件。这些插件需要在你的package.json文件中指定和使用npm install来安装
。如果你试图运行没有安装的Grunt插件,将会报错。
// 加载Grunt插件
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-jshint');
使用matchdep我们可以使用一行代码加载所有的任务
。这是很好的一点,因为现在依赖关系的列表都只包括了包文件。在顶部的Gruntfile.js的grunt.initConfig上面粘贴下面的一段代码
:
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
第五部分:注册默认任务 grunt.registerTask方法用来指定一个运行Grunt任务的默认组,当你运行grunt命令行会执行这指定的默认任务。
// 注册默认的任务
grunt.registerTask('default', ['watch']);
该方法的第一个参籹指定任务的名称(如本例中的default),第二个参数用来指定你希望执行的默认任务的组合。在前面的watch任务中我们定义了监测compass和jshint任务,所以我们只要在这里执行watch任务。
##2.4 运行Grunt## Grunt这些配置是非常强大的,但你如何在实际中运行Grunt呢?在你的终端执行grunt命令,将会执行在default任务中指定的所有任务
。你也可以通过grunt后加对应的任务名,执行单独的任务:
grunt //运行指定的默认任务
grunt compass //仅仅执行compass任务
##2.5 添加新的插件## 现在您已经了解如何设置和运行Grunt,让我们添加另一个插件CSS样式注入。这是一个很整洁的工具,更新浏览器中的CSS而无需刷新页面。
先要安装grunt-browser-sync任务包.使用--save-dev自动将插件插入package.json文件中。
npm install grunt-browser-sync --save-dev
你也需要在Gruntfile文件中加载插件:
grunt.loadNpmTasks('grunt-browser-sync')
接下来在Gruntfile.js文件中添加browser_sync任务的配置
。指定了CSS文件应该被注入到的页面中。这个插件也可以处理图像、JavaScript和模板文件
。然而,这些将触发一个完整的页面刷新。
browser_sync: {files: {src : ['assets/css/*.css','assets/img/*','assets/js/*.js','**/*.html'],},options: {watchTask: true}
},
这个watchTask选项设置为true,因为我们使用了watch插件
。因为我编译Sass,我们需要确认任何任务执行的顺序是正确的。否则浏览浏览器加入的CSS是compass任务之前生成的CSS文件
。
注意:浏览器同步在测试跨设备变得更明显,更强大。插件将决定网络的IP地址,可以跨设备同步工作。然而,如果你使用的是自定义域名或浏览器同步找不到正确的IP地址,您可以指定host主机。
host: 'treehouse.dev'
接下来,你需要更新默认任务,里面指定browser_sync任务:
grunt.registerTask('default', ['browser_sync', 'watch']);
使用WebSockets将消息发送到浏览器,触发样式的注入或页面的更新,实现浏览器同步。如果你第一次执行grunt命令,将会给您的HTML添加两行代码,用来创建WebSocket连接
。
<script src='http://YOUR_HOST:3000/socket.io/socket.io.js'></script>
<script src='http://YOUR_HOST:3001/browser-sync-client.min.js'></script>
你已经完成了!您现在能够更新你的CSS、JavaScript和HTML文件,自动在浏览器中更新页面。每次修改文件不需要手动刷新浏览器窗口真爽
。
有时因为插件加载到Grunt中,我们有可能会指定开始选项。首先是HTML文件(index.html),包含下面的内容:
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"><title>Enter your first name</title><link rel="stylesheet" href="build/css/master.css"></head><body><label for="firstname">Enter your first name</label><input id="firstname" name="firstname" type="text"><p id="namevalidation" class="validation"></p><script type="text/javascript" src="build/js/base.min.js"></script></body>
</html>
在grunt.initConfig中添加这样的配置:
htmlhint: {build: {options: {'tag-pair':true,'tagname-lowercase':true,'attr-lowercase':true,'attr-value-double-quotes':true,'doctype-first':true,'spec-char-escape':true,'id-unique':true,'head-script-disabled':true,'style-disabled':true},src:['index.html']}
}
一个插件的配置通常是这样的:插件的名称(不带grunt-contrib-/grunt-前缀)然后是你选择的一个或更多的目标(可以用于创建自定义插件的文件),一个options对象,和这个文件效果
。现在你在终端运行grunt htmlhint,它会查看源文件,并确保我们的HTML没有错误!然而,一小时手动输入这个命令数次,将让你的工作很快变得乏味。
在命令的终端执行grunt htmlhint命令后,如果index.html没有出错时,在终端会有信息提出:
Running "htmlhint:build" (htmlhint) task
>> 0 files lint free.Running "htmlhint:src" (htmlhint) task
>> 1 file lint free.
##2.6 每次保存文件自动化运行任务## watch任务可以根据被保存的文件运行一个独特的任务
。在grunt.initConfig加入下面的代码:
watch: {html: {files:['index.html'],tasks:['htmlhint']}
}
然后在终端运行grunt watch。你会在终端看到下面的提示信息:
Running "watch" task
Waiting...
现在尝试在index.html中添加一个注释。你会注意到,当文件被保存,验证是自动执行的!你会在终端看到对应的信息:
Running "watch" task
Waiting...OK
>> File "index.html" changed.Running "htmlhint:build" (htmlhint) task
>> 0 files lint free.Running "htmlhint:src" (htmlhint) task
>> 1 file lint free.Done, without errors.
Completed in 0.538s at Fri Nov 01 2013 22:54:03 GMT+0800 (CST) - Waiting...
这对于开发者来说是一个很好的东西,因为它意味着,你在编写代码的时候他会默默的进行验证,如果代码没有通过验证测试的时候他会失败(和它会告诉你是什么问题引起的错误)
。
注意,grunt watch将会一直运行,直到关闭终端或者直到它停止(在Mac上执行control + c可以直接停止grunt watch命令)。
##2.7 尽可能让JavaScript文件小## 让我们创建一个JavaScript文件来验证一个用户名。尽可能我可以分简单,我们将检查的只是非字母字符。我们也会利用JavaScript的strict模式,它阻止我们品尼高有效但质量差劲的JavaScript
。把下面的代码粘贴到assets/js/base.js
:
function Validator(){"use strict";
}Validator.prototype.checkName = function(name) {"use strict";return(/[^a-z]/i.test(name) === false);
};window.addEventListener('load',function(){"use strict";document.getElementById('firstname').addEventListener('blur',function(){var _this = this;var validator = new Validator();var validation = document.getElementById('namevalidation');if (validator.checkName(_this.value) === true){validation.innerHTML = 'Looks good! :)';validation.className = 'validation yep';_this.className = "yep";}else {validation.innerHTML = 'Looks bad! :(';validation.className = "validation nope";_this.className = "nope";}});
});
我们使用UglifyJS来压缩这个文件,在grunt.initConfig中加入下面代码:
uglify: {build: {files: {'build/js/base.min.js' : ['assets/js/base.js']}}
}
UglifyJS压缩我们源文件中所有的变量和函数名,让我们文件尽可能少的占用空间,然后剪去空白和注释——非常适合用于生产的JavaScript
。接着,我们需要为我们的Uglify的JavaScript创建一个watch任务。将下面的代码添加到watch配置中:
watch: {js: {files: ['assets/js/base.js'],tasks: ['uglify']}
}
#3 Grunt上手指南# 命令行下安装:
# 如果之前有装过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({// task configuration});// Load the plugingrunt.loadNpmTasks('grunt-contrib-uglify');// Default task(s)grunt.registerTask('default', ['uglify']);
});
##3.1 关于插件## 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即可安装所有依赖的插件。
一个插件就是对应一个任务,一般来说,所有插件都会遵循下面将要说到的任务配置规则,很多插件的文档都不会很详细,所以你只能根据插件提供的示例套用这些规则看有没有更多配置的可能性。
##3.2 关于任务## 任务分为两种:"Basic" Tasks和"Multi" Tasks
。
Multi-tasks有所谓的target,比如下面的concat任务有foo和bar两个targets,而uglify任务有一个叫bar的target。
grunt.initConfig({concat: {foo: {// concat task 'foo' target options and files go here.},bar: {// concat task 'bar' target options and files go here.}},uglify: {bar: {// uglify task 'bar' target options and files go here.}}
});
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(arg1, arg2) {// do something
});
这样运行:grunt foo,或者grunt foo:a:b
,a和b就是传递给foo的参数。
##3.3 模板变量## grunt可以通过类似<%= k.sub.k %>
这种格式插入配置的其他属性值。
##3.4 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-leveloptions.},},
});
不一定所有的任务都会有option的。
##3.5 自定义任务## 获取/设置配置(模板变量):
可以读取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的配置。