原文转自:http://blog.jobbole.com/62098/

随着 Web 2.0 和 HTML 5 的流行,现在的 Web 应用所能提供的功能和交互能力比之前传统的 Web 应用要强大很多。应用的很多实现逻辑被转移到了浏览器端来实现。浏览器不再只提供单一的数据接收和展现功能,而是提供更多的用户交互能力。浏览器端所包含 的 HTML、CSS 和 JavaScript 代码也变得更加复杂。对于日益复杂的前端代码,需要有更好的流程和工具来管理开发的各个方面,包括初始的代码结构、开发流程和自动化测试等。Yeoman 是一个新兴的工具。它结合了 Yo、Grunt 和 Bower 等工具,组成了一个完整的工具集合,提供各种 Web 应用开发中所需的实用功能。

Yeoman 的最大优势在于它整合了各种流行的实用工具,提供了一站式的解决方案,使得 Web 应用开发中的很多方面变得简单。Yeoman 使得开发人员可以专注于应用本身的实现,而不用在搭建应用的基础结构、进行任务构建和其他辅助任务上花费过多的时间和精力。Yeoman 同时也把一些好的最佳实践自动地引入到项目的开发中。比如当需要在应用中使用第三方的 JavaScript 库时,一般的做法是直接到库的网站上进行下载。而 Yeoman 中基于 Bower 进行依赖管理的做法则是更好的实践方式。

Yeoman 的功能由其所包含的工具来实现。下面分别介绍 Yeoman 中包含的 Yo、Grunt 和 Bower 等工具。

Grunt

Grunt 是一个 JavaScript 任务执行工具,其核心理念是自动化。在 Web 应用开发过程中,会有很多不同的任务需要执行。这些任务与 Web 应用开发中的不同类型的组件和所处的阶段相关。比如对 JavaScript 来说,在开发阶段会需要使用 JSLint 和 JSHint 这样的工具来检查 JavaScript 代码的质量;在构建阶段,从前端性能的角度出发,会需要把多个 JavaScript 文件在合并之后进行压缩。对于 CSS 文件也有类似的任务需要执行。其他的任务还包括压缩图片、合并压缩和混淆 JavaScript 代码以及运行自动化单元测试用例等。所有这些任务都需要进行相应的配置,并通过对应的方式来运行。不同任务的运行方式并不相同,取决于任务本身使用的技 术。比如一些与 JavaScript 相关的任务,如 JSLint 和 JSHint,通过 JavaScript 引擎来运行。对于一般的基于 Java 平台的 Web 应用,如果需要执行 JSLint 任务,需要使用 Rhino 这样的引擎来执行 JavaScript 代码,同时与 Apache Ant、Maven 或 Gradle 这样的构建工具进行集成。这种方式的问题在于不同的任务的配置方式都不相同,并且需要与已有的构建系统进行集成。开发人员需要查询很多的文档才能知道如何 配置并使用这些任务。

Grunt 基于流行的 NodeJS 平台来运行。所有的任务执行都基于统一的平台。Grunt 的优势在于集成了非常多的任务插件。这些插件有些是 Grunt 团队开发的,更多的是由社区贡献的。这些插件使用 NodeJS 标准的模块机制来分发,只需要使用 npm 就可以进行管理。Web 应用只需要通过一个文件来声明所要执行的任务并进行相应的配置,Grunt 会负责任务的运行。通过这种方式,所有任务的配置都在一个文件中管理。

Grunt 的安装过程很简单。只需要运行“npm install -g grunt-cli”命令就可以安装。在安装 Yeoman 时,Grunt 就已经作为一部分被自动安装了。对于一个应用来说,使用 Grunt 需要两个文件。一个是 npm 使用的 package.json。该文件中包含了应用的相关元数据。在该文件中需要通过 devDependencies 来声明对 Grunt 及其他插件的依赖。另外一个文件是 Gruntfile,可以是一个 JavaScript 或 CoffeeScript 文件。该文件的作用是配置应用中所需要执行的任务。在 package.json 文件中声明依赖并安装 Grunt 插件之后,就可以在 Gruntfile 中配置并加载这些任务。通过 grunt 命令可以运行这些任务。不同任务的配置方式相对类似,只是所提供的配置项并不相同。

任务配置

Gruntfile 中的相关配置都包含在一个 JavaScript 方法中。在这个方法中,通过 grunt.initConfig 方法可以对使用的插件进行配置。由于在 Gruntfile 文件中进行配置时,通常会需要使用 package.json 文件中的某些值,一般的做法是把 package.json 的内容读入到某个属性中,方便在代码的其他部分中使用。代码清单1给出了 Gruntfile 的基本结构。调用 initConfig 方法的参数对象中的 pkg 属性表示的是 package.json 的内容。

