概述
打包的目的和意义就不用叙述了直接上干货
http://www.gruntjs.net/getting-started里面的教程也太简单了,需要下一番功夫去研究才行。本文将grunt打包的常用方法都用实例描述,更加清晰易懂。
1. 第一个简单的grunt打包
1)需要安装nodejs:http://www.cnblogs.com/chuaWeb/p/nodejs-npm.html
本人的nodejs工程目录为F:chuaNodejs(后续所有相对路径都是相对于这个目录)
2)命令行到nodejs目录(需要系统管理员权限,不然后续过程中会报错)执行npm install -g grunt-cli
3)在nodejs工程目录下建一个package.json,内容为
其中file属性在Gruntfile.js中要用到的属性,打包源名称
然后将devDependencies下面的包给下载下来,比如下载grunt: npm install grunt --save-dev 其他包下载方式一样
需要注意的是package.json中的数据必须是严格的json数据格式(连添加注释都是不可以的)。
4) 在nodejs工程目录下建一个Gruntfile.js,内容为
里面pkg读取package.json文件,然后可以访问其内容中的属性,如pkg.file。build属性src是待压缩的文件,dest是压缩重定向到该文件。
所以现在我要建立一个src目录,目录下面保存了一个叫做jquery.js的文件
5)命令行运行:grunt
输出
Running “uglify:build” (uglify) task File dest/jquery.min.js created: 277.14 kB ->93.35 kB >> 1 file created. Done.
创建了dest/jquery.min.js
注意:grunt命令和grunt uglify等价。当然也可以带上任务名称default:grunt default能等到同样结果。
6)总结:
grunt.initConfig:
为当前项目初始化一个配置对象,其中传入的 configObject 参数可以用在后续的task中,可以通过grunt.config 方法访问。几乎每个项目的 Gruntfile 都会调用此方法。
注意,任何 <% %> 模板字符串只会在取到配置数据后才被处理。
不同的插件有各自的参数,比如例子中的uglify插件用到的参数有options和build。详细信息需要参考各个插件。
initConfig详情参考:http://www.gruntjs.net/api/grunt.config#grunt.config.init
grunt.loadNpmTasks:
grunt打包主要是用到各种插件,比如上面的压缩用的插件uglify。加载插件需要使用该方法。
从指定的 Grunt 插件中加载任务。此插件必须通过npm安装到本地,并且是参照 Gruntfile.js 文件的相对路径。
详情参考:http://www.gruntjs.net/api/grunt.task#grunt.task.loadnpmtasks
grunt.registerTask:
注册 "别名任务" 或 任务函数。此方法支持以下两种类型:
别名任务(如果指定了一个任务列表,那么,新注册的任务将会是这一个或多个任务的别名(alias)。当此"别名任务"执行时,taskList中的所有任务都将按指定的顺序依次执行。taskList 参数必须是一个任务数组。):grunt.task.registerTask(taskName, taskList)
上面的例子就是别名任务。定义一个"default" 任务,当执行 Grunt 且不通过参数指定任务时,第二个参数中的任务将依序执行
任务函数(如果传入description和taskFunction,每当任务运行时,指定的函数(taskFunction)都会被执行。此外,当执行 grunt --help时,前面指定的描述(description)就会显示出来。特定任务的属性和方法在任务函数内部通过this对象的属性即可访问。如果任务函数返回false表示任务失败。):grunt.task.registerTask(taskName, description, taskFunction)
下一个例子我们就试一下这个任务函数,现在刚才例子每一个步骤目的就清晰了。
详情参考:http://www.gruntjs.net/api/grunt.task#grunt.task.registertask
2. 使用任务函数方式实现刚才的那个打包。
其他的东西都没有变,Gruntfile.js变成了
1 module.exports = function (grunt) { 2 // 加载提供"uglify"任务的插件 3 grunt.loadNpmTasks('grunt-contrib-uglify'); 4 // 任务函数 5 grunt.registerTask('build', 'uglify 使用 任务函数版', function () { 6 //任务列表 7 var tasks = ['uglify']; 8 // 项目配置 9 grunt.initConfig({ 10 pkg: grunt.file.readJSON('package.json'),//获取解析package.json将内容保存在pkg中 11 }); 12 var uglifyTask = { 13 options: { 14 banner: '/*! <%= pkg.file %> <%= grunt.template.today("yyyy-mm-dd") %> */n' 15 }, 16 build: { 17 src: 'src/<%=pkg.file %>.js', 18 dest: 'dest/<%= pkg.file %>.min.js' 19 } 20 } 21 //将一个或多个任务放入队列中 22 grunt.task.run(tasks); 23 //给当前项目的 Grunt 配置中的uglify属性设置一个值。 24 grunt.config.set("uglify", uglifyTask); 25 }); 26 }
然后去命令行运行: grunt bulid
和第一个不同的是运行命令必须带上了任务名称build。
注意前面提到的任何 <% %> 模板字符串只会在取到配置数据后才被处理。
3. 合并压缩
有些时候为了减少请求需要合并多个文件,且需要压缩。使用uglify即可做到这一点。
Gruntfile.js代码
1 module.exports = function (grunt) { 2 // 项目配置 3 grunt.initConfig({ 4 pkg: grunt.file.readJSON('package.json'),//获取解析package.json将内容保存在pkg中 5 uglify: { 6 options: { 7 banner: '/*! <%= pkg.file %> <%= grunt.template.today("yyyy-mm-dd") %> */n',//压缩目标文件头部注释 8 mangle: false//变量和函数名称不压缩 9 }, 10 my_target: {//该对象名称随意 11 files: { 12 'dest/libs.min.js': ['src/jquery.js', 'src/router.js'] 13 } 14 } 15 } 16 }); 17 // 加载提供"uglify"任务的插件 18 grunt.loadNpmTasks('grunt-contrib-uglify'); 19 // 默认任务 20 grunt.registerTask('default', ['uglify']); 21 }
文件压缩的顺序按照files中定义的数组的顺序压缩。我们可以通过options.mangle来设置变量和函数名称是否压缩。还可以有下面的用法
1 options: { 2 banner: '/*! <%= pkg.file %> <%= grunt.template.today("yyyy-mm-dd") %> */n',//压缩目标文件头部注释 3 mangle: { 4 except: ["jQuery"]//不压缩的关键字列表 5 } 6 }
最终jquery.js和router.js合并压缩成libs.min.js
详情参考:https://www.npmjs.com/package/grunt-contrib-uglify
4. 合并压缩require配置的文件。
首先需要下载grunt-contrib-requirejs插件:npm install grunt-contrib-requirejs --save-dev
比如我们的执行文件main.js使用的是require来模块化加载,代码如下
1 require.config({ 2 baseUrl: "", 3 paths: { 4 "jquery": "src/jquery", 5 "bootstrap": "src/bootstrap.min", 6 "validator": "src/bootstrapValidator.min" 7 }, 8 shim: { 9 "bootstrap":["jquery"], 10 "beyond": ["bootstrap"], 11 "validator": ["bootstrap"] 12 } 13 }); 14 requirejs(['validator'], function (v) { 15 //代码 16 });
我们希望jquery/bootstrap/validator几个文件合并成一个,避免多次请求。
我们新建一个grunt配置文件gruntCfg.json将main.js的require文件配置代码段拷贝到这个配置文件。并写入输入输出目标。源码如下
1 { 2 "requirejs": { 3 "main": { 4 "options": { 5 "baseUrl": "", 6 "paths": { 7 "jquery": "src/jquery", 8 "bootstrap": "src/bootstrap.min", 9 "validator": "src/bootstrapValidator.min" 10 }, 11 "shim": { 12 "bootstrap":["jquery"], 13 "validator": ["bootstrap"] 14 }, 15 "include":["validator","jquery","bootstrap"], 16 "out":"dest/libs.js" 17 } 18 } 19 } 20 }
上面include中我打乱了顺序,为了测试压缩顺序我在三个库的前面都添加了console.log(“我是” + 模块名称)。
修改Gruntfile.js
1 module.exports = function (grunt) { 2 grunt.loadNpmTasks('grunt-contrib-requirejs'); 3 //为了介绍自定义任务搞了一个这个 4 grunt.registerTask('build', 'require', function () { 5 6 //设置requireJs的信息 7 var taskCfg = grunt.file.readJSON('gruntCfg.json'); 8 var requireTask = taskCfg.requirejs; 9 10 //添加人任务列表 11 grunt.task.run(['requirejs']); 12 grunt.config.set("requirejs", requireTask); 13 }); 14 }
好了现在看一下相关文件的文件结构如下
执行build任务:grunt build
文件夹dest下多了一个libs.js文件
打开来看
第一行代码就有我刚才添加的console。继续找我添加的标志的话发现压缩顺序是:jQuery->bootstrap->bootstrapValidator。和我们的shim依赖顺序一致。说明合并压缩的顺序没有问题。
更多详情请查看:https://www.npmjs.com/package/grunt-contrib-requirejs
5. 多任务
我们先看一下使用别名任务来执行多个任务的情况,Gruntfile.js源码如下
1 module.exports = function (grunt) { 2 // 项目配置 3 grunt.initConfig({ 4 pkg: grunt.file.readJSON('package.json'),//获取解析package.json将内容保存在pkg中 5 uglify: { 6 options: { 7 banner: '/*! <%= pkg.file %> <%= grunt.template.today("yyyy-mm-dd") %> */n' 8 }, 9 build: { 10 src: 'src/<%=pkg.file %>.js', 11 dest: 'dest/<%= pkg.file %>.min.js' 12 }, 13 my_target1: { 14 files: { 15 'dest/libs.min.js': ['src/jquery.js', 'src/router.js'] 16 } 17 }, 18 my_target2: { 19 files: { 20 'dest/libs.min2.js': ['src/jquery.js', 'src/router.js'] 21 } 22 } 23 }, 24 requirejs: { 25 "main": { 26 "options": { 27 "baseUrl": "", 28 "paths": { 29 "jquery": "src/jquery", 30 "bootstrap": "src/bootstrap.min", 31 "validator": "src/bootstrapValidator.min" 32 }, 33 "shim": { 34 "bootstrap":["jquery"], 35 "validator": ["bootstrap"] 36 }, 37 "include":["validator","jquery","bootstrap"], 38 "out":"dest/libs.js" 39 } 40 }, 41 "main2": { 42 "options": { 43 "baseUrl": "", 44 "paths": { 45 "jquery": "src/jquery", 46 "bootstrap": "src/bootstrap.min", 47 "validator": "src/bootstrapValidator.min" 48 }, 49 "shim": { 50 "bootstrap":["jquery"], 51 "validator": ["bootstrap"] 52 }, 53 "include":["validator","jquery","bootstrap"], 54 "out":"dest/libs2.js" 55 } 56 } 57 } 58 59 }); 60 // 加载提供"uglify"任务的插件 61 grunt.loadNpmTasks('grunt-contrib-uglify'); 62 grunt.loadNpmTasks('grunt-contrib-requirejs'); 63 // 默认任务 64 grunt.registerTask('default', ['uglify',"requirejs"]); 65 }
执行:grunt
dest文件夹下多出了5个文件
源码解析是:任务列表有两个任务'uglify'和"requirejs",'uglify'有三个子任务:build/ my_target1/ my_target2, "requirejs"有两个子任务main/main2。最终这五个子任务完成后生成的结果就是dest下多出的5个文件。
还可以使用任务函数方式注册多个任务。Gruntfile.js源码如下
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 log: { 4 l1: [1,2,3], 5 l2: 'hello world', 6 l3: false, 7 l4: {name: "chua"}, 8 l5: 1, 9 //这个是不行的l6: undefined, 10 //这个是不行的l7: null 11 l8: function(){alert("test")} 12 } 13 }); 14 15 grunt.registerMultiTask('log','log stuff.', function(){ 16 grunt.log.writeln(this.target + ': ' + this.data); 17 }); 18 }
执行:grunt log
我们使用自定义方式实现先前的多任务Gruntfile.js源码如下
1 module.exports = function (grunt) { 2 // 项目配置 3 grunt.initConfig({ 4 pkg: grunt.file.readJSON('package.json'),//获取解析package.json将内容保存在pkg中 5 log: { 6 uglify: { 7 options: { 8 banner: '/*! <%= pkg.file %> <%= grunt.template.today("yyyy-mm-dd") %> */n' 9 }, 10 build: { 11 src: 'src/<%=pkg.file %>.js', 12 dest: 'dest/<%= pkg.file %>.min.js' 13 }, 14 my_target1: { 15 files: { 16 'dest/libs.min.js': ['src/jquery.js', 'src/router.js'] 17 } 18 }, 19 my_target2: { 20 files: { 21 'dest/libs.min2.js': ['src/jquery.js', 'src/router.js'] 22 } 23 } 24 }, 25 requirejs: { 26 "main": { 27 "options": { 28 "baseUrl": "", 29 "paths": { 30 "jquery": "src/jquery", 31 "bootstrap": "src/bootstrap.min", 32 "validator": "src/bootstrapValidator.min" 33 }, 34 "shim": { 35 "bootstrap":["jquery"], 36 "validator": ["bootstrap"] 37 }, 38 "include":["validator","jquery","bootstrap"], 39 "out":"dest/libs.js" 40 } 41 }, 42 "main2": { 43 "options": { 44 "baseUrl": "", 45 "paths": { 46 "jquery": "src/jquery", 47 "bootstrap": "src/bootstrap.min", 48 "validator": "src/bootstrapValidator.min" 49 }, 50 "shim": { 51 "bootstrap":["jquery"], 52 "validator": ["bootstrap"] 53 }, 54 "include":["validator","jquery","bootstrap"], 55 "out":"dest/libs2.js" 56 } 57 } 58 } 59 } 60 }); 61 // 加载提供"uglify"任务的插件 62 grunt.loadNpmTasks('grunt-contrib-uglify'); 63 grunt.loadNpmTasks('grunt-contrib-requirejs'); 64 65 grunt.registerMultiTask('log','log stuff.', function(){ 66 if(this.target == "uglify"){ 67 //添加人任务列表 68 grunt.task.run(['uglify']); 69 grunt.config.set("uglify", this.data); 70 }else if(this.target == "requirejs"){ 71 //添加人任务列表 72 grunt.task.run(['requirejs']); 73 grunt.config.set("requirejs", this.data); 74 } 75 }); 76 }
执行:grunt log
照样得到先前的结果
说到底和先前的别名任务没有什么不同。
6. 压缩整个文件夹下的js文件
压缩src下的所有js文件,Gruntfile.js源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 uglify: { 4 my_target: { 5 files: [{ 6 expand: true, 7 cwd: 'src', 8 src: '**/*.js', 9 dest: 'dest' 10 }] 11 } 12 } 13 }); 14 grunt.loadNpmTasks('grunt-contrib-uglify'); 15 grunt.registerTask('default', ['uglify']); 16 }
源码文件结构(注意src/router下面还有一个js文件)
执行:grunt
目标文件结构
所以这个方法还是比较方便的,他会遍历源文件夹下的所有文件(包括子文件夹)然后压缩。
刚才上面的方式没有拷贝src文件夹,下面这种方式拷贝了src文件夹
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 uglify: { 4 my_target: { 5 files: [{ 6 expand: true, 7 //cwd: 'src', 8 src: 'src/**/*.js', 9 dest: 'dest' 10 }] 11 } 12 } 13 }); 14 grunt.loadNpmTasks('grunt-contrib-uglify'); 15 grunt.registerTask('default', ['uglify']); 16 }
执行:grunt
目标文件结构变成
src下所有的js都被压缩并保持原来的目录结构。
7. grunt-contrib-requirejs插件的更详细使用
我们用实例来说明。现在我们的文件结构是这样子的
main.js是我们使用require的真实配置文件,源码如下
1 require.config({ 2 baseUrl: "", 3 paths: { 4 "jquery": "src/jquery", 5 "bootstrap": "src/bootstrap.min", 6 "validator": "src/bootstrapValidator.min" 7 }, 8 shim: { 9 "bootstrap":["jquery"], 10 "beyond": ["bootstrap"], 11 "validator": ["bootstrap"] 12 } 13 }); 14 requirejs(['validator'], function (v) { 15 //代码 16 });
Gruntfile.js的源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 "requirejs": { 4 "main": { 5 "options": { 6 "baseUrl": ".", 7 "mainConfigFile": "main.js",//指定配置文件 8 "name": "test",//会将对应的文件压缩到main.js依赖的文件的前面压缩。但是会在main.js非依赖文件后面压缩(比如router.js) 9 "include":["jquery","bootstrap","validator","src/router/router.js"],//要压缩在一起的文件(会包括name对应的文件) 10 "out":"dest/libs.js" 11 } 12 } 13 } 14 }); 15 grunt.loadNpmTasks('grunt-contrib-requirejs'); 16 grunt.registerTask('default', ['requirejs']); 17 }
需要说明的是name指定的文件内容会在main.js配置的依赖文件压缩之前压缩,但是如果include中还包含其他非main.js依赖的文件,则会在main.js非依赖文件后面压缩。
我们的test.js源码为
1 console.log("这是我随便测试用的一个js");
然后我们执行:grunt
结果在dest下生成一个libs.js压缩文件
并且这个文件里面包含的压缩文件的顺序是:router.js->test.js->jquery.js-> bootstrap.min.js-> bootstrapValidator.min.js。
所以说配置include中文件会依序压缩到libs.js,但是main.js依赖的文件会放在最后(依赖会逐层往上查找依赖),而name指定的文件会在非依赖文件之后依赖文件之前压缩。
require模板文件打包
模板文件使用到require工程上的text.js文件,路径:http://github.com/requirejs/text
我们这里建立一个模板文件test.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>test</title> 5 </head> 6 <body> 7 </body> 8 </html>
实际上现在test.html没有用到任何模板相关的运用,我们只是做打包例子,所以不管其他,我们只需要知道模板文件一般是html文件即可
现在工程的文件结构是
Gruntfile.js的源码为
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 "requirejs": { 4 "main": { 5 "options": { 6 baseUrl: ".", 7 paths: { 8 "jquery": "src/jquery", 9 "bootstrap": "src/bootstrap.min", 10 "validator": "src/bootstrapValidator.min", 11 "text": "text"//引入requirejs项目下解析模板引擎 12 }, 13 shim: { 14 "bootstrap":["jquery"], 15 "beyond": ["bootstrap"], 16 "validator": ["bootstrap"] 17 }, 18 "include":["jquery","bootstrap","validator","text!test.html"], "out":"dest/libs.js" 19 } 20 } 21 } 22 }); 23 grunt.loadNpmTasks('grunt-contrib-requirejs'); 24 grunt.registerTask('default', ['requirejs']); 25 }
执行命令行:grunt
dest文件下多了一个libs.js,查看其中是否有模板文件test.html中的内容
说明模板被一同压缩进去了。关键是"text!test.html"这句话。test会将模板test.html解析成js脚本形式。
8. cssmin打包样式文件
需要用npm下载cssmin插件:npm install grunt-contrib-cssmin --save-dev
Gruntfile.js文件源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 cssmin: { 4 compress: { 5 files: { 6 'dest/t.min.css': ["src/t1.css","src/t2.css"] 7 } 8 } 9 } 10 }); 11 12 grunt.loadNpmTasks('grunt-contrib-cssmin'); 13 14 }
命令行执行:grunt cssmin
两个css文件压缩打包到dest/t.min.css
9. htmlmin打包html文件
需要用npm下载cssmin插件:npm install grunt-contrib-htmlmin --save-dev
Gruntfile.js源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 htmlmin: { 4 main: { 5 options:{ 6 removeComments: true, 7 collapseWhitespace: true 8 }, 9 files:{ 10 "dest/test.html": "test.html" 11 } 12 } 13 } 14 }); 15 16 grunt.loadNpmTasks('grunt-contrib-htmlmin'); 17 grunt.registerTask("default",["htmlmin"]); 18 }
执行命令:grunt
test.html压缩到dest/test.html
10. copy拷贝文件
需要下载copy插件npm install grunt-contrib-copy --save-dev
将src文件夹(包括内容和子文件内容)拷贝到dest目录下,Gruntfile.js源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 copy: { 4 main: { 5 expand: true, 6 src: 'src/**', 7 dest: 'dest/' 8 } 9 } 10 }); 11 12 grunt.loadNpmTasks('grunt-contrib-copy'); 13 grunt.registerTask("default",["copy"]); 14 }
运行:grunt
src被完美的拷贝到dest下
只拷贝src的第一层子文件,Gruntfile.js源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 copy: { 4 main: { 5 expand: true, 6 src: 'src/*', 7 dest: 'dest/' 8 } 9 } 10 }); 11 12 grunt.loadNpmTasks('grunt-contrib-copy'); 13 grunt.registerTask("default",["copy"]); 14 }
运行结果
这个时候router是空文件夹。
所以这里我们需要明白路径中“*”只表示当前这一层,“**”表示需要递归子文件夹
如果只是拷贝src中的内容而不用src包裹则需要cwd属性
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 copy: { 4 main: { 5 expand: true, 6 cwd: "src/", 7 src: '*',//也可以是数组形式["*"],可以过滤多种类型 8 dest: 'dest/' 9 } 10 } 11 }); 12 13 grunt.loadNpmTasks('grunt-contrib-copy'); 14 grunt.registerTask("default",["copy"]); 15 }
执行结果是
注意下面这种写法会报错
module.exports = function (grunt) { grunt.initConfig({ copy: { main: { expand: true, cwd: "src", src: '/*',//会报错,不能以/开头,会被认为是绝对路径 dest: 'dest/' } } }); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.registerTask("default",["copy"]); }
拷贝src文件夹下指定类型的文件,Gruntfile.js源码
module.exports = function (grunt) { grunt.initConfig({ copy: { main: { expand: true, src: 'src/*.js', dest: 'dest/' } } }); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.registerTask("default",["copy"]); }
执行:grunt
结果src的js文件随src文件夹被拷贝
递归拷贝src文件夹下所有子文件夹中的js文件
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 copy: { 4 main: { 5 expand: true, 6 src: 'src/**/*.js', 7 dest: 'dest/' 8 } 9 } 10 }); 11 12 grunt.loadNpmTasks('grunt-contrib-copy'); 13 grunt.registerTask("default",["copy"]); 14 }
执行结果
将所有指定类型的文件提取到同一层,Gruntfile.js源码
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 copy: { 4 main: { 5 flatten: true,//所有文件提取到dest下 6 expand: true, 7 src: 'src/**/**.js', 8 dest: 'dest/' 9 } 10 } 11 }); 12 13 grunt.loadNpmTasks('grunt-contrib-copy'); 14 grunt.registerTask("default",["copy"]); 15 }
执行结果
我们发现router/router.js被提取到了目标目录下,这也是flatten的作用
11. 使用contrib-watch和newer实时监听文件更改
这里需要用到两个插件,下载这两个插件
grunt-contrib-watch —— 作用是实现我们一开始需求的“自动化”!它会监听需要处理的文件的变动,一旦有变动就会自动执行相应处理。但是它有一个问题,就是每当监听到一处变动时,就会大费周章地把所有被监听的文件都处理一遍;
grunt-newer —— 作用是处理上方watch的毛病,让watch在监听到某个文件变动时,仅仅对变动的文件进行事务处理。
我们以合并压缩为例,Gruntfile.js源码
1 module.exports = function (grunt) { 2 // 项目配置 3 grunt.initConfig({ 4 uglify: { 5 my_target: {//该对象名称随意 6 files: { 7 'dest/libs.min.js': ['src/jquery.js', 'src/router.js'] 8 } 9 } 10 }, 11 watch: { 12 watchJs: { 13 files: ["src/**/*.js"], 14 tasks: ["newer:uglify"]//一旦监听到files中文件修改,立马触发uglify任务 15 } 16 } 17 }); 18 // 加载提供"uglify"任务的插件 19 grunt.loadNpmTasks('grunt-contrib-uglify'); 20 grunt.loadNpmTasks('grunt-contrib-watch'); 21 grunt.loadNpmTasks('grunt-newer'); 22 // 默认任务 23 grunt.registerTask('default', ['uglify',"watch"]); 24 }
上面watch任务有一个子任务watchJs监听js的变动,一旦监听到files更改就触发uglify任务。
12. 使用autoprefixer自动为CSS规则添加最合适的前缀兼容浏览器
Autoprefixer解析CSS文件并且添加浏览器前缀到CSS规则里,使用Can I Use的数据来决定哪些前缀是需要的。
需要下载grunt-autoprefixer插件
Gruntfile.js源码实例
1 module.exports = function (grunt) { 2 // 项目配置 3 grunt.initConfig({ 4 autoprefixer : { 5 my_target: {//该对象名称随意 6 expand:true, 7 src: "src/**/*.css", 8 dest: "dest/" 9 } 10 }, 11 watch: { 12 watchJs: { 13 files: ["src/**/*.css"], 14 tasks: ["newer:autoprefixer"]//一旦监听到files中文件修改,立马触发任务 15 } 16 } 17 }); 18 // 加载提供"uglify"任务的插件 19 grunt.loadNpmTasks('grunt-autoprefixer'); 20 grunt.loadNpmTasks('grunt-contrib-watch'); 21 grunt.loadNpmTasks('grunt-newer'); 22 // 默认任务 23 grunt.registerTask('default', ['newer:autoprefixer',"watch"]); 24 }
这样监听了所有css更改,每次更改都会先添加浏览器兼容前缀。我们可以放心的在样式文件中按照最新的W3C规范来正常书写CSS而不需要浏览器前缀。
13. 总结
总的来说grunt压缩打包都是基于插件,各种插件的作用可以查看官网文档。
在运行任务函数指定的任务的时候可以通过冒号分割来传递参数。比如下面的例子
module.exports = function (grunt) { //为了介绍自定义任务搞了一个这个 grunt.registerTask('test', '任务函数实例', function (arg1, arg2) { if (arguments.length === 0) { grunt.log.writeln(this.name + " 没有参数"); } else { var join = Array.prototype.join; grunt.log.writeln(this.name + " 的参数有" + join.call(arguments,",")); } }); }
执行:grunt test
打印:
Runing “test” task
test 没有参数
执行:grunt test:1
打印:
Runing “test:1” (test) task
test 的参数有1
执行:grunt test:1:2
打印:
Runing “test:1:2” (test) task
test 的参数有1,2
正常来说我们的html/css/js文件都是用不同的文件夹保存的,所以我们可以分成三种任务来处理。这些任务都可以配置在一起,最后一次性打包,这部分根据各自实际项目情况来处理。
ok,如果你从头到尾看完并把上面的实例执行,那么grunt的基本功能就没有问题了。更多的需要看具体的插件使用了。
码字不容易,求推荐。
最后
以上就是自然背包为你收集整理的grunt打包的全部内容,希望文章能够帮你解决grunt打包所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复