grunt工具–concat

grunt的话,就不多说了,是一个前端开发者使用的工具,支持很多的功能,比如文件的合并,压缩,合法性验证等等,可以有效的提高前端开发者的工作效率,对于grunt,我也是刚刚开始接触,所以也没有太多可以说明的,这篇文章也不算什么分享,只是自己学习的一些记录吧。

一:概述

grunt是基于nodejs使用的,所以,如果您想要使用grunt的话,那么就要对nodejs有一些基本的了解,而关于nodejs的东西,这里也不做说明,但是如果您想要测试使用grunt的话,还是先在自己电脑上,配置上nodejs,然后安装grunt模块,安装的方法可以参考:grunt 快速入门

二:grunt 的concat模块

作为程序员,对于concat应该是在了解不过了,即:连接,比如在JS中,数组的连接,字符串的连接等,都是使用的concat方法的。

当然,这里的concatJS中的concat还是有区别的,这里的concat是把目标的多个文件,进行合并,输出到一个文件中,这样,就可以减少线上产品所要请求的http次数了,而且对于我们程序的开发,也没有太大的影响,因为我们开发时,依然可以在单独的文件中开发,只有上线时,才做合并。

OK,下面看下grunt是如何配置一些信息,做文件合并处理的,本文主要是参考grunt-contrib-concatgit上的主页,进行的一个简单示例的说明:

grunt-contrib-concatgit地址:gruntjs/grunt-contrib-concat

三:使用方法

首先,在可以在nodejs的文件目录下,新建一个grunt的文件夹,并且在grunt文件夹下,新建一个concat文件,用来测试学习这个concat的模块。

grunt的用来操作文件,需要有两个关键的文件,package.jsonGruntfile.js文件,在concat文件下,新建这两个文件,并且把package.json文件的内容暂时存为以下内容:


{
    "name": "myObject",
    "version": "0.1.0",
    "description": "An example of how to run grunt",
    "author": {
        "name": "zhangyunling",
        "email": "****@qq.com"
    },
    "private": true,
    "dependencies": {
        "grunt": "*",
        "grunt-contrib-concat": "~0.5.0"
  }
}


这篇文章的话,是假定你对于package.jsonGruntfile.js的内容格式是有一定的了解的,而且,这里主要是想说明一下Gruntflie.js的写法,以及如何编辑Gruntfile.js来实现不同合并文件的方式。

Gruntfile.js文件,依然属于nodejs的写法类型,而nodejs的单个JS的模块化中,对外公开的接口,是定义于文件中的module对象中的,所以,在Gruntfile.js中,我们所需要设置的一些信息,都是存放于下面的函数内部的。


module.exports = function(grunt) {
    //这里存放,当调用Gruntfile.js文件时,对外公开的本接口的内容
}


关于module,如有疑问,请参考:Nodejs中的module简介

那么在exports内部,grunt是如何进行初始化的呢,看一个在git中给的例子:


module.exports = function(grunt) {
    //使用grunt.initConfig进行初始化
    grunt.initConfig({
	jshint: {},
	concat: {},
	uglify: {}		
    });
}


由上例中,可以看出,在初始化时,initConfig函数,是传入另一个对象,而这个对象中,又包含很多个对象,比如,在例子中,包含的对象有三个,分别为jshintconcatuglify三个,当然,jshintuglify都是不同于concat的模块,这里暂时不予考虑。

本篇中,只考虑concat的模块,所以,在本篇中的Gruntfile.js中,initConfig对象中,只有一个就是concat模块,所以,我们可以把grunt.initConfig的传入参数简化为如下:


grunt.initConfig({
    concat: {}
});


而对于concat的使用,方法,就得继续看concat对象中的参数设置了,由git的项目介绍中,我们可以看到,concat主要可以分为两类参数,一个是options属性(该属性设置一些参数,作用于所有的task属性),另外一个就是task属性了(这个可以分为很多个),下面就先以一个最简单的例子,来实现这个concat的功能吧。

