引入:grunt是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于:
- ① 压缩文件
- ② 合并文件
- ③ 简单语法检查
环境:grunt是基于nodejs运行的,所以需要有nodejs,在Nodejs中,安装grunt的命令行接口。
1 npm install -g grunt-cli
将grunt命令植入系统路径。通过nodejs的require查找到安装的grunt,就能在任意目录下运行grunt项目了。
在一个简单的实例中,慢慢享受grunt给前端所带来的便捷与随心所欲。
新建项目的时候,增加两个文件,一个为:package.json;另一个为:Gruntfile.js。
package.json
这个文件用来存储npm模块的依赖项(比如我们的打包若是依赖requireJS的插件,这里就需要配置)
然后,我们会在里面配置一些不一样的信息,比如我们上面的file,这些数据都会放到package中
对于package的灵活配置。
Gruntfile
这个文件尤其关键,他一般干两件事情:
① 读取package信息
② 插件加载、注册任务,运行任务(grunt对外的接口全部写在这里面)
Gruntfile一般由四个部分组成
① 包装函数
这个包装函数没什么东西,意思就是我们所有的代码必须放到这个函数里面
module.exports = function (grunt) { //你的代码 }
这个不用知道为什么,直接将代码放入即可
② 项目/任务配置
我们在Gruntfile一般第一个用到的就是initConfig方法配置依赖信息
pkg: grunt.file.readJSON('package.json')
这里的 grunt.file.readJSON就会将我们的配置文件读出,并且转换为json对象
然后我们在后面的地方就可以采用pkg.XXX的方式访问其中的数据了
值得注意的是这里使用的是underscore模板引擎,所以你在这里可以写很多东西
uglify是一个插件的,我们在package依赖项进行了配置,这个时候我们为系统配置了一个任务
uglify(压缩),他会干这几个事情:
① 在src中找到zepto进行压缩(具体名字在package中找到)
② 找到dest目录,没有就新建,然后将压缩文件搞进去
③ 在上面加几个描述语言
这个任务配置其实就是一个方法接口调用,按照规范来就好,暂时不予关注,内幕后期来
这里只是定义了相关参数,但是并未加载实际函数,所以后面马上就有一句:
grunt.loadNpmTasks('grunt-contrib-uglify');
用于加载相关插件
最后注册一个自定义任务(其实也是默认任务),所以我们下面的命令行是等效的:
grunt == grunt uglify
实例:
1 js压缩打包
package.json文件
1 { 2 "name": "demo", 3 "file": "zepto", 4 "version": "0.1.0", 5 "description": "demo", 6 "license": "MIT", 7 "devDependencies": { 8 "grunt": "~0.4.1", 9 "grunt-contrib-jshint": "~0.6.3", 10 "grunt-contrib-uglify": "~0.2.1", 11 "grunt-contrib-requirejs": "~0.4.1", 12 "grunt-contrib-copy": "~0.4.1", 13 "grunt-contrib-clean": "~0.5.0", 14 "grunt-strip": "~0.2.1" 15 }, 16 "dependencies": { 17 "express": "3.x" 18 } 19 }
1->1(一个文件打包压缩到另一个文件):
1 module.exports = function (grunt) { 2 banner: '/*! <%= pkg.file %>Qboooogle <%= grunt.template.today("yyyy-mm-dd") %> */\n' 3 }, 4 build: {6 src: 'build/js/<%=pkg.file %>.js', 7 dest: 'dist/js/<%= pkg.file %>.min.js' 8 } 9 }
N->1(N个文件打包压缩到一个文件):
1 module.exports = function (grunt) { 2 banner: '/*! <%= pkg.file %>Qboooogle <%= grunt.template.today("yyyy-mm-dd") %> */\n' 3 }, 4 build: { 5 src: ['build/js/<%=pkg.file %>.js','build/js/<%=pkg.file %>1.js'],7 dest: 'dist/js/<%= pkg.file %>.min.js' 8 } 9 }
N->N(通过my_target):
1 module.exports = function (grunt) { 2 options: { 3 banner: '/*! <%= pkg.file %> Qboooogle <%= grunt.template.today("yyyy-mm-dd") %> */\n' 4 }, 5 my_target : { 6 files : { 7 'dist/js/index.min.js':['build/js/index.js'], 8 'dist/js/index1.min.js':['build/js/index1.js'], 9 'dist/js/index2.min.js':['build/js/index1.js'], 10 'dist/js/index3.min.js':['build/js/index1.js'] 11 } 12 } 13 }
2 less编译打包
N->N
1 less : { 2 development: { 3 options: { 4 compress: true 5 }, 6 files: { 7 "dist/css/index1.css":"build/less/index1.less", 8 "dist/css/index.css" : "build/less/index.less" 9 } 10 } 11 }
N->1(将build/less/下的两个文件编译合并到dist/css/目录下)
1 module.exports = function (grunt) { 2 less : { 3 development: { 4 options: { 5 compress: false 6 }, 7 files: { 8 "dist/css/index.css":["build/less/index1.less","build/less/index.less"] 9 } 10 } 11 }
开发模式与产品模式(唯一区别就是开发模式下,为了进行调试,尽量不压缩文件,而上线版本,最好将其进行压缩)代码表示将build/less/下的两个Less文件转化为dist/css/下的css文件,两者前者为未压缩版本。
1 module.exports = function (grunt) { 2 less : { 3 development: { 4 options: { 5 compress: false 6 }, 7 files: { 8 "dist/css/index.css":["build/less/index1.less","build/less/index.less"] 9 } 10 }, 11 production: { 12 options: { 13 compress: true 14 }, 15 files: { 16 "dist/css/index4.css":["build/less/index1.less","build/less/index.less"] 17 } 18 } 19 }
3 图片优化(将图片进行优化处理,并生成新的文件,存放在另一个文件夹中)这里表示,匹配build/img下面的所有以png,jpg,gif,svg,jpeg格式结尾的文件,并一一进行优化处理,然后将优化后的图片放在dist/img/目录下。
1 image : { 2 dynamic : { 3 files:[{ 4 expand:true, 5 cwd:'build/img/', 6 src:['**/*.{png,jpg,gif,svg,jpeg'], 7 dest:'dist/img/' 8 }] 9 } 10 } 11 });
4 js语法检查(按照自定义的标准,检测绑定的相关js文件是否有语法错误)
1 jshint : { 2 options: { 3 jshintrc :'.jshintrc' 4 }, 5 core: { 6 src:'dist/js/index.min.js' 7 }, 8 demo: { 9 src:'dist/js/index1.min.js' 10 } 11 }
5 监听(watch):通过绑定所有的js文件及less文件,并时时监听文件内容的变化,当变化发生时,将重新编译、压缩、打包生成最新的文件。
1 uglify: { 2 options: { 3 banner: '/*! <%= pkg.file %> Qboooogle <%= grunt.template.today("yyyy-mm-dd") %> */\n' 4 }, 5 build : { 6 src: 'build/js/index.js', 7 dest:'dist/js/index6.min.js' 8 } 9 }, 10 watch: { 11 files: ["build/less/*.less","build/js/*.js"], 12 tasks: ["less", "uglify"] 13 },
6 清理文件(构建成功后,将不再需要的文件删除,比如图片优化之后,之前的图片就可以清理掉了)
1 clean: { 2 build: ["build/img/*"] 3 },
7 css文件校验处理
1 csslint: { 2 options: { 3 csslintrc: 'build/less/.csslintrc' 4 }, 5 dist:[ 6 'dist/css/index1.css', 7 ] 8 }
8 链接Bootstrap HTML 并进行语法检查
1 bootlint: { 2 options: { 3 relaxerror: ['W002','W003','W005','W007'] 4 }, 5 files: ['*.html'] 6 },
9 构建HTML模板
1 includes: { 2 build: { 3 src: ['*.html'], // Source files 4 dest: 'documentation/', // Destination directory 5 flatten: true, 6 cwd: 'documentation/build', 7 options: { 8 silent: true, 9 includePath: 'documentation/build/include' 10 } 11 }
其中css链接处理需要的.jshintrc文件如下:
1 { 2 "adjoining-classes": false, 3 "box-sizing": false, 4 "box-model": false, 5 "compatible-vendor-prefixes": false, 6 "floats": false, 7 "font-sizes": false, 8 "gradients": false, 9 "important": false, 10 "known-properties": false, 11 "outline-none": false, 12 "qualified-headings": false, 13 "regex-selectors": false, 14 "shorthand": false, 15 "text-indent": false, 16 "unique-headings": false, 17 "universal-selector": false, 18 "unqualified-attributes": false, 19 "ids": false, 20 "fallback-colors": false, 21 "vendor-prefix": false, 22 "import": false 23 }
完整的Gruntfile.js文件如下:
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 pkg: grunt.file.readJSON('package.json'), 4 uglify: { 5 options: { 6 banner: '/*! <%= pkg.file %> Qboooogle <%= grunt.template.today("yyyy-mm-dd") %> */\n' 7 }, 8 build : { 9 src: 'build/js/index.js', 10 dest:'dist/js/index6.min.js' 11 } 12 }, 13 watch: { 14 files: ["build/less/*.less","build/js/*.js"], 15 tasks: ["less", "uglify","image","clean"] 16 }, 17 concat: { 18 options: { 19 separator: ';' 20 }, 21 dist: { 22 src:["build/less/index1.less","build/less/index.less"], 23 dest:"build/less/index3.less" 24 } 25 }, 26 less : { 27 development: { 28 options: { 29 compress: false 30 }, 31 files: { 32 "dist/css/index6.css":["build/less/index1.less","build/less/index.less"] 33 } 34 }, 35 production: { 36 options: { 37 compress: true 38 }, 39 files: { 40 "dist/css/index5.css":["build/less/index1.less","build/less/index.less"] 41 } 42 } 43 }, 44 clean: { 45 build: ["build/img/*"] 46 }, 47 uglify: { 48 options: { 49 mangle:true, 50 preserveComments:'some' 51 } 52 }, 53 54 cssmin: { 55 compress: { 56 files: { 57 "dist/css/index.css": [ 58 "build/less/index1.less", 59 "build/less/index.less" 60 ] 61 } 62 } 63 } 64 image: { 65 dynamic: { 66 files: [{ 67 expand: true, 68 cwd: 'build/img/', 69 src: ['**/*.{png,jpg,gif,svg,jpeg}'], 70 dest: 'dist/img/' 71 }] 72 } 73 }, 74 csslint: { 75 options: { 76 csslintrc: 'build/less/.csslintrc' 77 }, 78 dist:[ 79 'dist/css/index1.css', 80 ] 81 }, 82 bootlint: { 83 options: { 84 relaxerror: ['W002','W003','W005','W007'] 85 }, 86 files: ['*.html'] 87 }, 88 includes: { 89 build: { 90 src: ['*.html'], // Source files 91 dest: 'documentation/', // Destination directory 92 flatten: true, 93 cwd: 'documentation/build', 94 options: { 95 silent: true, 96 includePath: 'documentation/build/include' 97 } 98 } 99 } 100 jshint : { 101 options: { 102 jshintrc :'.jshintrc' 103 }, 104 core: { 105 src:'dist/js/index.min.js' 106 }, 107 demo: { 108 src:'dist/js/index1.min.js' 109 } 110 } 111 }); 112 113 grunt.loadNpmTasks('grunt-contrib-jshint'); 114 grunt.loadNpmTasks('grunt-image'); 115 grunt.loadNpmTasks('grunt-contrib-less'); 116 grunt.loadNpmTasks('grunt-contrib-clean'); 117 grunt.loadNpmTasks('grunt-contrib-csslint'); 118 grunt.loadNpmTasks('grunt-bootlint'); 119 grunt.loadNpmTasks('grunt-includes'); 120 grunt.loadNpmTasks("grunt-contrib-concat"); 121 grunt.loadNpmTasks("grunt-contrib-watch"); 122 grunt.loadNpmTasks("grunt-contrib-uglify"); 123 grunt.loadNpmTasks('grunt-contrib-cssmin'); 124 125 grunt.registerTask('link', ['includes']); 126 grunt.registerTask('default', ['includes']); 127 // Linting task 128 //grunt.registerTask('lint', ['jshint', 'csslint', 'bootlint']); 129 130 // The default task (running "grunt" in console) is "watch" 131 //grunt.registerTask('default', ['watch']); 132 }
完整的目录结构如下:
整项目代码下载:Qboooogle