水墨中国

Grunt 前端自动化工具学习

  • 15-01-02
  • font-end
  • grunt
  • yeoman
  • bower

什么是前端集成解决方案?

草根派:解决前端工程的根本问题

学院派:一套包含框架和工具,便于开发者快速构建美丽实用的 Web 应用程序的工作流,同时这套工作流必须是稳健强壮的。

解决哪些前端问题?

1、开发团队代码风格不统一,如何强制开发规范;

2、前期开发的组件库如何维护和使用;

3、如何模块化前端项目;

4、服务器部署前必须的压缩,检查流程如何简化,流程如何完善

主流的方式有哪些?

1、Yeoman

2、Bower

3、Grunt / Gulp

4、CodeKit

5、FIS

6、Spirit

Grunt 的定位 : 构建工具(build tool)

##Yeoman

定义:现代Web app 的脚手架工具

作用:在 Web 项目的立项阶段,使用 yeoman 来生成项目的文件,代码结构。 Yeoman 自动将最佳实践和工具整合进来,大大加速和方便了我们后续的开发。 包括:代码校验,测试,压缩

安装npm install -g yo

我们可以再 Yeoman 的官方站点http://yeoman.io/generators/查找可以用来生成的 generator,比如说:我们要生成一个 Angular 项目,首先先全局安装该 Angular生成器: npm install -g generator-angular

然后使用该生成器初始化项目: yo angular angular-yo-project 第三个参数为项目的名称。

如果要生成过一个 Webapp 项目,可以用 yo webapp webapp-yo-project

##Bower

定义:Web 的包管理器

安装npm install -g bower

管理文件bower.json

安装组件bower install jquery bower install bootstrap

所有安装的文件默认都在 /bower components 文件夹中,可以在 bowerrc 中修改

如果组件比较小众,没有在 bower 注册,怎么办?

1、通过github的短写安装 bower install jquery/jquery

2、项目完整的github地址 bower install http://github.com/jquery/jquery.git

3、没有在github上立项, 使用URL安装 bower install http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js

手动初始化 bower.json bower init

将项目添加到 dependencies (开发环境中)

bower install angular --save

将项目添加到 devDependencies (生产环境中) bower install angular --save-dev

关于 bowerrc

{
	"directory":"bower_components",
	"proxy":"http://proxy.tencent.com:8080",	//添加代理
	"https-proxy":"https://proxy.tencent.com:8080",
	"timeout":60000		//修改时延
}

##Grunt

定义: Javascript Task Runer, Build Tool

自动化:减少像压缩,编译,单元测试,代码校验这种重复且无业务关联的工作

卸载npm uninstall -g grunt

安装npm install -g grunt-cli

package.json: 用于node.js 包管理,比如Grunt插件安装

Gruntfile.js:Grunt配置问价,配置任务或者自定义任务

手动初始化package.jsonnpm init

安装Grunt到当前目录: npm install grunt --save-dev

手动生成Gruntfile.jsgrunt init

###通配符支持

  • 匹配任何字符,除了 /

? 匹配单个字符,除了 /

** 匹配任何字符,包括 / ,所以用在目录路径里面

{} 逗号分隔的”或“操作

! 排除某个匹配

^ 限定主版本;~ 限定此版本;

##常用 Grunt Tasks##

load-grunt-tasks:将 package.json 文件中所有的依赖项(dependencies & devdependencies),将其载入npm任务。 require('load-grunt-tasks')(grunt)

time-grunt:运行 grunt 任务时显示任务执行所虚耗的时间

grunt-contrib-connect:创建一个 node 服务器,开启项目

grunt-contrib-watch:开始监听所定义的文件,并执行相应定义的任务

grunt-wiredep:配合 bower 将 bowercompents 中的依赖的 css 和 js 写入指定的 html 文件中

注:需要在 html 文件中指明 <!-- bower:<type> --> <!-- endbower --> grunt-contrib-copy:顾名思义,复制源文件到目标文件。

grunt-contrib-clean:删除文件

grunt-jshint:检查 js 代码是否符合规范