清单 1. Gruntfile 的基本结构
1
2
3
4
5
module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json')
  });
};

在配置对象中可以包含任意的属性值。不过重要的是执行不同任务的插件所对应的配置项。每个插件的配置项在配置对象中的属性名称与插件的名称相对应。比如 grunt-contrib-concat 插件所对应的配置项属性名称为 concat,如代码清单2所 示。插件 grunt-contrib-concat 的作用是把多个 JavaScript 文件拼接在一起组成单个文件。在该插件的配置项中,src 和 dest 属性分别表示要拼接的 JavaScript 文件和生成的目标文件的名称。其中 src 属性的值使用通配符指定了一系列文件,dest 属性的值中通过 pkg.name 引用了 package.json 文件中定义的属性 name 的值。“<%= %>”是 Grunt 提供的字符串模板的语法格式,用来根据变量值生成字符串。

清单 2. 插件 grunt-contrib-concat 的配置
1
2
3
4
concat: {
  src: ['src/**/*.js'],
  dest: 'dist/<%= pkg.name %>.js'
}

Grunt 的模板使用“<% %>”来进行表达式的分隔,同时也支持表达式的嵌套。在解析模板中包含的内容时,整个配置对象被作为解析时的上下文。也就是说配置对象中包含的属性 都可以直接在模板中引用。除此之外,grunt 对象及其包含的方法也可以在模板中使用。模板有两种形式:第一种是“<%= %>”,用来引用配置对象中的属性值;第二种是“<% %>”,用来执行任意的 JavaScript 代码,通常用来控制代码执行流程。

有的插件允许同时定义多个不同的配置,称为不同的“目标(target)”。这是因为某些任务在不同的条件下所使用的配置并不相同。对于这些不同的目标,可以在配置对象中添加相应名称的属性来表示。代码清单3给 出了 grunt-contrib-concat 插件的另一种配置方式。代码中定义了 common 和 all 两个不同的目标。每个目标的配置并不相同。在运行任务时,通过“grunt concat:common”和“grunt concat:all”来运行不同的目标。如果没有指定具体的目标,而是通过“grunt concat”来直接运行,则会依次执行所有的目标。

清单 3. 插件 grunt-contrib-concat 的多目标配置
1
2
3
4
5
6
7
8
9
10
concat: {
  common: {
    src: ['src/common/*.js'],
    dest: 'dist/common.js'
  },
  all: {
    src: ['src/**/*.js'],
    dest: 'dist/all.js'
  }
}

对于包含了多个目标的配置来说,可以通过 options 属性来配置不同目标的默认属性值。在目标中也可以通过 options 属性来覆写默认值。

任务创建与执行

在 对插件进行配置之后,需要在 Gruntfile 中创建相关的任务。这些任务由 Grunt 负责执行。在加载了 Grunt 插件之后,该插件提供的任务可以被执行。也可以通过 grunt.registerTask 方法来定义新的任务,或是为已有的任务创建别名。在定义一个任务时,需要提供任务的名称和所执行的方法。任务的描述是可选的。代码清单4中给出了一个简单的任务。当通过“grunt sample”运行该任务时,会在控制台输出相应的提示信息。

清单 4. 简单的 Grunt 任务
1
2
3
grunt.registerTask('sample', 'My sample task', function() {
  grunt.log.writeln('This is a sample task.');
});

在定义任务时可以声明任务运行时所需的参数,在通过 grunt 运行任务时可以指定这些参数的值。代码清单5给 出了一个包含参数的任务的示例。任务 profile 在运行时需要提供 2 个参数 name 和 email。在通过 grunt 运行时,使用“grunt profile:alex:alex@example.org”可以把参数值“alex”和“alex@example.org”分别传递给参数 name 和 email。不同的参数之间通过“:”分隔。

清单 5. 包含参数的 Grunt 任务
1
2
3
grunt.registerTask('profile', 'Print user profile', function(name, email) {
  grunt.log.writeln('Name -> ' + name + '; Email -> ' + email);
});

如果要定义的任务类似 grunt-contrib-concat 插件可以支持多个不同的目标,只需要使用 grunt.registerMultiTask 方法来进行定义即可。

除了定义新的任务之外,还可以通过为已有的任务添加别名的方式来创建新的任务。代码清单6给出了一个示例。名为 default 的任务在执行时,会依次执行 jshint、qunit、concat 和 uglify 等任务。当运行 grunt 命令时,如果没有指定任务名称,会尝试运行名为 default 的任务。

