Yeoman:Web 应用开发流程与工具

随着 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 的基本结构

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 的配置

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 的多目标配置

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 任务

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 任务

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. 使用添加别名的方式创建的任务

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

清单 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. 插件加载示例

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 库

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

清单 10. bower.json 文件示例

{
  "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 文件

{
    "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 应用中,有助于创建高质量和可维护的应用。

原文出处: IBM DeveloperWorks

文章转载自 开源中国社区 [http://www.oschina.net]

时间: 2024-09-17 23:11:27

Yeoman:Web 应用开发流程与工具的相关文章

《例说51单片机(C语言版)(第3版)》——1-5 MCS-51的开发流程与工具

1-5 MCS-51的开发流程与工具 例说51单片机(C语言版)(第3版) 8x51系统的开发流程与一般单片机微控制器的开发流程类似,其基本开发流程可分为软件与硬件两部分,而这两部分可以并行开发.在硬件开发方面,主要是设计原型电路板(prototype),也就是目标板(target board).在软件开发方面,则是编写源程序(可使用C语言或汇编语言),再经过编译.汇编成为可执行码,然后进行调试/仿真.当完成软件设计后,即可应用在线仿真器(In-Circuit Emulator,ICE),加载该

《例说51单片机(C语言版)(第3版)》一1.5 MCS-51的开发流程与工具

1.5 MCS-51的开发流程与工具 例说51单片机(C语言版)(第3版) 8x51系统的开发流程与一般单片机微控制器的开发流程类似,其基本开发流程可分为软件与硬件两部分,而这两部分可以并行开发.在硬件开发方面,主要是设计原型电路板(prototype),也就是目标板(target board).在软件开发方面,则是编写源程序(可使用C语言或汇编语言),再经过编译.汇编成为可执行码,然后进行调试/仿真.当完成软件设计后,即可应用在线仿真器(In-Circuit Emulator,ICE),加载该

《例说8051:单片机程序设计案例教程》——1-3 8051的开发流程与工具

1-3 8051的开发流程与工具 8051系统的开发流程与一般单片机的开发流程类似,其基本开发流程可分为软件与硬件两部分,而这两部分是并行开发.在硬件开发方面,主要是设计原型电路板(prototype),也就是目标板(target board).在软件开发方面,则是编写源程序(可使用C语言或汇编语言).再经过编译.汇编成为可执行代码,然后进行排错/仿真.当完成软件设计后,即可应用在线仿真器(In-Circuit Emulator,ICE),下载该可执行代码,然后在目标板上进行在线仿真.若软.硬件

《Linux C编程从入门到精通》一第2章 在Linux中编写C语言代码2.1 Linux中C语言程序开发流程和工具介绍

第2章 在Linux中编写C语言代码 Linux C编程从入门到精通 Linux作为一个操作系统,一项重要的功能就是要支持用户编程.传统的UNIX下的程序开发语言是C语言,C语言是一种平台适应性强.易于移植的语言.Linux是用C语言写成的.反过来,Linux又为C语言提供了很好的支持,C语言编译工具gcc.调试工具gdb属于最早开发出来的一批自由软件.因此Linux与C语言形成了完美的结合,为用户提供了一个强大的编程环境,本章将介绍在Linux中编写C语言程序的流程和具体方法. 2.1 Lin

《Linux C编程从入门到精通》——第 2 章 在Linux中编写C语言代码 2.1Linux中C语言程序开发流程和工具介绍

第 2 章 在Linux中编写C语言代码 Linux作为一个操作系统,一项重要的功能就是要支持用户编程.传统的UNIX下的程序开发语言是C语言,C语言是一种平台适应性强.易于移植的语言.Linux是用C语言写成的.反过来,Linux又为C语言提供了很好的支持,C语言编译工具gcc.调试工具gdb属于最早开发出来的一批自由软件.因此Linux与C语言形成了完美的结合,为用户提供了一个强大的编程环境,本章将介绍在Linux中编写C语言程序的流程和具体方法. 2.1 Linux中C语言程序开发流程和工

Yeoman提供各种Web应用开发中所需的实用功能

浏览器端所包含的 HTML.CSS 和 JavaScript 代码也变得更加复杂.对于日益复杂的前端代码,需要有更好的流程和工具来管理开发的各个方面,包括初始的代码结构.开发流程和自动化测试等.Yeoman 是一个新兴的工具.它结合了 Yo.Grunt 和 Bower 等工具,组成了一个完整的工具集合,提供各种 Web 应用开发中所需的实用功能. Yeoman 的最大优势在于它整合了各种流行的实用工具,提供了一站式的解决方案,使得 Web 应用开发中的很多方面变得简单.Yeoman 使得开发人员

Web开发流程规范的五个要点

web|规范 开发流程及规范:Web 开发的分散性和交互性,决定了 Web 开发必须遵从一定的开发规范和技术约定. 只有每个开发人员都按照一个共同的规范去设计.沟通.开发.测试.部署,才能保证整个开发团队协调一致的工作,从而提高开发工作效率,提升工程项目质量. 一. 项目的角色划分 如果不包括前.后期的市场推广和产品销售人员,开发团队一般可以划分为项目负责人.程序员.美工三个角色. 项目负责人在我们中国习惯称为"项目经理",负责项目的人事协调.时间进度等安排,以及处理一些与项目相关的其

《Web前端开发最佳实践》——导读

前 言 Web前端开发入门难度并不高,但是初学者如果没有一个很好的学习和编码习惯,则开发水平的提高速度会变得很慢.下面几点是影响Web前端开发者技术提高的主要因素. 其一是开发者缺乏良好的实践指导.Web前端兴起的时间不长,很多大学都还没有来得及开一门专门讲解Web前端的课程,因此,大部分的Web前端开发者都是通过自学的方式来了解Web前端相关的技术.开发者学习前端技术的渠道很多,其中很大一部分是通过查找网络资源的方式,而网络上充斥着大量的错误或者过时的实践方法,这些实践方法很容易误导初学者,使

web标准下的web开发流程思考

web|web标准 web开发需要考虑三面人的人员:设计师,程序员,客户,项目经理. A.设计师负责平面效果设计 B.程序员负责系统开发 C.客户提出需求验收系统 D.项目经理负责统筹全局 这里就不谈需求分析细节,和与客户谈判的细节了,假定需求已经确定. web标准是结构和表现相分离的,所以设计师和程序员在项目经理需求确定之后,可以并行开发,打破了以往的,平面效果确定系统才能开发的低效率开发流程.什么样的系统都可以拥有MVC式系统的开发效率. 下面是一个流程图 需求确定,系统规划完成之后: 程序