这篇文章将带领你用Grunt来提速和优化网站开发的流程。首先我们会简短介绍Grunt的功能,然后我们直接上手,介绍如何用Grunt的不同插件来替你完成网站项目开发中的很多繁冗工作。

接着我们会创建一个简单的input校验器,用 Sass 来完成CSS的预处理,我们会学习如何用grunt-cssc 和CssMin来合并和压缩CSS,如何用 HTMLHint 来保证我们的HTML正确无误,以及如何实现在运行时部署和压缩我们的文件。最后,我们会学习如何用UglifyJS 来极简化我们的JavaScript以尽可能地节约带宽。

Grunt.js 是一个JavaScript 任务运行工具,它能替你完成重复性的任务,如极简化、 编译、单元测试和linting。

Grunt入门

过去几年JavaScript的发展速度令人震惊,不管是像Backbone.js和Ember.js这样的开发框架,还是JS Bin这样的开发社区,这个语言的发展都不仅改变了我们作为用户对网站的体验,还改变了我们作为开发者对网站的开发方式。

使用JavaScript,你往往需要定期去执行一系列的任务, 在大部分项目里人们可能对此已习以为常了,但它们仍然是重复的、浪费时间的活计。身处一个如此活跃的开发社区,你大概已经猜到,有现成的工具可以帮你自动化和加速完成这些任务了——这就是Grunt的用武之地。

Grunt 是什么?

Grunt基于Node.js之上,是一个以任务处理为基础的命令行工具,可以减少优化开发版本为发布版本所需的人力和时间,从而加速开发流程。它的工作原理是把这些工作整合为不同的任务,在你开发时自动执行。基本上,你可以让Grunt完成任何让你厌烦的任务:那些你需要重复进行的手工设置和运行发布的任务。

早期版本的Grunt自带JSHint和Uglify等plugin,最新的版本(version 0.4)则完全依赖用户指定plugin来运行任务。到底有哪些任务可以运行呢?这个单子可是长得很,可以说,Grunt能干任何你扔给它的活,从极简化(minifying) 到合并JavaScript (concatenating)。它还可以完成一些跟JavaScript无关的任务,比如从LESS和Sass编译CSS。我们甚至还用过它跟 blink(1) 来做编译失败的提醒。

为什么要用Grunt ?

Grunt最大的优势之一是给团队带来一致性。如果你和别人一起工作过,你肯定知道代码风格的不一样有多让人伤神。Grunt能让团队使用一套统一的命令,从而保证每个人写的代码符合统一标准。说到底,如果因为团队中几个人代码风格的微小不同而导致编译失败,那可是最烦人的事了。

Grunt还有一个极其活跃的开发者社区,定期发布新的plugin。使用Grunt的门槛也相对较低,因为很多工具和自动化任务都是直接可用的。

设置安装

要使用Grunt,第一件事是安装Node.js。(即使你没用过Node.js也不用担心——你只需安装它让Grunt能运行。)

安装了Node.js之后,用命令行工具执行以下命令:

 
 
1
$ npm install -g grunt-cli

要确认Grunt是否正确安装,可以使用以下命令:

 
 
1
$ grunt --version

下一步是在你的项目的根目录下创建package.json和gruntfile.js两个文件。

创建package.json文件

这个JSON文件让我们指定我们的开发环境所依赖的必须模块。有了它,项目的所有开发者都能保证安装上一致的必须模块,从而保证所有人拥有一样的开发环境。

在项目根目录下的pacakge.json文件中写上:

 
 
1
2
3
4
5
6
7
8
9
10
{
    "name" : "SampleGrunt",
    "version" : "0.1.0",
    "author" : "Brandon Random",
    "private" : true,
 
    "devDependencies" : {
        "grunt" :                   "~0.4.0"
    }
}

然后在命令行工具运行:

 
 
1
$ npm install

该命令告诉npm 需要安装的必须模块,npm会安装它们,自动保存在项目根目录下一个叫做 node_modules 的文件夹里。

创建gruntfile.js文件

gruntfile.js 文件本质上就是一个wrapper函数,接受grunt作为参数:

 
 
1
2
3
4
5
6
7
8
9
module.exports = function(grunt){
 
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json')
    });
 
    grunt.registerTask('default', []);
 
};

现在你已经可以在项目根目录下运行grunt命令行工具了。

 
 
1
2
$ grunt
> Task "default" not found. Use --force to continue.