清单 6. 使用添加别名的方式创建的任务
1
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);

大部分任务是同步执行的,也可以用异步的方式来执行。如果任务中的某部分需要比较长的时间完成,可以通过异步的方式来完成。代码清单7给出了一个异步执行的任务的示例。通过调用 async 方法可以把当前任务的执行变成异步的。调用 async 方法的返回值是一个 JavaScript 方法。当任务执行完成之后,调用该 JavaScript 方法来通知 grunt。

清单 7. 异步执行的任务
1
2
3
4
5
6
7
grunt.registerTask('asynctask', function() {
  var done = this.async();
  setTimeout(function() {
    grunt.log.writeln('Done!');
    done();
  }, 1000);
});

一个任务可以依赖其他任务的成功执行。当某个任务执行失败之后,剩下的其他任务不会被执行,除非在执行 grunt 命令时使用了“–force”参数。在任务代码中可以通过 grunt.task.requires 方法来声明对其他任务的依赖。如果所依赖的任务没有成功执行,当前任务也不会被执行。当任务对应的 JavaScript 方法在执行时返回 false 时,该任务被认为执行失败。对于异步执行的任务,只需要在调用 async 返回的回调方法时传入 false 参数即可。比如在代码清单7中,可以使用“done(false);”来声明异步任务执行失败。

为了能够在调用 grunt 时使用插件提供的任务,需要使用 grunt.loadNpmTasks 方法来加载插件。代码清单8给出了加载 grunt-contrib-watch 和 grunt-contrib-concat 插件的示例。

清单 8. 插件加载示例
1
2
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');

Bower

在 Web 应用开发中,一般都会使用很多第三方 JavaScript 库,比如 jQuery 和 Twitter Bootstrap 这样的常见库。传统的做法是从这些库的网站上直接下载所需版本的 JavaScript 库文件,放到 Web 应用的某个目录中,然后在 HTML 页面中引用。这种做法的问题在于引入了很多额外的工作量,包括查找所需的 JavaScript 库文件、下载和管理等。一些 JavaScript 库有很多个版本,也依赖于其他 JavaScript 库。对于给定版本的某个 JavaScript 库,需要找到它所依赖的兼容版本的其他 JavaScript 库。这可能是一个递归的过程,会花费很多的时间。Bower 是一个前端库管理工具,可以很好的解决在 Web 应用中引用第三方库时可能遇到的问题。Bower 所提供的功能类似于 Java 开发中会用到的 Apache Ivy、Apache Maven 或 Gradle 等工具。

Bower 也是基于 NodeJS 开发的。只需要使用“npm install -g bower”命令即可安装。Yeoman 在安装时也包含了 Bower。在安装完 Bower 之后,就可以在命令行使用 bower 命令来管理所需的库。通过“bower help”可以查看 Bower 命令行所支持的操作。一般的做法是首先通过“bower search”命令来搜索需要使用的库。如“bower search jquery”可以用来搜索名称中包含 jquery 的库。当找到所需的库之后,可以通过“bower install”命令来安装。如“bower install jquery-ui”可以用来安装 jQuery UI 库。在安装时可以指定库的版本,如“bower install jquery-ui#1.9.2”可以安装 jQuery UI 的 1.9.2 版本。在使用名称来安装库时,要求该库已经注册到 Bower。Bower 也支持从远程或本地 Git 仓库和本地文件中安装库。Bower 会把下载的库文件放在 bower_components 目录中。当库有更新时,通过“bower update”命令来进行更新。当不需要一个库时,通过“bower uninstall”命令来删除。使用“bower list”命令可以列出来当前应用中已经安装的库的信息。

在通过 Bower 安装库之后,可以直接在 HTML 页面中引用,如代码清单 9所示。这要求 Bower 的下载目录是可以公开访问的。

清单 9. HTML 页面中引入 Bower 管理的 JavaScript 库
1
<script src="/bower_components/jquery/jquery.min.js"></script>

与逐一安装所需的库相比,更好的方式是在 bower.json 文件中定义所依赖的库,然后运行“bower install”命令来安装所有的这些库。bower.json 文件的作用类似于 NodeJS 中 package.json。可以直接创建该文件,也可以通过“bower init”命令来以交互式的方式创建。代码清单10给出了 bower.json 文件的示例。使用 dependencies 来声明所依赖的库及其版本。有了 bower.json 文件之后,只需要运行一次“bower install”命令就可以安装所需的全部库。