首先,在之前nodejs/grunt/concat/目录下,新建两个文件夹分别为srcdist文件,src用于存放合并之前的文件,dist文件,用于存放合并之后的文件。

所以我们首先以默认的形式把src文件夹下的a.jsb.js合并为dist文件夹下的myObject.js,那么concat的属性就应该如下的写法:


module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
	concat: {
	    dist: {
		src: ['src/a.js',"src/b.js"],
		dest: 'dist/myObject.js',
	    }
	}
    });
	
    //上面的initConfig,只是为了设置属性的,
    //而你所需要的模块,还得使用下面的方法进行加载
    //否则,当您在控制面板中,输入grunt concat:dist时,
    //会因为无法找到concat方法,而发出警告,并且导致合并失败
    grunt.loadNpmTasks('grunt-contrib-concat');
	
    //而下面的这个,就是当你直接在控制面板中,运行grunt时
    //默认的动作执行,这个可以更好的简化整个流程的运行。
    //比如,我需要先合并,后压缩加密的话,
    //可以直接把默认的任何写出:
    //grunt.registerTask('default', ['concat','uglify']);
    //这样,就会先执行concat方法,再执行uglify方法了,更简洁,自动化
    grunt.registerTask('default', ['concat']);
}


配置好Gruntfile.js如上述代码之后,就可以直接在nodejs的控制面板中,进入到nodejs/grunt/concat的目录下,执行grunt concat:dist的命令,进行a.jsb.js的合并,如果合并成功,则会有下面的提示信息:


Running "concat:dist" (concat) task
File dist/myObject.js created.

Done, without errors.


如果其中的设置,出现了问题,则会有相应的错误提示。

合并成功之后,就可以在dist文件夹下有一个新的myObject.js文件生成,如果本来就有这个文件,则更新该文件,如果没有这个文件,则创建这个文件。

这里呢,合并的文件都是按照默认的情况下进行的,也就是options的内容都没有改变,那么options可以修改哪些内容呢?

看下git源码的介绍处,给出的options的属性,分别为:
1,separator:分隔符,就像是把字符串链接一样,这个作为字符串连接的分隔符,而该处,则作为文件的合并时的分隔符,该值默认为换行符,如果您需要修改分隔符,那么可以在options中,修改separator的值,比如改为分号“;”。

那么concat对象的值,就要跟着做下面的修改了:


concat: {
    options:{
	separator:";"
    },
    dist: {
       src: ['src/a.js',"src/b.js"],
       dest: 'dist/myObject.js',
    }
}


2,banner属性:是不是记得在一些源码的文件中,文件最开头都有一些注释,表面该源码的版本,作者等信息,这就是banner的信息表示,默认情况下,是没有banner的,所以如果您要添加一个banner的话,则可以在options的对象中,添加banner的属性,并且设置一个字符串类型的值,那么在合并之后的文件中,该banner就会出现在合并的文件的开头位置。

3,footer属性:于banner相同,只是显示的位置,footer是显示在合并文件的末尾位置,所以如果您可以修改options的内容如下,来测试bannerfooter的属性。


concat: {
    options:{
	banner:"//edit by zhangyunling! this is a banner!\n\n",
	footer:"\n\n//this is a footer."
    },
    dist: {
        src: ['src/a.js',"src/b.js"],
	dest: 'dist/myObject.js',
    }
}


当然啦,如果您添加的bannerfooter是注释的话,还是要添加注释符的,并且,记得添加换行符,否则,就会直接和头尾连在一起了。

3,stripBanners属性,说是是否会考虑源文件中的banner,默认值为false,就是,不管源文件的banner的属性,如果在第一个文件(这里是a.js)的源文件开头位置,有类似banner的注释,那么合并之后的文件,会有两个banner出现,options添加的banner位于最开始的位置。

如果把该属性设置成true,那么在合并之后的文件中,a.js文件中的banner被过滤掉,合并之后的文件中,只包含options.banner的值。

