随着 Web 2.0 和 HTML 5 的流行,如今的 Web 应用所能提供的功能和交互能力比以前传统的 Web 应用要强大不少。应用的不少实现逻辑被转移到了浏览器端来实现。浏览器再也不只提供单一的数据接收和展示功能,而是提供更多的用户交互能力。浏览器端所包含的 HTML、CSS 和 JavaScript 代码也变得更加复杂。对于日益复杂的前端代码,须要有更好的流程和工具来管理开发的各个方面,包括初始的代码结构、开发流程和自动化测试等。yeoman 是一个新兴的工具。它结合了 Yo、Grunt 和 Bower 等工具,组成了一个完整的工具集合,提供各类 Web 应用开发中所需的实用功能。javascript
Yeoman能够帮助咱们建立新的开发项目,为咱们提供更好的工具来使咱们的项目更多样化。html
Generators是yeoman生态系统的积木,是经过yo命令运行而为终端用户生产文件的插件。前端
在你须要建立generator的地方建立一个目录,目录要以generator-name命名(name替换成你要建立的generator名称)。命名规则很重要,由于yeoman会经过文件系统来查找可使用的generator。
在上面建立的目录下建立一个package.json文件,该文件是一个Node.js项目的的模块清单.相关介绍请看官网。你能够经过在命令行运行 npm init 来构建package.json文件,固然你也能够手动填充这个文件:java
{ "name": "generator-name", "version": "0.1.0", "description": "", "files": [ "app", "router" ], "keywords": ["yeoman-generator"], "dependencies": { "yeoman-generator": "^0.20.2" } }
其中 name
属性必须以generator-
前缀。keywords
属性必须包含"yeoman-generator" 而且repo
必须有一个引用 generators page索引的描述。node
你必须保证引用了最新版本的yeoman-generator 模块做为依赖.能够经过 npm install --save yeoman-generator
来实现。git
files
属性必须是一个在你的generator里面用到的文件和目录的数组。github
yeoman是深度依赖你组织的文件目录文件系统,每个子generator都有本身的文件夹。web
generator默认把app做为默认的子generator,当你使用yo name
调用的是app子generator。所以你的generator必须包含app/目录。你能够经过yo name:subcommand
命令来调用子generator,他会调用与subcommand彻底同样的文件夹即子generator。npm
下面是示例项目的文件夹结构json
├───package.json ├───app/ │ └───index.js └───router/ └───index.js
经过命令 yo name
和 yo name:router
能够显示出来generator。
若是你不想把全部的文件都放在根目录下面,很幸运的是yeoman支持两种不一样的目录结构 ./
和 generators/
,yeoman会从他们当中注册可用的generators。
因此前一个示例的结构也可用定义成以下:
├───package.json └───generators/ ├───app/ │ └───index.js └───router/ └───index.js
若是你使用这种目录结构,请确保package.json 文件内的 files
属性定义了子generator在generators目录下:
{ "files": [ "generators/app", "generators/router" ] }
当到了这一步你就可用去实现generator的具体内容了
yeoman提供了一个基础的generator让咱们扩展使用以实现本身的目标.基础的generator提供了大部分的功能来缓解你的任务量。
下面是扩展基础generator的方法:
var generators = require('yeoman-generator'); module.exports = generators.Base.extend();
extend
容许你在基础的class上扩展新的本身想要的prototype规范.他的功能是经过Class-extend模块得来的。若是你用过backbone,你会以为他很熟悉。在生态系统中,咱们指定扩展的generator使用module.export来让其有效,就像在nodeJs使用export module同样
有些generator方法只有定义在构造方法内才能被调用到.这些特殊的方法能够作的一些重要的操做等,而这些操做可能在构造以外没法正常运行。
module.exports = generators.Base.extend({ // The name `constructor` is important here constructor: function () { // Calling the super constructor is important so our generator is correctly set up generators.Base.apply(this, arguments); // Next, add your custom code this.option('coffee'); // This method adds support for a `--coffee` flag } });
当generator被调用时,一般状况下里面定义的方法会按照顺序执行,可是咱们将在下一节中看到的,一些特殊的方法名称将触发特定的运行秩序。
下面的一段代码是建立两个自定义的方法
module.exports = generators.Base.extend({ method1: function () { console.log('method 1 just ran'); }, method2: function () { console.log('method 2 just ran'); } });
当运行generator 你会看到会用log打印出来。
当在本地目录内完成上面的建立后,generator还不能被当作全局的npm module ,咱们能够经过在 generator-name/
目录下运行 npm link
来实现generator的全局化。
当使用yo命令来运行generator的生活,yeoman会把 .yo-rc.json
文件所在的目录做为工程的根目录,以后Yeoman将当前文件目录跳转到根目录下运行请求的生成器。当咱们使用this.config.save()的时候,storage模块会建立它。若是.yo-rc.json 不在当前的工做目录,请确保他也不在其余的项目目录里。
咱们推荐在prompting 方法内来定义prompt与用户交互,定义方法以下:
module.exports = generators.Base.extend({ prompting: function () { return this.prompt([{ type : 'input', name : 'name', message : 'Your project name', default : this.appname // Default to current folder name }, { type : 'confirm', name : 'cool', message : 'Would you like to enable the Cool feature?' }]).then(function (answers) { this.log('app name', answers.name); this.log('cool feature', answers.cool); }.bind(this)); } })
在generator内,全部的静态方法都会被做为action而自定执行,固然generator也提供了能够声明不自动执行的辅助函数,generator提供了三种能够建立辅助函数的方法.
1 经过下划线开头定义函数,如:CopyFiles
2 使用实例函数声明:
generators.Base.extend({ constructor: function () { this.helperMethod = function () { console.log('won\'t be called automatically'); }; } });
3 继承一个父级generator:
var MyBase = generators.Base.extend({ helper: function () { console.log('methods on the parent generator won\'t be called automatically'); } }); module.exports = MyBase.extend({ exec: function () { this.helper(); } });
运行顺序
Yeoman是按照优先级顺序依次执行所定义的方法。当你定义的函数名字是Yeoman定义的优先级函数名时,会自动将该函数列入到所在优先级队列中,不然就会列入到 default 优先层级队列中。
基本上执行的顺序以下:
initializing
prompting
configuring
default
writing
conflicts
install
end
Arguments是在命令行中直接传递的。 如:yo webapp my-project,接受键值对的条件。
desc:描述argument
required:定义是否必须
optional:是否可选择的
type:参数类型,支持的类型有String Number Array Object
defaults: argument默认值
banner:字符串显示的使用说明(这是默认提供)
注意:参数必须的定义在construct函数内,不然当你使用generator调用命令(如:yo webapp --help
)的时候,不可以输出相关的帮助信息。
示例:
var _ = require('lodash'); module.exports = generators.Base.extend({ // note: arguments and options should be defined in the constructor. constructor: function () { generators.Base.apply(this, arguments); // This makes `appname` a required argument. this.argument('appname', { type: String, required: true }); // And you can then access it later on this way; e.g. CamelCased this.appname = _.camelCase(this.appname); } });
option和argument很类似,可是option是做为命令行标识使用的,如yo webapp --coffee
。
咱们可能够经过generator.option()添加option。
示例:
module.exports = generators.Base.extend({ // note: arguments and options should be defined in the constructor. constructor: function () { generators.Base.apply(this, arguments); // This method adds support for a `--coffee` flag this.option('coffee'); // And you can then access it later on this way; e.g. this.scriptSuffix = (this.options.coffee ? ".coffee": ".js"); } });
输出消息是经过generator.log模块来处理实现的。不建议使用console.log输出命令。
示例:
module.exports = generators.Base.extend({ myAction: function () { this.log('Something has gone wrong!'); } });
通常当你运行你的generator的时候,你常常须要经过 npm 和 Bower来安装一些generator用到的依赖模块。而这些任务是很是繁琐的,为了方便,yeoman将这部分任务抽离了出来。
你只须要调用generator.npmInstall()
命令就能够执行npm安装命令,yeoman确保了npm install
只执行了一次,即便他被多个generator调用。
例如你想安装lodash做为dev dependency:
generators.Base.extend({ installingLodash: function() { this.npmInstall(['lodash'], { 'saveDev': true }); } });
上面代码等同于调用了npm install lodash --save-dev命令。
你只须要调用generator.bowerInstall()
便可启动安装命令。yeoman确保了bower install
只执行了一次,即便他被多个generator调用。
调用enerator.installDependencies()
便可同时运行npm 和 bower。
yeoman抽离了spawn命令,这个抽离保证了咱们能够在Linux ,mac 以及windows系统上能够很好的运行。
假如你是一个PHP狂热爱好者,你想运行composer
命令,你能够这样作:
generators.Base.extend({ install: function () { this.spawnCommand('composer', ['install']); } });
请确保面spawn命令在install队列里。由于您的用户不肯意等待在那儿直到安装命令完成。
为了方便文件流的输入输出,Yeoman使用两种位置环境。
目标上下文定义为当前工做目录或含.yo-rc.json文件最接近的父文件夹。该.yo-rc.json文件定义了一个generator项目的根目录。该文件容许用户在子目录中运行命令,并让他们在项目中能够运行。这确保了用户行为的一致。
你能够经过generator.destinationRoot()
命令获取目标路径,也能够经过generator.destinationPath('sub/path')
来拼一个路径:
// Given destination root is ~/projects generators.Base.extend({ paths: function () { this.destinationRoot(); // returns '~/projects' this.destinationPath('index.js'); // returns '~/projects/index.js' } });
模板上下文是你保存模板文件的目录,他通常是你要读取和复制的目录。模板上下文通常是默认是定义在 ./templates/
目录的.你能够经过generator.sourceRoot('new/template/path')
命令来重写。你能够经过generator.sourceRoot()
或者generator.templatePath('app/index.js').
来获取路径。
generators.Base.extend({ paths: function () { this.sourceRoot(); // returns './templates' this.templatePath('index.js'); // returns './templates/index.js' } });
当涉及到覆盖用户的文件的时候,yeoman很是的谨慎,基本上,每个write动做都是一个为已经存在的文件解决冲突的过程。帮助用户严重须要覆盖的内容。
generator的this.fs
暴露出全部的文件方法,经过mem-fs editor .
其余相关介绍请看官网
'use strict'; var generators = require('yeoman-generator'); var mkdirp = require('mkdirp'); var yosay = require('yosay'); var chalk = require('chalk'); module.exports = generators.Base.extend({ constructor: function() { generators.Base.apply(this, arguments); this.option('coffee'); this.scriptSuffix = (this.options.coffee ? ".coffee": ".js"); }, initializing: function() { var message = chalk.bgBlack.bold('\nWelcome to webApp\n') + chalk.underline('webApp.github.io\n'); this.log(yosay(message)); }, prompting: function() { var prompts = [{ type:'input', name: 'appName', message: 'input app name .', default: 'webApp' }]; this.prompt(prompts, function (answers) { this.log(answers); }.bind(this)); }, configuring: function() { this.config.save(); }, selfFunction: function () { this.log("执行了自定义方法"); }, writing: function() { this.fs.copyTpl( this.templatePath('index.html'), this.destinationPath('public/index.html'), { title: 'Templating with Yeoman' } ); }, });
原文连接:http://yeoman.io/authoring/
翻译自力谱宿云 LeapCloud 团队_UX成员:Jerry Zhang
力谱宿云 LeapCloud 团队首发:https://blog.maxleap.cn/archi...
欢迎关注微信订阅号:从移动到云端欢迎加入咱们的力谱宿云 LeapCloud 活动QQ群:555973817,咱们将不按期作技术分享活动。如有转载须要,请转发时注意自带做者信息一栏并本自媒体公号:力谱宿云,尊重原创做者及译者的劳动成果~ 谢谢配合~