清单 10. bower.json 文件示例
1
2
3
4
5
6
7
8
9
10
11
{
  "name": "yeoman-sample",
  "version": "0.1.0",
  "dependencies": {
    "sass-bootstrap": "~3.0.0",
    "requirejs": "~2.1.8",
    "modernizr": "~2.6.2",
    "jquery": "~1.10.2"
  },
  "devDependencies": {}
}

Bower 本身的配置可以通过.bowerrc 文件来完成。该文件以 JSON 格式来进行配置。代码清单11给出了.bowerrc 文件的示例。该示例中通过 directory 定义了 Bower 下载库的目录。

清单 11. 配置 Bower 的.bowerrc 文件
1
2
3
{
    "directory": "app/bower_components"
}

Yo

当 打算开始开发一个 Web 应用时,初始的目录结构和基础文件很重要,因为这些是应用开发的基础。有些开发人员选择从零开始进行,或是复制已有的应用。更好的选择是基于已有的模板。 很多 Web 应用程序使用 HTML5 Boilerplate 这样的模板来生成初始的代码结构。这样做的好处是可以直接复用已有的最佳实践,避免很多潜在的问题,为以后的开发打下一个良好的基础。Yo 是一个 Web 应用的架构(scaffolding)工具。它提供了非常多的模板,用来生成不同类型的 Web 应用。这些模板称为生成器(generator)。社区也贡献了非常多的生成器,适应于各种不同的场景。通过 Yo 生成的应用使用 Grunt 来进行构建,使用 Bower 进行依赖管理。

以基本的 Web 应用生成器为例,只需要使用“yo webapp”命令就可以生成一个基本的 Web 应用的骨架。运行该命令之后,会有一些提示信息来对生成的应用进行基本的配置,可以选择需要包含的功能。默认生成的 Web 应用中包含了 HTML5 Boilerplate、jQuery、Modernizr 和 Twitter Bootstrap 等。只需要一个简单的命令,就可以生成一个能够直接运行的 Web 应用。后续的开发可以基于生成的应用骨架来进行。这在很大程度上简化了应用的开发工作,尤其是某些原型应用。

在生成的 Web 应用中包含了一些常用的 Grunt 任务。这些任务可以帮助快速的进行开发。这些任务包括:

  • grunt server:启动支持 Live Reload 技术的服务器。当本地的文件有修改时,所打开的页面会自动刷新来反映最新的改动。这免去了每次手动刷新的麻烦,使得开发过程变得更加方便快捷。
  • grunt test:运行基于 Mocha 的自动化测试。
  • grunt build:构建整个 Web 应用。其中所执行的任务包括 JavaScript 和 CSS 文件的合并、压缩和混淆等操作,以及添加版本号等。

Yeoman

Yeoman 的重要之处在于把各种不同的工具整合起来,形成一套完整的前端开发的工作流程。使用 Yeoman 之后的开发流程可以分成如下几个基本的步骤。

在 开发的最初阶段需要确定前端的技术选型。这包括选择要使用的前端框架。在绝大部分的 Web 应用开发中,都需要第三方库的支持。有的应用可能只使用 jQuery,有的应用会增加 Twitter Bootstrap 库,而有的应用则会使用 AngularJS。在确定了技术选型之后,就可以在 Yeoman 中查找相应的生成器插件。一般来说,基于常见库的生成器都可以在社区中找到。比如使用 AngularJS、Backbone、Ember 和 Knockout 等框架的生成器。

所有的生成器都使用 npm 来进行安装。生成器的名称都使用“generator-”作为前缀,如“generator-angular”、“generator- backbone”和“generator-ember”等。安装完成之后,通过 yo 命令就可以生成应用的骨架代码,如“yo angular”用来生成基于 AngularJS 的应用骨架。

生成的应用骨架中包含了一个可以运行的基本应用。只需要通过“grunt server”命令来启动服务器就可以查看。应用的骨架搭建完成之后,把生成的代码保存到源代码仓库中。团队可以在这个基础上进行开发。开发中的一些常用 任务可以通过 Yeoman 来简化。当需要引入第三方库时,通过 Bower 来搜索并添加。

小结

面 对复杂的 Web 应用的开发,良好的流程和工具支持是必不可少的,可以让日常的开发工作更加顺畅。Yeoman 作为一个流行的工具集,在整合了 Yo、Grunt 和 Bower 等工具的基础上,定义了一个更加完备和清晰的工作流程。通过把一些最佳实践引入到 Web 应用中,有助于创建高质量和可维护的应用。