这里我们只指定了Grunt作为必须模块,还没定义任何任务。接下来我们就要指定任务和必须模块。首先来看如何拓展package.json文件。

拓展package.json文件

使用Node.js最好的一点,就是它可以根据package.json文件的内容,一次性查找和安装多个package。要安装我们项目的所有必须任务,只须在package.json文件中加上以下内容:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    "name" : "SampleGrunt",
    "version" : "0.1.0",
    "author" : "Mike Cunsolo",
    "private" : true,
 
    "devDependencies" : {
        "grunt" :                       "~0.4.0",
        "grunt-contrib-cssmin":         "*",
        "grunt-contrib-sass":           "*",
        "grunt-contrib-uglify":         "*",
        "grunt-contrib-watch":          "*",
        "grunt-cssc":                   "*",
        "grunt-htmlhint":               "*",
        "matchdep":                     "*"
    }
}

那么如何实现安装?你肯定已经猜到了:

 
 
1
$ npm install

使用Grunt载入任务

package安装好后,还必须被Grunt载入才能为我们所用。使用 matchdep,我们用一行代码就可以自动载入所有任务。这是开发流程的一大优化,因为现在我们只须把必须任务列表写在package.json一个文件里,便于管理。

在gruntfile.js里,grunt.initConfig之上,写上以下代码:

 
 
1
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);

要是没有matchdep,我们就必须为每一个必须任务写一次grunt.loadNpmTasks(“grunt-task-name”); ,随着我们使用的任务的增加,这些载入任务的代码很快就会变得相当繁冗。在Grunt载入这些任务前,我们还可以指定设置选项。

现在我们需要创建我们的HTML文件(index.html):

 
 
 
 
 

XHTML

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!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>

用HTMLHint验证HTML

在grunt.initConfig里加入下列设置代码:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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']
    }
}

一般来说,一个plugin的设置方法如下:plugin的名称(去掉grunt-contrib-或grunt-前缀),选择使用此plugin的一个或多个对象(在这里可以给不同文件设置此plugin 的不同选项),一个选项object,以及plugin要作用的对象。现在,如果我们用命令行工具运行grunt htmlhint,该plugin就会检查我们在src里指定的HTML文件,验证其中有没有错误!但是每个小时都要手动运行几次这个任务,很快就让人觉得很繁琐了。

自动化任务运行

watch是一个特殊的任务,它可以在目标文件保存时自动触发一系列任务的运行。在grunt.initConfig里加入以下设置:

 
 
1
2
3
4
5
6
watch: {
    html: {
        files: ['index.html'],
        tasks: ['htmlhint']
    }
}

然后,在命令行工具中运行grunt watch命令。现在,你可以试试在index.html里加一行注释,保存文件。你会注意到,保存文件时会自动触发HTML的验证!这是对开发流程的一大优化:在你写代码时,watch任务就会默默同时为你验证代码,如果验证失败任务就会报告失败(它还会告诉你问题在哪)。

注意grunt watch任务会一直运行,直到命令行工具关闭,或手动停止(control+c在Mac中)。

保持JavaScript极简

让我们来写一个验证用户输入的名字的JavaScript文件。简便起见,我们这里只检查其中是否含有非字母的字符。我们的JavaScript会使用strict模式,这可以防止我们写可用但低质量的JavaScript。创建assets/js/base.js文件并在其中写上:

 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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中加上以下设置:

 
 
1
2
3
4
5
6
7
uglify: {
    build: {
        files: {
            'build/js/base.min.js': ['assets/js/base.js']
        }
    }
}

UglifyJS会替换所有的变量和函数名,剔除所有空白和注释,从而生成占据最小空间的JavaScript文件,对发布非常有用。同样地,我们需要设置一个watch任务来使用它,在watch的设置里加入以下代码:

 
 
1
2
3
4
5
6
watch: {    
    js: {
        files: ['assets/js/base.js'],
        tasks: ['uglify']
    }
}

从Sass源文件生成CSS

Sass对CSS相关工作非常有用,特别是在团队中。使用Sass可以大量减少代码量,因为Sass可通过变量、mixin函数生成CSS代码。Sass的具体使用方法并不在本教程探讨的范围内,所以如果你还不想使用Sass这样的CSS预处理器,可以跳过这一段。但我们这里会介绍一个很简单的用例,使用变量、一个mixin函数和Sass式CSS语法(SCSS)。

