yeoman-generator入門教程
1. yeoman
Yeoman可以幫助我們創建新的開發項目,為我們提供更好的工具來使我們的項目更多樣化。
2. yeoman-generator
Generators是yeoman生態系統的積木,是通過yo命令運行而為終端用戶生產文件的插件。
3. 構建創建自己的generator
1. 創建 node module
在你需要創建generator的地方創建一個目錄,目錄要以generator-name命名(name替換成你要創建的generator名 稱)。命名規則很重要,因為yeoman會通過文件系統來查找可以使用的generator。 在上面創建的目錄下創建一個package.json文件,該文件是一個Node.js項目的的模塊清單.相關介紹請看官網。你可以通過在命令行運行 npm init 來構建package.json文件,當然你也可以手動填充這個文件:
{
"name": "generator-name",
"version": "0.1.0",
"description": "",
"files": [
"app",
"router"
],
"keywords": ["yeoman-generator"],
"dependencies": {
"yeoman-generator": "^0.20.2"
}
}</code></pre>
其中 name 屬性必須以generator-前綴。keywords 屬性必須包含”yeoman-generator” 并且repo必須有一個引用 generators page索引的描述。
你必須保證引用了最新版本的yeoman-generator 模塊作為依賴.可以通過 npm install –save yeoman-generator來實現。
2.目錄樹
yeoman是深度依賴你組織的文件目錄文件系統,每一個子generator都有自己的文件夾。
generator默認把app作為默認的子generator,當你使用yo name
調用的是app子generator。因此你的generator必須包含app/目錄。你可以通過yo name:subcommand
命令來調用子generator,他會調用與subcommand完全一樣的文件夾即子generator。
下面是示例項目的文件夾結構
```javascript
├───package.json
├───app/
│ └───index.js
└───router/
└───index.js</code></pre>
通過命令 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"
]
}
3. 擴展generator
當到了這一步你就可用去實現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一樣
4. 重寫constructor方法
有些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
}
});
5. 添加自定義方法
當generator被調用時,通常情況下里面定義的方法會按照順序執行,但是我們將在下一節中看到的,一些特殊的方法名稱將觸發特定的運行秩序。
下面的一段代碼是創建兩個自定義的方法
module.exports = generators.Base.extend({
method1: function () {
console.log('method 1 just ran');
},
method2: function () {
console.log('method 2 just ran');
}
});
當運行generator 你會看到會用log打印出來。
6. 運行generator
當在本地目錄內完成上面的創建后,generator還不能被當做全局的npm module ,我們可以通過在generator-name/目錄下運行 npm link 來實現generator的全局化。
7.找到工程根目錄
當使用yo命令來運行generator的生活,yeoman會把 .yo-rc.json文件所在的目錄作為工程的根目錄,之后Yeoman將當前文件目錄跳轉到根目錄下運行請求的生成器。當我們使用 this.config.save()的時候,storage模塊會創建它。如果.yo-rc.json 不在當前的工作目錄,請確保他也不在其他的項目目錄里。
4. 完善generator
### 1.創建用戶交互
我們推薦在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));
}
})
2. 運行上下文
在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();
}
});
3.運行順序
運行順序
Yeoman是按照優先級順序依次執行所定義的方法。當你定義的函數名字是Yeoman定義的優先級函數名時,會自動將該函數列入到所在優先級隊列中,否則就會列入到 default 優先層級隊列中。
基本上執行的順序如下: initializing
prompting
configuring
default
writing
conflicts
install
end
4.generator Arguments
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);
}
});
5. Options
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");
}
});
6. 輸出消息
輸出消息是通過generator.log模塊來處理實現的。不建議使用console.log輸出命令。
示例:
module.exports = generators.Base.extend({
myAction: function () {
this.log('Something has gone wrong!');
}
});
7. 處理依賴關系
一般當你運行你的generator的時候,你經常需要通過 npm 和 Bower來安裝一些generator用到的依賴模塊。而這些任務是非常繁瑣的,為了方便,yeoman將這部分任務抽離了出來。
npm
你只需要調用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命令。
Bower
你只需要調用generator.bowerInstall()即可啟動安裝命令。yeoman確保了bower install只執行了一次,即使他被多個generator調用。
npm && Bower
調用enerator.installDependencies()即可同時運行npm 和 bower。
其他tools
yeoman抽離了spawn命令,這個抽離保證了我們可以在Linux ,mac 以及windows系統上可以很好的運行。
假如你是一個PHP狂熱愛好者,你想運行composer命令,你可以這樣做:
generators.Base.extend({
install: function () {
this.spawnCommand('composer', ['install']);
}
});
請確保面spawn命令在install隊列里。因為您的用戶不愿意等待在那兒直到安裝命令完成。
8. 上下文路徑
為了方便文件流的輸入輸出,Yeoman使用兩種位置環境。
1. 目標上下文
目標上下文定義為當前工作目錄或含.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'
}
});
2. 模板上下文
模板上下文是你保存模板文件的目錄,他一般是你要讀取和復制的目錄。模板上下文一般是默認是定義在./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'
}
});
3. “內存”文件系統
當涉及到覆蓋用戶的文件的時候,yeoman非常的謹慎,基本上,每一個write動作都是一個為已經存在的文件解決沖突的過程。幫助用戶嚴重需要覆蓋的內容。
4. 文件工具
generator的this.fs暴露出所有的文件方法,通過mem-fs editor .
其他相關介紹請看官網
9.完整示例
'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' }
);
},
});
——————————————–END——————————————–
原文鏈接:http://yeoman.io/authoring/
翻譯自 MaxLeap團隊_UX成員:Jerry Zhang
來自:https://blog.maxleap.cn/archives/951