【转】Yeoman:Web 应用开发流程与工具的更多相关文章

  1. 20个可以帮你简化iOS app开发流程的工具

    这里推荐20个可以帮你简化iOS app开发流程的工具.很多开发者都使用过这些工具,涉及原型和设计.编程.测试以及最后的营销,基本上涵盖了整个开发过程. 原型和设计 有了一个很好的创意后,你要做的不是 ...

  2. flask实战-留言板-Web程序开发流程

    Web程序开发流程 在实际的开发中,一个Web程序的开发过程要设计多个角色,比如客户(提出需求).项目经理(决定需求的实现方式).开发者(实现需求)等,在这里我们假设自己是一个人全职开发.一般来说一个 ...

  3. iOS开发之工具篇-20个可以帮你简化移动app开发流程的工具

    如果想进入移动app开发这个领域,你总能从别的开发者或者网上或者书上找到各种各样的方法和工具,对于新手来说,还没有摸清门路就已经陷入迷茫了.这里推荐20个可以帮你简化app开发流程的工具.很多开发者都 ...

  4. WEB前端开发流程总结

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 WEB前端开发项目流程总结 1.新建项目 ...

  5. web项目开发流程

    对于一个web项目,在实际编码之前,有一些通用的步骤来planning a website: 0.Defining the project (predr0->dr0) 对于外部项目,客户一般会发 ...

  6. 2022年Web前端开发流程和学习路线(详尽版)

    前言 前端侧重于人机交互和用户体验,后端侧重于业务逻辑和大规模数据处理.理论上,面向用户的产品里,所有问题(包括产品.设计.后端.甚至看不见的问题)的表现形式,都会暴露在前端,而只有部分问题(数据问题 ...

  7. 单页web应用开发流程

    用循环的视角审视Web应用开发 框定一个一致的SPA图形用户界面(GUI)和模型 将SPA的原则带回服务器端 聚集于对合适的应用进行早期SPA开发[3]  SPA协调的起点是认识到SPA与脚本和网页编 ...

  8. PC端Web项目开发流程

    从前一直再做前端,突然想到如果有一天领导让自己独立承担一个web 项目的话是否有足够的能力去接这个任务,要学会自己去搭建一些基础的工具信息.所有的这一切在心里都要有个大致的流程,不然真正做的时候难免会 ...

  9. 关于Web应用开发流程的总结

    以下内容为个人工作总结,如果不当,谢谢指出错误. 假设最简单的情况,一个开发人员,开发所有的代码,一个测试人员.一个测试的服务器,一个生产的服务器. 开发人员需要为公司开发一个项目,开发人员首先分析产 ...

随机推荐

  1. Java 集合系列 12 TreeMap

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. wait(), notify(),sleep详解

    在JAVA中,是没有类似于PV操作.进程互斥等相关的方法的.JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的 ...

  3. 5月21日 CSS样式表加阴影

    HTML <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  4. 数据库索引<二> 补充前篇 (上一篇抽风了,这个补上)

    在前一个创建索引中已经大概说了三部分的影响,基本应该注意哪一些.写完上一篇后我感觉有很多地方没有写清楚,所以这篇就是更深入一些的理解索引到底是怎么和数据表关联,怎么快速查询的. 先看一下下面的图,图是 ...

  5. 【转】理解cookie和session机制

    cookie和session机制之间的区别与联系 具体来说cookie机制采用的是在客户端保持状态的方案.它是在用户端的会话状态的存贮机制,他需要用户打开客户端的cookie支持.cookie的作用就 ...

  6. php solr 查询

    $options = array( 'hostname' => 'localhost', 'port' => 8080, 'path' => 'solr/test'); $clien ...

  7. 指定socket文件连接mysql

    1.利用ps aux |grep mysql  查看--socket 路径 2.创建软连接.创建文件 3.登录成功

  8. 使用Zen coding高效编写html代码

    zen-Coding是一款快速编写HTML,CSS(或其他格式化语言)代码的编辑器插件,这个插件可以用缩写方式完成大量重复的编码工作,是web前端从业者的利器. zen-Coding插件支持多种编辑器 ...

  9. 快速配置 Samba 将 Linux 目录映射为 Windows 驱动器,用于跨平台编程

    一.局域网内的 Linux 服务器上操作步骤: 1.安装samba(CentOS Linux): yum install samba system-config-samba samba-client ...

  10. select2 插件

    官网:http://select2.github.io/ Select2是基于jQuery的一个插件,没有引用jQuery,是没有效果的   1.在实现给select2添加placeholder效果的 ...