grunt-contrib-uglify:压缩 js 文件

grunt-contrib-cssmin:压缩 css 文件

grunt-autoprefixer:css 自动补全厂商前缀

grunt-contrib-imagemin:压缩各类图片(gif, jpeg, jpg, png)

grunt-contrib-htmlmin:压缩 html 文件

grunt-contrib-concat:合并文件

grunt-concurrent:并行执行一些 tasks

grunt-newer:配合 grunt-contrib-watch,检测文件是否是新文件

grunt-rev:根据静态资源内容的变化加上 MD5 版本控制名

grunt-usemin:修改并替换一些 css 或 js 引用,常常配合 rev 使用

注:需要在 html 中指明 <!-- build:<type>(alternate search path) <path> --> <!-- endbuild -->

grunt-concurrent:并行执行一些 task

##组合Task——build

grunt.registerTask('build', [
  'clean:dist',			// 清除 dist 和 .tmp 文件夹
  'wiredep',			// 在 html 中加入bower中的插件 js & css
  'useminPrepare',		// 指定使用usemin 的 html(其中包含<build></build>)
  'concurrent:dist',		// 并行执行 css->.tmp,imagemin->dist,svgmin->dist
  'autoprefixer',		// 补全 .tpm 中 css 的厂商前缀
  'concat',			// 根据useminPrepare,合并 js & css
  'cssmin',			// 压缩 css 并复制到 dist
  'uglify',			// 压缩 js 并复制到 dist
  'copy:dist',			// 复制 ico txt webp fonts 到 dist
  'rev',			// 给所有静态文件加 MD5 版本号
  'usemin',			// 修改 html & css 中的静态文件的名称
  'htmlmin'			// 压缩 html
]);

##组合Task——serve

grunt.registerTask('serve', 'start the server and preview your app, --allow-remote for remote access', function (target) {
  if (grunt.option('allow-remote')) {
    grunt.config.set('connect.options.hostname', '0.0.0.0');
  }
  if (target === 'dist') {
    return grunt.task.run(['build', 'connect:dist:keepalive']);
  }
  grunt.task.run([
    'clean:server',		// 清除 .tmp 文件
    'wiredep',			// 在 html 中加入bower中的插件 js & css
    'concurrent:server',	// 复制 css 到 .tmp
    'autoprefixer',		// 补全 .tpm 中 css 的厂商前缀
    'connect:livereload',	// 开启服务
    'watch'			// 监视代码变化
  ]);
});

##Grunt 自定义任务

###获取/设置配置 可以读取json配置文件: config: grunt.file.readJSON('config.json')

获取json对象的属性 grunt.config('config.key.subkey')

对相应的模板变量 <%= config.key.subkey %>

设置配置端: grunt.config('config', 'value')

###动态更改任务配置,循环执行某个任务 grunt的任务都会放入一个队列顺序执行,但是队列本身是异步执行的,所以下面的这种做法是不会如预期输出:

grunt.registerTask('demo',function(){
  for(var i = 0; i < 5; i++){
    grunt.task.run('t');
  }
  // 期望执行玩5次 t 任务之后打印输出
  // 实际上会立即输出,在 t 任务开始之前
  console.log('run after t');
  // 执行5次 t 之后才会执行这个 final 任务
  grunt.task.run('final');
})

动态耕太任务配置可以利用模板变量来做,由于如上所说得异步,所以不能直接在循环中给模板变量复制,而是要额外做一个任务来接收配置

//假如有这样一个配置
t:{
  target: 'some <%= param %>'
}
// 在这个demo 任我中需要多册调用 t 任务,每次都要设置 param
grunt.registerTask('demo', function(){
  for(var i = 0; i < 5; i++){
    //要一个额外的任务去更改配置
    grunt.task.run('r_wrapper:' + i);
  }
});
// 更改 t 配置并运行
grunt.register('t_wrapper', function( i ){
  grunt.config('param', i);
  grunt.task.run('t');
})

###设置输出文字颜色 grunt.log('test color'.green)

##参考文章 前端工作流

comments powered by Disqus