Grunt的Sass plugin需要使用Sass gem,为此你需要安装Ruby(OS X中已经预装了Ruby)。用以下命令你可以测试系统中是否已安装Ruby:

 
 
1
ruby -v

使用以下命令安装Sass gem:

 
 
1
gem install sass

根据系统设置的不同,你可能需要用sudo来运行此命令——即sudo gem install sass——这里你会被要求输入管理者密码。安装好Sass,在assets文件夹里创建sass文件夹,并在其中创建文件master.sass,然后写上:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@mixin prefix($property, $value, $prefixes: webkit moz ms o spec) {
    @each $p in $prefixes {
        @if $p == spec {
            #{$property}: $value;
        }
        @else {
            -#{$p}-#{$property}: $value;
        }
    }
}
$input_field:            #999;
$input_focus:           #559ab9;
$validation_passed:     #8aba56;
$validation_failed:     #ba5656;
$bg_colour:             #f4f4f4;
$box_colour:            #fff;
$border_style:          1px solid;
$border_radius:         4px;
 
html {
    background:         $bg_colour;
}
 
body {
    width:              720px;
    padding:            40px;
    margin:             80px auto;
    background:         $box_colour;
    box-shadow:         0 1px 3px rgba(0, 0, 0, .1);
    border-radius:      $border_radius;
    font-family:        sans-serif;
}
 
input[type="text"] {
    @include            prefix(appearance, none, webkit moz);
    @include            prefix(transition, border .3s ease);
    border-radius:      $border_radius;
    border:             $border_style $input_field;
    width:              220px;
}
 
input[type="text"]:focus {
    border-color:       $input_focus;
    outline:            0;
}
 
label,
input[type="text"],
.validation {
    line-height:        1;
    font-size:          1em;
    padding:            10px;
    display:            inline;
    margin-right:       20px;
}
 
input.yep {
    border-color:       $validation_passed;
}
 
input.nope {
    border-color:       $validation_failed;
}
 
p.yep {
    color:              $validation_passed;            
}
 
p.nope {
    color:              $validation_failed;
}

你会注意到SCSS比起普通的Sass更像CSS。这个样式表使用了Sass的两个特性:mixin和变量。一个mixin根据给它的参数生成CSS代码块,很像函数。而一个变量可以用来定义一段CSS代码片段,然后在很多地方重用。变量对定义Hex颜色尤其有用,我们可以用它建立一个色表,然后在尝试不同设计时,只须修改一处代码,从而大大提高了效率。这里的mixin则用来给CSS3的apperance和transition等属性生成前缀,减少了冗余代码。编写一个很长的样式表文件时,任何减少代码量的方法,都会让团队中日后更新此样式表的人受益。

