Grunt是前端自动化工具,其作用就是将压缩、单元检测、编译等重复性操作自动化完成。只要配置好配置文件,任务机就可以自动完成项目中的重复性任务。
现在主流的工具有Grunt和Gulp,还有国内百度开源的一个FIS。Gulp比Grunt用起来更加方便,而FIS本身集成了很多东西,比较容易上手。但是我们还是以Grunt作为起点来认识前端自动化吧。
需要安装Grunt,首先需要安装node。
node安装教程
node是自动配置环境变量的,所以安装完成后可以直接运行开始测试。
安装完node并且确认安装成功后,就可以通过命令行来安装Grunt了。
运行一下命令:
npm install –g grunt-cli
安装Grunt成功后,就可以在自己的项目中去配置了,等待全部配置完成后,就可以应用了。
接下来讲讲如何配置Grunt。首先进入项目所在文件目录:
然后自己定义一个package.json文件。这个文件的作用是给我们指定开发环境所依赖的必须模块。有了它,项目的所有开发者都能保证安装上一致的必须模块,从而保证所有人都拥有一样的开发环境。
在package.json中写上:
{
"name" : "SampleGrunt",
"version" : "0.1.0",
"author" : "Liu Fang",
"private" : true,
"devDependencies" : { "grunt" : "~0.4.0" } }
至于package.json中的具体配置项,可以参考该文章:package配置项
配置完成后,在项目所在目录中运行:
npm install
接下来继续创建一个叫做gruntfile.js的文件夹:
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.registerTask('default', []);
};
我们可以通过拓展package.json来安装我们项目所需要的插件。Grunt插件大全
里有所有的插件,开发者可以随意挑选,选中后,修改我们的package.json如下:
{
"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": "*" } }
这代表我们选中了几款插件。然后是安装:
等待,出现结果:
可以发现项目根目录下的node_modules文件夹中出现了新东西:
说明配置插件成功了,接下来就是如何应用插件了。
这里我们介绍一下各个插件的应用。
首先需要介绍了介绍matchdep插件。利用该插件,我们用·一行代码就可以自动载入所有任务,对gruntfile.js进行修改。
在grunt.initConfig加句代码:
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.registerTask('default', []);
};
如果没有该插件,我们就必须为每一个任务写一个
grunt.loadNpmTasks(‘grunt-task-name’);
随着任务的增多,是非常不方便的。
接下来我们介绍一个html语法检验器htmlhint。
首先我们在项目根目录下创建一个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>
然后我们修改gruntfile.js如下:
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
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.registerTask('default', []);
};
至于插件具体如何配置可以查看htmlhint官方文档
任务已经定义好了,接下来是执行,只需要在命令行中运行grunt htmlhint就可以了。错误会出现在命令行中。
但是这样依旧不方便,难道我们每一次检查html页面都需要执行一次任务吗?
所以我们需要介绍另外一个插件watch。
watch是一个特殊的任务,它可以在目标文件保存时自动触发一系列任务。还是修改gruntfile.js:
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {//文件保存时自动触发一系列任务
html: {
files: ['index.html'],
tasks: ['htmlhint']
}
},
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.registerTask('default', []);
};
然后在命令行中执行grunt watch命令,它就会一直监听,每一次保存指定文件都会触发指定任务:
接下来介绍javascript的压缩插件uglify。
该插件会替换所有的变量和函数名,剔除所有空白和注释,使得javascript文件最小化。
首先我们在根目录下写一个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";
}
});
});
然后在gruntfile.js的grunt.initConfig配置uglify来压缩:
uglify: { build: { files: { 'base.min.js': ['base.js'] }
}
}
还是通过watch来使用它:
watch: { js: { files: ['base.js'], tasks: ['uglify'] }
}
最后介绍一下css的压缩工具cssmin。
前面讲的很详细了,这里直接上脚本:
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {//文件保存时自动触发一系列任务
html: {
files: ['index.html'],
tasks: ['htmlhint']
},
js: {
files: ['base.js'],
tasks: ['uglify']
}
},
htmlhint: {//html语法检测
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']
}
},
uglify: {//javascript压缩
build: {
files: {
'base.min.js': ['base.js']
}
}
},
cssmin: {
options: {
shorthandCompacting: false,
roundingPrecision: -1
},
target: {
files: {
'output.css': ['test1.css', 'test2.css']
}
}
}
});
grunt.registerTask('default', []);
};
最后全部实验demo地址