在讲之前先谈谈大致步骤:安装nodejs -> 全局安装grunt -> 项目创建package.json --> 项目安装grunt以及grunt插件 -> 配置Gruntfile.js -> 运行任务
1.安装Node
我们开始之前需要安装Nodejs,如果没有安装的 传送门
安装好了之后,查看是否安装成功,正常是这样的提示
这里建议npm换成淘宝的cnpm,速度杠杠的。
安装命令:
2.安装全局Grunt
安装命令:
cnpm install grunt -g
3.项目创建package.json
在项目根目录下创建package.json文件,文件内容如下
4.项目安装grunt以及grunt插件
我们所需要的插件
插件名称 | 说明 | Github地址 |
grunt-contrib-clean | 清空文件和文件夹 | https://github.com/gruntjs/grunt-contrib-clean |
grunt-contrib-copy | 复制文件和文件夹 | https://github.com/gruntjs/grunt-contrib-copy |
grunt-contrib-concat | 连接、合并文件(没用到) | https://github.com/gruntjs/grunt-contrib-concat |
grunt-contrib-cssmin | (CSS文件)压缩 | https://github.com/gruntjs/grunt-contrib-cssmin |
grunt-contrib-uglify | (JS文件)压缩 | https://github.com/gruntjs/grunt-contrib-uglify |
grunt-filerev | 文件内容hash(MD5)(版本号控制) | https://github.com/yeoman/grunt-filerev |
grunt-usemin | 文件进行引用修改 | https://github.com/yeoman/grunt-usemin |
load-grunt-tasks | oad-grunt-tasks | https://github.com/sindresorhus/load-grunt-tasks |
我们打开我们的项目文件夹,在路径栏中输入cmd然后回车
回车后的界面
打开命令行窗口之后,我们输入安装命令:
cnpm install grunt grunt-contrib-clean grunt-contrib-copy grunt-contrib-concat grunt-contrib-cssmin grunt-contrib-uglify grunt-filerev grunt-usemin load-grunt-tasks --save-dev
5.配置Gruntfile.js (这是重点,重点,重点。重要的事情说三遍。)
先贴一下我的配置,后面慢慢说明
1 module.exports = function (grunt) { 2 require('load-grunt-tasks')(grunt); 3 4 var path = { 5 src : 'test', 6 dest : 'dist', 7 } 8 9 grunt.initConfig({ 10 path : path, 11 clean : {//清空生产文件夹 12 beforebuild : { 13 files : [{ 14 src : ['<%= path.dest %>/'] 15 } 16 ] 17 } 18 }, 19 filerev : {//对css和js文件重命名 20 build : { 21 files : [{ 22 src : ['<%= path.dest %>/**', 23 '!<%= path.dest %>/page/*.html',//html文件不加版本号 24 '!<%= path.dest %>/**/*.{png,jpg,jpeg}']//图片 不需要加版本号 25 } 26 ] 27 } 28 }, 29 useminPrepare : {//声明concat、cssmin、uglify 30 build : { 31 files : [{ 32 src : '<%= path.src %>/page/*.html' 33 } 34 ], 35 36 } 37 }, 38 usemin : {//修改html中的css和js引用 39 html : { 40 files : [{ 41 src : '<%= path.dest %>/page/*.html' 42 } 43 ] 44 } 45 }, 46 copy : {//复制文件 47 build : { 48 files : [{ 49 expand : true,//为true启用cwd,src,dest选项 50 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 51 src : ['**/*.*'],//相对于cwd路径的匹配模式。意思就是 src/**/*.*,匹配src下面所有文件 52 dest : '<%= path.dest %>/'//目标文件路径前缀。 53 } 54 ] 55 } 56 }, 57 cssmin :{ 58 build : { 59 files : [{ 60 expand : true,//为true启用cwd,src,dest选项 61 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 62 src : ['css/*.css'],//相对于cwd路径的匹配模式。意思就是 src/**/*.css,匹配src下面所有css文件 63 dest : '<%= path.dest %>/'//目标文件路径前缀。 64 } 65 ] 66 } 67 }, 68 uglify :{ 69 build : { 70 files : [{ 71 expand : true,//为true启用cwd,src,dest选项 72 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 73 src : ['js/*.js'],//相对于cwd路径的匹配模式。意思就是 src/**/*.js,匹配src下面所有js文件 74 dest : '<%= path.dest %>/'//目标文件路径前缀。 75 } 76 ] 77 } 78 }, 79 }); 80 grunt.registerTask('default', ['clean:beforebuild', 'copy', 'cssmin', 'uglify','filerev', 'usemin']); 81 };
我们前面一直都在安装这个安装那个,但是安装的这些东西怎么用起来了?
首先我们通过学习 grunt入门 了解到插件如何使用,这是官网的例子。
pkg是通过读取package.json生成的json对象。
uglify是 grunt-contrib-uglify 指定的任务名,每个插件都有对应的任务名,可以在对应的github里面查看
grunt.loadNpmTasks('grunt-contrib-uglify'); 从字面上就可以看出来/,加载能够提供"uglify"任务的插件。
grunt.registerTask('default', ['uglify']); 注册别名任务,这个别名任务对应的是一个任务列表
当通过 grunt 别名时,实际是执行列表里的任务,并按顺序执行
这些基本的信息都可以通过官网查看。
我们来说说我们需求,我们需要对静态文件打包压缩,并且需要对静态文件加入版本号而且所有引用静态文件的html或css都得修改文件名,我们的需求明确后来来看看我们怎么做。
第一步:我们需要重新打包,那就需要复制文件,所以我们需要grunt-contrib-copy插件。
在copy之前我们先要确定源文件和目标文件,我这里源文件都放在test文件夹中,目标文件都放在dist文件夹中
我们创建文件路径
1 var path = { 2 src : 'test', 3 dest : 'dist', 4 }
文件路径创建好了,我们来看copy
1 copy : {//复制文件 2 build : { 3 files : [{ 4 expand : true,//为true启用cwd,src,dest选项 5 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 6 src : ['**/*.*'],//相对于cwd路径的匹配模式。意思就是 src/**/*.*,匹配src下面所有文件 7 dest : '<%= path.dest %>/'//目标文件路径前缀。 8 } 9 ] 10 } 11 },
从代码的注释就可以看出一二了。这里说下cwd,src,dest 。
其实这里的源路径是 cwd + src。这才是真正的源路径。dest是目标路径前缀。
我这里的意思是src下面所有的文件,意思就是把 src文件夹 里面的文件复制到 dest文件夹 里。这里可以指定需要复制的具体文件夹或者文件类型
第二步:进行文件压缩,我这里只是针对js和css压缩,对img的压缩可以查看对应的插件,思路都一样。
css压缩需要用到 grunt-contrib-cssmin 插件,该插件对应的任务名为 cssmin
1 cssmin :{ 2 build : { 3 files : [{ 4 expand : true,//为true启用cwd,src,dest选项 5 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 6 src : ['css/*.css'],//相对于cwd路径的匹配模式。意思就是 src/**/*.css,匹配src下面所有文件 7 dest : '<%= path.dest %>/'//目标文件路径前缀。 8 } 9 ] 10 } 11 },
js 压缩需要用到 grunt-contrib-uglify 插件,该插件对应的任务名为 uglify
1 uglify :{ 2 build : { 3 files : [{ 4 expand : true,//为true启用cwd,src,dest选项 5 cwd : '<%= path.src %>/',//所有src指定的匹配都将相对于此处指定的路径(但不包括此路径) 6 src : ['js/*.js'],//相对于cwd路径的匹配模式。意思就是 src/**/*.js,匹配src下面所有文件 7 dest : '<%= path.dest %>/'//目标文件路径前缀。 8 } 9 ] 10 } 11 },
第三步:静态文件重命名,我们这里的版本控制是通过对静态文件重命名来现实的。
重命名需要用到 grunt-filerev 插件,该插件对应的任务名为 filerev
1 filerev : {//对css和js文件重命名 2 build : { 3 files : [{ 4 src : ['<%= path.dest %>/**', 5 '!<%= path.dest %>/page/*.html',//html文件不加版本号 6 '!<%= path.dest %>/**/*.{png,jpg,jpeg}']//图片 不需要加版本号 7 } 8 ] 9 } 10 },
这里只有一个src参数,传的是个数组,我们这里是只想给css和js重命名,其他文件不需要。所以数组第一个参数 src/** 匹配src文件夹中所有文件,后面两个 ! xx,是排除的意思,
第四步:修改html中css和js的引用
修改文件引用需要用到 grunt-usemin 插件,该插件对应的任务名为 usemin
1 usemin : {//修改html中的css和js引用 2 html : { 3 files : [{ 4 src : '<%= path.dest %>/page/*.html' 5 } 6 ] 7 } 8 },
这里也只有一个src参数,给出的是html的地址,如果你还有css 可以这样写
1 usemin : {//修改html中的css和js引用 2 html : { 3 files : [{ 4 src : '<%= path.dest %>/page/*.html' 5 } 6 ] 7 }, 8 css :{ 9 files : [{ 10 src : '<%= path.dest %>/css/*.css' 11 } 12 ] 13 } 14 },
这里需要注意 :usemin 除了需要在 Gruntfile.js中配置外,还需要在需要修改引用的文件中加入指令。 具体可以在github查看,上面有地址。
(但是在idea中我没加也可以,不知道是什么原因。)
1 DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <title>Grunttitle> 5 6 <link href="../../css/common/common.css" type="text/css" rel="stylesheet"> 7 8 head> 9 <body> 10 <div class="wrap"> 11 div> 12 13 <script src="../../js/tools/constants.js">script> 14 15 body> 16 html>
第五步:我们从 复制,压缩,重命名,修改引用都说了一遍,这里还少一个东西,就是我们每次复制之前需要把目标文件夹里面的文件删除掉。
修改文件引用需要用到 grunt-contrib-clean 插件,该插件对应的任务名为 clean
1 clean : {//清空生产文件夹 2 beforebuild : { 3 files : [{ 4 src : ['<%= path.dest %>/'] 5 } 6 ] 7 } 8 },
这里也只有一个src参数,给出目标文件夹的地址。
所有任务到这里就结算了。
我们注册任务别
1 grunt.registerTask('default', ['clean:beforebuild', 'copy', 'cssmin', 'uglify','filerev', 'usemin']);
可以看到,我们这里只是注册了任务,并没有应用插件。我们添加插件是听过 load-grunt-tasks 插件完成的
1 require('load-grunt-tasks')(grunt);
这里指令相当于我们一个个写
1 grunt.loadNpmTasks('xxx');
Gruntfile.js 配置完了之后我们执行grunt命令就可以在目标文件夹中得到我们所需要的文件
这里补充说明几点:
这种写法是动态构建文件对象 传送门
这种写法是文件数组格式 传送门