在Sass之外,grunt-cssc任务可以整合CSS文件中定义的样式规则,最大限度削减所生成的CSS文件中的重复内容。在中到大型项目中经常出现重复的样式规则,使用这个任务就很有益处。但是,由此生成的CSS文件也不一定就是最简的,所以我们还需要使用cssmin任务,它既能剔除所有空白,还能把颜色值替换为可能的最简形式(比如white会被替换为#fff)。在gruntfile.js中加入如下内容:

 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cssc: {
    build: {
        options: {
            consolidateViaDeclarations: true,
            consolidateViaSelectors:    true,
            consolidateMediaQueries:    true
        },
        files: {
            'build/css/master.css': 'build/css/master.css'
        }
    }
},
 
cssmin: {
    build: {
        src: 'build/css/master.css',
        dest: 'build/css/master.css'
    }
},
 
sass: {
    build: {
        files: {
            'build/css/master.css': 'assets/sass/master.scss'
        }
    }
}

现在我们设置好了处理样式表的任务,还要让它们自动运行。Grunt自动创建了build文件夹来存放所有的发布用script、CSS和(如果这是一个完整的网站项目的话)压缩后的图片文件。这意味着assets文件夹里可以包含为开发而做的详细的注释文件甚至说明文档,而build文件夹里则只会包含极简化代码和优化压缩过的图像文件。

我们给CSS相关的工作定义一套新的任务,在gruntfile.js里的default task下面加上以下内容:

 
 
 
 

JavaScript

 
1
grunt.registerTask('buildcss',  ['sass', 'cssc', 'cssmin']);

现在,运行grunt buildcss任务就会按顺序运行所有CSS相关的任务,比起分别运行grunt sass、grunt cssc然后grunt cssmin来,这样简洁多了。最后我们需要做的就是更新watch任务的设置,让这些CSS相关任务也能自动运行:

 
 
1
2
3
4
5
6
watch: {
    css: {
        files: ['assets/sass/**/*.scss'],
        tasks: ['buildcss']
    }
}

这个路径可能看起来有点奇怪,它的用途是递归地遍历我们assets/sass文件夹里的所有文件和子文件夹,来查找.scss文件。如此一来,我们就可以创建任意多的.scss文件,而不需要在gruntfile.js里添加它们的路径。现在,你的gruntfile.js应该是下面这样:

 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
module.exports = function(grunt){
 
    "use strict";
   require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
 
    grunt.initConfig({
 
        pkg: grunt.file.readJSON('package.json'),
 
        cssc: {
            build: {
                options: {
                    consolidateViaDeclarations: true,
                    consolidateViaSelectors:    true,
                    consolidateMediaQueries:    true
                },
                files: {
                    'build/css/master.css': 'build/css/master.css'
                }
            }
        },
 
        cssmin: {
            build: {
                src: 'build/css/master.css',
                dest: 'build/css/master.css'
            }
        },
 
        sass: {
            build: {
                files: {
                    'build/css/master.css': 'assets/sass/master.scss'
                }
            }
        },
 
        watch: {
            html: {
                files: ['index.html'],
                tasks: ['htmlhint']
            },
            js: {
                files: ['assets/js/base.js'],
                tasks: ['uglify']
            },
            css: {
                files: ['assets/sass/**/*.scss'],
                tasks: ['buildcss']
            }
        },
 
        htmlhint: {
            build: {
                options: {
                    'tag-pair': true,                      
// Force tags to have a closing pair
                    'tagname-lowercase': true,            
// Force tags to be lowercase
                    'attr-lowercase': true,                
// Force attribute names to be lowercase e.g. <div id="header"> is invalid
                    'attr-value-double-quotes': true,      
// Force attributes to have double quotes rather than single
                    'doctype-first': true,                
// Force the DOCTYPE declaration to come first in the document
                    'spec-char-escape': true,              
// Force special characters to be escaped
                    'id-unique': true,                    
// Prevent using the same ID multiple times in a document
                    'head-script-disabled': true,          
// Prevent script tags being loaded in the  for performance reasons
                    'style-disabled': true                
// Prevent style tags. CSS should be loaded through
                },
                src: ['index.html']
            }
        },
 
        uglify: {
            build: {
                files: {
                    'build/js/base.min.js': ['assets/js/base.js']
                }
            }
        }
 
    });
 
    grunt.registerTask('default',   []);
    grunt.registerTask('buildcss',  ['sass', 'cssc', 'cssmin']);
 
};

现在我们有了一个静态HTML页面,一个存放Sass和JavaScript源文件的assets文件夹,一个存放优化后的CSS和JavaScript的build文件夹,以及package.json文件和gruntfile.js文件。

至此你已经有了一个不错的基础来进一步探索Grunt。像之前提到的,一个非常活跃的开发者社区在为Grunt开发前端plugin。我建议你现在就到plugin library 去看看那300个以上的plugin。

资料转自:http://blog.jobbole.com/51586/

grunt--自动化任务快速上手的更多相关文章

  1. Python编程快速上手-让繁琐工作自动化-第二章习题及其答案

    Python编程快速上手-让繁琐工作自动化-第二章习题及其答案 1.布尔数据类型的两个值是什么?如何拼写? 答:True和False,使用大写的T和大写的F,其他字母是小写. 2.3个布尔操作符是什么 ...

  2. 入门python:《Python编程快速上手让繁琐工作自动化》中英文PDF+代码

    入门推荐学习<python编程快速上手>前6章是python的基础知识,通俗易懂地讲解基础,初学者容易犯错的地方,都会指出来.从第三章开始,每章都有一个实践项目,用来巩固前面所学的知识. ...

  3. Python编程快速上手 让繁琐工作自动化 - 专业程序员的养成完整版PDF免费下载_百度云盘

    Python编程快速上手  让繁琐工作自动化 - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:7qm4 有关本书 累计销售超过10万册 零基础编程者的不二之选 基于Python3编写 通用 ...

  4. 《Python编程快速上手 —让繁琐工作自动化》|百度网盘免费下载|Python自动化办公

    Python编程快速上手—让繁琐工作自动化 提取码:u8vj 如今,人们面临的大多数任务都可以通过编写计算机软件来完成. Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言.通过 P ...

  5. Airtest 快速上手教程

    一.Airtest 简介: AirtestIDE 是一个跨平台的UI自动化测试编辑器,适用于游戏和App. 自动化脚本录制.一键回放.报告查看,轻而易举实现自动化测试流程 支持基于图像识别的 Airt ...

  6. Ansible快速上手

    ansible 是通过python 语言开发的自动化运维工具,可以实现批量系统设置.批量程序部署.批量执行命令等功能 下面是基于docker使用ansible测试示例,可以让新手快速上手使用 一.新建 ...

  7. 新手学习Linux之快速上手分析

    一.起步 首先,应该为自己创造一个学习linux的环境--在电脑上装一个linux或unix 问题1:版本的选择 北美用redhat,欧洲用SuSE,桌面mandrake较多,而debian是技术最先 ...

  8. Ansible 快速上手(转)

    add by zhj: 执行Ansible(发音时,重音在最前面)命令有两种方式,一种是ad-hoc形式,另一种是playbooks,对于软件开发者来说,一般使用ad-hoc就足够了.playbook ...

  9. Gradle快速上手——从Maven到Gradle

    [本文写作于2018年7月5日] 本文适合于有一定Maven应用基础,想快速上手Gradle的读者. 背景 Maven.Gradle都是著名的依赖管理及自动构建工具.提到依赖管理与自动构建,其重要性在 ...

  10. Ansible 快速上手

    Ansible优点: 充分利用现有设施.使用 Ansible 无需安装服务端和客户端,只要 SSH 即可.这意味着,任何一台装有 Ansible 的机器都可以成为强大的管理端.我觉得,这种去中心化的思 ...

随机推荐

  1. Ninject的项目情况

    Ninject的项目情况 首先,它有很多的项目组成,适合不同的环境,当然它有几个基本的核心库. 为什么它会有这么多的库呢?因为轻量级,易于使用和被扩展是它的目标,代码越是少,你使用代码的可能性越高嘛. ...

  2. Knockout, Web API 和 ASP.Net Web Forms 进行简单数据绑定

    使用Knockout, Web API 和 ASP.Net Web Forms 进行简单数据绑定   原文地址:http://www.dotnetjalps.com/2013/05/Simple-da ...

  3. script —— 终端里的记录器

    当 你在终端或者控制台工作时,你可能想要记录在终端中所做的一切.这些记录可以用来当作史料,保存终端所发生的一切.比如说,你和一些Linux管理员们同 时管理着相同的机器,或者你让某人远程登陆到了你的服 ...

  4. boke

    云/n 计算/v 代表/n IT/x 领域/n 向/p 集约化/v ./w 规模化/v 与/c 专业化/v 道路/n 发展/v 的/u 趋势/n ,/w 是/v IT/x 领域/n 正在/d 发生/v ...

  5. 【转载】Stack Overflow: The Architecture - 2016 Edition

    转载:http://www.infoq.com/cn/news/2016/03/Stack-Overflow-architecture-insi?utm_source=tuicool&utm_ ...

  6. CentOS 6下安装nodejs 0.9.0(转)

    确保安装了python,大部分安装失败都是由于python版本过低导致.安装之前,升级python版本,升级步骤 http://www.tomtalk.net/wiki/Python. [root@S ...

  7. XLSTransformer生成excel文件

    jxls的使用方法: 1)声明一个XLSTransformer对象,生成方式就是使用new操作符                 XLSTransformer transformer = new XL ...

  8. jquery选择器之内容过滤选择器

    先写出DOM元素的HTML结构: <style type="text/css"> /*高亮显示*/ .highlight{ background-color: gray ...

  9. Opengl坐标转换

    有时候我们需要手动计算三维点对应的二维坐标,下面的矩阵公式就是模拟了一遍三维图形的流程.这里已假设读者具备了图形学的基础知识,比如矩阵乘法代表的三维变换,放射变换:还有齐次坐标等. 这里不考虑模型自身 ...

  10. SVN Access to '/svn/Test/!svn/me' forbidden,不能更新解决办法

    从之前的电脑将Repositorise复制到现在用的PC,出现可以checkout但是不能update的问题.在网上找到以下解决方法,均未能解决. 1.确认URL跟实际一致: 2.确认用户名密码正确: ...