[记录]如何用Grunt来简化工作

对于互联网应用(直白点,就是Web网站),几乎离不开Javascript.而压缩混淆javascript,这样一个普遍的工作就可以使用Grunt来完成.(其实就是我想用来压缩,混淆我的js)

我的环境:Linux64位,非root权限用户

安装

Grunt基于Node.js,安装之前要先安装Node.js,某些linux系统的软件源有提供,可以使用你自己常用的命令安装,比如:

sudo apt-get install nodejs  #软件名根据实际修改

如果没有提供nodejs的安装,可以到github下载,自行编译安装:

git clone  https://github.com/joyent/node.git           #需要有git
cd node
./configure
make
sudo make install

上面安装完nodejs环境,下面开始安装grunt.
grunt或者grunt使用的各个插件都使用nodejs的npm进行安装,大概的命令为:

sudo npm install grunt
sudo npm install -g grunt-cli

 使用

grunt可以用来完成很多自动化工作内容,但我主要用来完成以下任务:合并/压缩js,压缩css;
这些工作主要用到的插件是:grunt-contrib-concat / grunt-contrib-uglify / grunt-contrib-cssmin ;
grunt需要两个文件:package.json和Gruntfile.js,
package.json主要用来描述项目项目的信息,具体的工作命令在Gruntfile.js中进行配置.

package.json文件

我是直接使用npm init来生成package.json文件的,大概步骤是:转到某个目录,一般就是资源文件的根目录,然后执行命令npm init,会提示你输入一些信息,完成之后就会生成一个package.json文件;

Gruntfile.js文件

Gruntfile.js是具体任务的命令说明文件,需要有一定的"语法",大概像下面这样:

module.exports = function(grunt) {
	//目标目录
	var destPath='最后生成的文件的目录路径,我用绝对路径,因为在另外一个很遥远的地方';

	// 具体工作内容
	grunt
			.initConfig({
				pkg : grunt.file.readJSON('package.json'),
				concat:{ //合并
					webgroup_js:{
						src:'js/*.js',
						dest:'build/js/<%= pkg.name %>.js'
					},
					webgroup_css:{
						src:'css/*.css',
						dest:'build/css/<%= pkg.name %>.css'
					}
				},
				//压缩js
				uglify : {
					options : {
						banner : '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
					},
					build : {
						src : 'build/js/<%= pkg.name %>.js',
						dest : destPath+'build/js/<%= pkg.name %>.min.js'
					},
					localstorage:{
						src:'js/localstorage/localstorage.js',
						dest:destPath+'build/js/localstorage.min.js'
					}
				},
				//压缩css
				cssmin:{
					options:{
						banner : '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
						beautify:{
							//说可以防止中文乱码?
							ascii_only:true
						}
					},
					build:{
						src:'build/css/<%= pkg.name %>.css',
						dest:destPath+'build/css/<%= pkg.name %>.min.css'
					}
				}
			});

	//加载需要的插件,上面任务要用到的,这里就加载了
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-cssmin');
	grunt.loadNpmTasks('grunt-contrib-uglify');

	// 注册任务,在命令行:grunt 任务名,就会调用对应的任务了
	grunt.registerTask('default', ['concat','cssmin', 'uglify' ]);
	grunt.registerTask('localstorage',['uglify:localstorage']);
	
};

上面用到的插件,需要先安装,可以使用以下命令:

sudo npm install grunt-contrib-uglify --save-dev   #在package.json目录执行该命令,执行完后(加--save-dev会在package.json中添加相应记录)
sudo npm install grunt-contrib-concat --save-dev
sudo npm install grunt-contrib-cssmin --save-dev

Grunt的具体实例

下面通过cssmin模块,演示如何编写Gruntfile.js文件。cssmin模块的作用是最小化CSS文件。

首先,在项目的根目录下安装该模块。

npm install grunt-contrib-cssmin --save-dev

然后,新建文件Gruntfile.js。

module.exports = function(grunt) {
	grunt.initConfig({
		cssmin : {
			minify : {
				expand : true,
				cwd : 'css/',
				src : [ '*.css', '!*.min.css' ],
				dest : 'css/',
				ext : '.min.css'
			},
			combine : {
				files : {
					'css/out.min.css' : [ 'css/part1.min.css',
							'css/part2.min.css' ]
				}
			}
		}
	});
	grunt.loadNpmTasks('grunt-contrib-cssmin');
	grunt.registerTask('default', [ 'cssmin:minify', 'cssmin:combine' ]);
};

下面详细解释上面代码中的三个方法,下面一个个来看。

(1)grunt.initConfig

grunt.initConfig方法用于模块配置,它接受一个对象作为参数。该对象的成员与使用的同名模块一一对应。由于我们要配置的是cssmin模块,所以里面有一个cssmin成员(属性)。

