grunt基础知识我就不再写了,直接看官网就可以了.官网的教程还是挺清楚的.
大概看了一点以后,打算自己试试看,就按照现在公司的项目需求,拿来练练手.需求如下:

gruntProject根目录下,有html页面,less文件夹,jssrc文件夹.
less文件夹下,有一些公共的less文件,像global.less,mixins.less,variables.less.
像index,buy,这些比较大的页面,会有一个文件夹,把它里面的每个版块分别写入一个less文件,而根目录下的index.less,则引入了index文件夹下的less文件.
jssrc文件夹下则是每个页面引入的js,至于jq等框架,则不在这个根目录下,在更外层,这里暂时不需要考虑.
我们的需求就是,404.less,buy.less,index.less,这些页面需要直接引用的less,是需要被编译成css,并且压缩的,压缩后输出在根目录的css文件夹下.而公共的less,则不需要编译,另外,less文件夹下的文件夹里的less文件,也是不需要编译并输出的.说白了就是,一个页面引入一个css,其它作为依赖被引入的less文件,都不需要编译.而js文件,每个都需要压缩,压缩后输出到js文件夹下.
这样,一共需要用到四个插件:
- 编译less的插件: grunt-contrib-less
 - 压缩js的插件: grunt-contrib-uglify
 - 实时监测的插件: grunt-contrib-watch
 - 加载所有插件的插件: load-grunt-tasks
 
首先创建一个package.json文件: npm init
然后安装插件:
- 安装grunt-cli: sudo npm install -g grunt-cli
 - 安装grunt: npm install grunt –save-dev
 - 安装load-grunt-tasks: npm install load-grunt-tasks –save-dev
 - 安装另外几个插件,不赘述
 
然后开始书写Gruntfile.js:
'use strict';
module.exports = function(grunt) {
    require('load-grunt-tasks')(grunt)
    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            files:['jssrc/*.js','less/**/*.less'],
            tasks:['default']
        },
        uglify: {
            build: {
                expand: true,
                cwd: 'jssrc/',
                src: '*.js',
                dest: 'js/',
                ext: '.min.js',
                extDot: 'last'
            }
        },
        less: {
            options: {
                compress:true
            },
            build: {
                expand: true,
                cwd: 'less/',
                src: ['*.less','!global.less','!mixins.less','!variables.less'],
                dest: 'css/',
                ext: '.min.css',
                extDot: 'last'
            }
        }
    });
    // 默认被执行的任务列表。
    grunt.registerTask('default', ['uglify','less']);
};
下面分析一下这个文件:
1.基本格式:
'use strict';
module.exports = function(grunt) {
    ...
};
2.加载package.json的devDependencies里的插件:
require('load-grunt-tasks')(grunt)
3.配置任务:
grunt.initConfig({
    ...
})
4.获取package.json里的参数(这个例子用不到):
pkg: grunt.file.readJSON('package.json'),
5.配置uglify任务:
uglify: {
    build: {
        expand: true,
        cwd: 'jssrc/',
        src: '*.js',
        dest: 'js/',
        ext: '.min.js',
        extDot: 'last'
    }
}
这里使用的是动态配置的方法,就是说,不是针对某几个文件,而是所有匹配的文件.
- expand: true 开始动态配置
 - cwd: 路径,是下面的src的相对路径
 - src: 需要压缩的文件,相对于cwd路径,\.js表示cwd根目录下的所有js文件.*(不包括子文件夹下的js)
 - dest: 压缩后输入的js的路径.不是相对于cwd哦,就是相对于项目根目录.
 - ext: 压缩后的文件的后缀名替换.
 - extDot: 从文件名里的第几个句点开始替换.这里定义last,就表示从最后一个句点开始替换.比如
a.b.c.js,从最后一个句点开始替换,就是.js部分替换成ext. 
这样做的好处是不需要经常改动配置文件,但是当文件非常多,并且开启了watch任务的时候,对电脑的性能是个很大的挑战.
6.配置less任务:
less: {
    options: {
        compress:true
    },
    build: {
        expand: true,
        cwd: 'less/',
        src: ['*.less','!global.less','!mixins.less','!variables.less'],
        dest: 'css/',
        ext: '.min.css',
        extDot: 'last'
    }
}
less任务的options中设置compress属性为true,表示编译后需要压缩.
同样,less任务也使用动态配置,它和uglify任务的配置有一点不同:
src里排除了global.lee,mixins.less,variables.less,这些全局的,不需要编译的文件.
7.配置watch任务:
watch: {
    files:['jssrc/*.js','less/**/*.less'],
    tasks:['default']
}
files属性配置需要监测变化的文件,tasks属性配置文件变化以后需要执行的任务.
这里再次用到了一个很重要的知识点: /\.js 表示目录下所有的js文件,不包括目录的子目录下的js文件. /**/*.less* 表示目录下的所有less文件,包括目录的子目录下的less文件.
8.注册default任务:
grunt.registerTask('default', ['uglify','less']);
把默认要执行的任务定义为uglify任务和less任务.
然后执行一下grunt,就可以看到文件被编译压缩好了:

开启实时监测模式: grunt watch, 然后修改less或者js,都会实时编译压缩.
其实grunt就是使用一个又一个的插件,它的复杂在于插件很多都是英文的,比较难看懂,锻炼英文水平挺好~还有就是当多个插件混合使用的时候,尤其是使用了yeoman,下次我就会学习使用了yeoman以后再使用grunt.到时候再来写博客.