4,process,这个会和bannerfooter有关,取值可以分为四种:
false,true,data,这三种,我还没有看出来,到底有什么区别~~

而第四种,是给了一个实例:


options: {
    // Replace all 'use strict' statements in the code with a single one at the top
    banner: "'use strict';\n",
    process: function(src, filepath) {
    return '// Source: ' + filepath + '\n' +
	src.replace(/(^|\n)[ \t]*('use strict'|"use strict");?\s*/g, '$1');
    },
}


通过该processs,则会把在banner中,添加一个//Source:filepath的路径
并且,可以去掉文中的use strict的字样

另外,options还有其他一些属性,包括:sourceMapsourceMapNamesourceMapStyle,对于这三种属性,到底是在执行什么样的逻辑,表示暂时还不能理解。

所以关于options的属性,只要先知道separator,banner,footer即可。

下面继续看,如果我们不知道需要合并的文件有多少,甚至不知道具体的路径呢?所以,grunt提供了模糊匹配的功能,你可以按照以下的写法:


grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
	options:{
	    banner:"//edit by <%= pkg.author.name %>! this is a banner!\n\n"
	},
	dist: {
	    src: ['src/**/*.js'],
            dest: 'dist/myObject.js',
	}
    }
});


如果,我需要最后合并,并且最终输出到两个不同的文件呢,又该如何?其实就像是添加dist方法,我们再添加一个extra(这个方法名,并不是固定的,不管你命名为何,只要这个方法内部,包含srcdest即可)方法即可。

所以,可以分别如下的方法实现:


grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
	options:{
	    banner:"//edit by <%= pkg.author.name %>! this is a banner!\n\n"
	},
	dist: {
	    src: ['src/a/a.js','src/a/b.js'],
	    dest: 'dist/a.js'
	},
	extra:{
	    src: ['src/b/a.js','src/b/b.js'],
	    dest: 'dist/b.js'
	},
	asdasd:{
	    src: ['src/asdasd/a.js','src/asdasd/b.js'],
	    dest: 'dist/asdasd.js'
	}
    }
});


并且,按照代码中的信息,分别建立文件夹,和对应的js文件。然后在nodejs的控制面板中,执行grunt concat,就会把上述的三个文件合成出来。

当然,如果你只是想要合并单一的文件的话,就可以分别在控制面板输入:grunt concat:dist生成a.js,输入grunt concat:extra生成b.js,输入grunt concat:asdasd生成asdasd.js

是不是也会觉得,如果我要生成的文件很多的话,这样写,是不是有点麻烦了,所以,也有一种更简单的写法,写法如下:


grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
	dist: {
	    options:{
		banner:"//edit by <%= pkg.author.name %>! this is a banner!\n\n"
	    },
	    files:{
		"dist/a.js":['src/a/a.js','src/a/b.js'],
		"dist/b.js":['src/b/a.js','src/b/b.js'],
		"dist/asd.js":['src/asdasd/a.js','src/asdasd/b.js']
	    }
	},
	asdasd: {
	    options:{
		banner:"//edit by <%= pkg.author.name %>! this is a banner!\n\n"
	    },
	    files:{
		"dist/a2.js":['src/a/a.js','src/a/b.js'],
		"dist/b2.js":['src/b/a.js','src/b/b.js'],
		"dist/asd2.js":['src/asdasd/a.js','src/asdasd/b.js']
	    }
	}
    }
});


同样,这里也可以通过grunt concat:distgrunt concat:asdasd的命令分别编译对于的文件。而distasdasd的命名,也是没有任何要求的,只要不同即可,但是内部的files的命名,却是要固定的。

OK,关于编译grunt concat的介绍,就先到这里,对于我这个初学者来说,现在这些,也是已经足够我使用的了,有些东西,还得慢慢发掘。

本文地址:http://www.zhangyunling.com/?p=253

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>