cssmin(属性)指向一个对象,该对象又包含多个成员。除了一些系统设定的成员(比如options),其他自定义的成员称为目标 (target)。一个模块可以有多个目标(target),上面代码里面,cssmin模块共有两个目标,一个是“minify”,用于压缩css文 件;另一个是“combine”,用于将多个css文件合并一个文件。

每个目标的具体设置,需要参考该模板的文档。就cssmin来讲,minify目标的参数具体含义如下:

  • expand:如果设为true,就表示下面文件名的占位符(即*号)都要扩展成具体的文件名。
  • cwd:需要处理的文件(input)所在的目录。
  • src:表示需要处理的文件。如果采用数组形式,数组的每一项就是一个文件名,可以使用通配符。
  • dest:表示处理后的文件名或所在目录。
  • ext:表示处理后的文件后缀名。

除了上面这些参数,还有一些参数也是grunt所有模块通用的。

  • filter:一个返回布尔值的函数,用于过滤文件名。只有返回值为true的文件,才会被grunt处理。
  • dot:是否匹配以点号(.)开头的系统文件。
  • makeBase:如果设置为true,就只匹配文件路径的最后一部分。比如,a?b可以匹配/xyz/123/acb,而不匹配/xyz/acb/123。

关于通配符,含义如下:

  • *:匹配任意数量的字符,不包括/。
  • ?:匹配单个字符,不包括/。
  • **:匹配任意数量的字符,包括/。
  • {}:允许使用逗号分隔的列表,表示“or”(或)关系。
  • !:用于模式的开头,表示只返回不匹配的情况。

比如,foo/*.js匹配foo目录下面的文件名以.js结尾的文件,foo/**/*.js匹配foo目录和它的所有子目录下面的文件名以.js结尾的文件,!*.css表示匹配所有后缀名不为“.css”的文件。

使用通配符设置src属性的更多例子:
{src: 'foo/th*.js'}grunt-contrib-uglify {src: 'foo/{a,b}*.js'} {src: ['foo/a*.js', 'foo/b*.js']}

至于combine目标,就只有一个files参数,表示输出文件是css子目录下的out.min.css,输入文件则是css子目录下的part1.min.css和part2.min.css。

files参数的格式可以是一个对象,也可以是一个数组。
files: { 'dest/b.js': ['src/bb.js', 'src/bbb.js'], 'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'], }, // or files: [ {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'}, {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}, ],

如果minify目标和combine目标的属性设置有重合的部分,可以另行定义一个与minify和combine平行的options属性。
grunt.initConfig({ cssmin: { options: { /* ... */ }, minify: { /* ... */ }, combine: { /* ... */ } } });

(2)grunt.loadNpmTasks

grunt.loadNpmTasks方法载入模块文件。

(3)grunt.registerTask

grunt.registerTask方法定义如何调用具体的任务。“default”任务表示如果不提供参数,直接输入grunt命令,则先运行 “cssmin:minify”,后运行“cssmin:combine”,即先压缩再合并。如果只执行压缩,或者只执行合并,则需要在grunt命令后 面指明“模块名:目标名”。
grunt # 默认情况下,先压缩后合并 grunt cssmin:minify # 只压缩不合并 grunt css:combine # 只合并不压缩

如果不指明目标,只是指明模块,就表示将所有目标依次运行一遍。
grunt cssmin

常用模块设置

grunt的模块已经超过了2000个,且还在快速增加。下面是一些常用的模块(按字母排序)。

  • grunt-contrib-clean:删除文件。
  • grunt-contrib-compass:使用compass编译sass文件。
  • grunt-contrib-concat:合并文件。
  • grunt-contrib-copy:复制文件。
  • grunt-contrib-cssmin:压缩以及合并CSS文件。
  • grunt-contrib-imagemin:图像压缩模块。
  • grunt-contrib-jshint:检查JavaScript语法。
  • grunt-contrib-uglify:压缩以及合并JavaScript文件。
  • grunt-contrib-watch:监视文件变动,做出相应动作。

模块的前缀如果是grunt-contrib,就表示该模块由grunt开发团队维护;如果前缀是grunt(比如grunt-pakmanager),就表示由第三方开发者维护。

以下选几个模块,看看它们配置参数的写法,也就是说如何在grunt.initConfig方法中配置各个模块。

grunt-contrib-jshint

jshint用来检查语法错误,比如分号的使用是否正确、有没有忘记写括号等等。它在grunt.initConfig方法里面的配置代码如下。
jshint: { options: { eqeqeq: true, trailing: true }, files: ['Gruntfile.js', 'lib/**/*.js'] },

上面代码先指定jshint的检查项目,eqeqeq表示要用严格相等运算符取代相等运算符,trailing表示行尾不得有多余的空格。然后,指定files属性,表示检查目标是Gruntfile.js文件,以及lib目录的所有子目录下面的JavaScript文件。

grunt-contrib-concat

