隨着 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,咱們將不按期作技術分享活動。如有轉載須要,請轉發時注意自帶做者信息一欄並本自媒體公號:力譜宿雲,尊重原創做者及譯者的勞動成果~ 謝謝配合~