concat用来合并同类文件,它不仅可以合并JavaScript文件,还可以合并CSS文件。
concat: { js: { src: ['lib/module1.js', 'lib/module2.js', 'lib/plugin.js'], dest: 'dist/<a title="script" href="http://www.xidige.com">script</a>.js' } css: { src: ['style/normalize.css', 'style/base.css', 'style/theme.css'], dest: 'dist/screen.css' } },

js目标用于合并JavaScript文件,css目标用语合并CSS文件。两者的src属性指定需要合并的文件(input),dest属性指定输出的目标文件(output)。

grunt-contrib-uglify

uglify模块用来压缩代码,减小文件体积。
uglify: { options: { banner: bannerContent, sourceMapRoot: '../', sourceMap: 'distrib/'+name+'.min.js.map', sourceMapUrl: name+'.min.js.map' }, target : { expand: true, cwd: 'js/origin', src : '*.js', dest : 'js/' } },

上面代码中的options属性指定压缩后文件的文件头,以及sourceMap设置;target目标指定输入和输出文件。

grunt-contrib-copy

copy模块用于复制文件与目录。
copy: { main: { src: 'src/*', dest: 'dest/', }, },

上面代码将src子目录(只包含它下面的第一层文件和子目录),拷贝到dest子目录下面(即dest/src目录)。如果要更准确控制拷贝行为,比如只拷贝文件、不拷贝目录、不保持目录结构,可以写成下面这样:
copy: { main: { expand: true, cwd: 'src/', src: '**', dest: 'dest/', flatten: true, filter: 'isFile', }, },

grunt-contrib-watch

watch模块用来在后台运行,监听指定事件,然后自动运行指定的任务。
watch: { scripts: { files: '**/*.js', tasks: 'jshint', options: { livereload: true, }, }, css: { files: '**/*.sass', tasks: ['sass'], options: { livereload: true, }, }, },

设置好上面的代码,打开另一个进程,运行grunt watch。此后,任何的js代码变动,文件保存后就会自动运行jshint任务;任何sass文件变动,文件保存后就会自动运行sass任务。

需要注意的是,这两个任务的options参数之中,都设置了livereload,表示任务运行结束后,自动在浏览器中重载(reload)。这需要在浏览器中安装livereload插件。安装后,livereload的默认端口为localhost:35729,但是也可以用livereload: 1337的形式重设端口(localhost:1337)。

其他模块

下面是另外一些有用的模块。

(1)grunt-contrib-clean

该模块用于删除文件或目录。
clean: { build: { src: ["path/to/dir/one", "path/to/dir/two"] } }

(2)grunt-autoprefixer

该模块用于为CSS语句加上浏览器前缀。
autoprefixer: { build: { expand: true, cwd: 'build', src: [ '**/*.css' ], dest: 'build' } },

(3)grunt-contrib-connect

该模块用于在本机运行一个Web Server。
connect: { server: { options: { port: 4000, base: 'build', hostname: '*' } } }

connect模块会随着grunt运行结束而结束,为了使它一直处于运行状态,可以把它放在watch模块之前运行。因为watch模块需要手动中止,所以connect模块也就会一直运行。

(4)grunt-htmlhint

该模块用于检查HTML语法。
htmlhint: { build: { options: { 'tag-pair': true, 'tagname-lowercase': true, 'attr-lowercase': true, 'attr-value-double-quotes': true, 'spec-char-escape': true, 'id-unique': true, 'head-script-disabled': true, }, src: ['index.html'] } }

上面代码用于检查index.html文件:HTML标记是否配对、标记名和属性名是否小写、属性值是否包括在双引号之中、特殊字符是否转义、HTML元素的id属性是否为唯一值、head部分是否没有script标记。

(5)grunt-contrib-sass模块

该模块用于将SASS文件转为CSS文件。
sass: { build: { options: { style: 'compressed' }, files: { 'build/css/master.css': 'assets/sass/master.scss' } } }

上面代码指定输出文件为build/css/master.css,输入文件为assets/sass/master.scss。

(6)grunt-markdown

该模块用于将markdown文档转为HTML文档。
markdown: { all: { files: [ { expand: true, src: '*.md', dest: 'docs/html/', ext: '.html' } ], options: { <a title="template" href="http://www.xidige.com/">template</a>: 'templates/index.html', } } },

上面代码指定将md后缀名的文件,转为docs/html/目录下的html文件。template属性指定转换时采用的模板,模板样式如下。
<!DOCTYPE html> <html> <head> <title>Document</title> </head> <body> <div id="main" class="container"> <%=content%> </div> </body> </html>

 

» 本文链接地址:https://www.xidige.com/871

打开支付宝扫一扫,即可进行扫码打赏哦

扫码支持
扫码打赏,你说多少就多少

标签:

分享到:

扫一扫 在手机阅读、分享本文

上一篇: 下一篇:
评论区0人评论447人参与

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

*

loading

赞助商广告