使用yeoman構(gòu)建angular應(yīng)用的方法
本文將介紹如何親手來(lái)完成一個(gè)yeoman的generator,以實(shí)現(xiàn)快速構(gòu)建最適合自己的項(xiàng)目。
本文將實(shí)現(xiàn)的generator起名為ngtimo,依照yeoman的命名規(guī)矩就叫做generator-ngtimo,是筆者這周末一晚上加一上午參考著yeoman官方給出的幾個(gè)generator(generator-generator、generator-node)給強(qiáng)行催生出來(lái)的,目前也已經(jīng)在github上托管并發(fā)布到npm。
實(shí)現(xiàn)效果
首先確保已經(jīng)全局安裝了yeoman,然后再全局安裝generator-ngtimo:
npm install -g generator-ngtimo
安裝完成后即可使用yo命令來(lái)進(jìn)行構(gòu)建:
yo ngtimo
然后順利的話yeoman會(huì)像下面這樣詢問(wèn)一系列構(gòu)建的配置,這里筆者選擇輸入項(xiàng)目名稱為ng-test剩下的一路敲回車:

順利的話如下圖這樣的項(xiàng)目結(jié)構(gòu)就誕生了,可以 cd 到項(xiàng)目目錄下(自動(dòng)執(zhí)行的 npm install 失敗的話再手動(dòng)
npm install 一下),并運(yùn)行 npm run server 啟動(dòng)項(xiàng)目查看效果。

如果只是想要使用yeoman來(lái)快速進(jìn)行項(xiàng)目搭建的話,只需要找到一個(gè)喜歡的generator,像上文這樣全局安裝然后yo它就可以了!不過(guò)只是使用別人的generator會(huì)有些不自由而且考驗(yàn)對(duì)方的維護(hù)能力,就像筆者這個(gè)一時(shí)興起的ngtimo就才剛剛有了一個(gè)主模板而已,還需要做很多改進(jìn)和迭代。
如果想要自己來(lái)編寫一個(gè)generator其實(shí)難度也非常小,yeoman官方甚至給出了一個(gè)generator-generator來(lái)幫助我們創(chuàng)建一個(gè)generator,筆者這個(gè)不成器的ngtimo也是yo generator給yo出來(lái)然后加以養(yǎng)成的 :)。
yeoman generator基本項(xiàng)目結(jié)構(gòu)
不想自己從零開(kāi)始寫一個(gè)generator的話強(qiáng)烈推薦使用yeoman官方的generator-generator先把基本結(jié)構(gòu)構(gòu)建出來(lái):
npm install -g generator-generator
yo generator
yeoman的generator說(shuō)白也只是一個(gè)npm包,主要依賴yeoman-generator包來(lái)制定構(gòu)建規(guī)則,這里給出ngtimo的基本目錄結(jié)構(gòu):

構(gòu)建規(guī)則
現(xiàn)在主要著眼于generators/app/index.js,此文件是最主要的角色,定義了ngtimo要如何處理模板,如何與用戶交互等。筆者目前也只是照著比較成熟的generator在使用,存在片面之處還請(qǐng)包涵。
總覽index.js
整個(gè)index.js將導(dǎo)出一個(gè)擴(kuò)展了yeoman-generator的類,就像這樣:
const Generator = require('yeoman-generator');
// ...
module.exports = class extends Generator {
prompting() {
// ...
}
default() {
// ...
}
writing() {
// ...
}
install() {
// ...
}
}
內(nèi)部的這四個(gè)方法各有用處。
一、prompting方法
用于與用戶進(jìn)行交互,即在yo項(xiàng)目的時(shí)候,這老頭會(huì)啰啰嗦嗦問(wèn)我們很多問(wèn)題,這些問(wèn)題就是在這里配置的。
對(duì)于這個(gè)方法筆者選擇的套路是如下三部曲:
先讓老頭向用戶問(wèn)聲好
const yosay = require('yosay');
// ...
this.log(yosay(
'Welcome to the astonishing ' + chalk.red('generator-ngtimo') + ' generator!'
));
以上代碼效果就是老頭會(huì)代我們問(wèn)候(褒義)一下用戶:

把一連串問(wèn)題先配置好
const prompts = [{
type: 'input',
name: 'appName',
message: 'Your project name(你的項(xiàng)目名稱)',
default: this.appname
}, {
type: 'confirm',
name: 'addCommon',
message: 'Would you like to add some common code(include CoreModule, SharedModule, Router)?\n(要自動(dòng)創(chuàng)建額外的常用內(nèi)容嗎, 包含了核心模塊、共享模塊和路由能力)',
default: true
}];
這里就列舉了兩類問(wèn)題,一類是客觀題,讓用戶輸入要構(gòu)建的項(xiàng)目名稱,另一類是判斷題,詢問(wèn)用戶是否添加一些額外的常用代碼,還有一類沒(méi)有使用到的是選擇題,還蠻有趣的。
把這個(gè)問(wèn)題數(shù)組返回給老頭
問(wèn)題數(shù)組配置好了,現(xiàn)在要把它交給老頭保管,做法如下:
return this.prompt(prompts).then(props => {
// 用戶交互完成后把得到的配置設(shè)置到參數(shù)中
this.props = props;
});
效果就是當(dāng)用戶做完這些題目后回答會(huì)配置給props變量,在后面的寫如內(nèi)容環(huán)節(jié)就可以根據(jù)用戶的答案來(lái)有選擇的創(chuàng)建項(xiàng)目了。
二、default方法
筆者一開(kāi)始沒(méi)有配置這個(gè)方法,是在測(cè)試構(gòu)建時(shí)發(fā)現(xiàn)沒(méi)辦法給目標(biāo)項(xiàng)目套一個(gè)頂層目錄時(shí)參考官方generator加上的,猜測(cè)是可以用來(lái)執(zhí)行一些默認(rèn)行為,比如自動(dòng)給目標(biāo)項(xiàng)目創(chuàng)建一個(gè)頂層目錄,像這樣:
const path = require('path');
const mkdirp = require('mkdirp');
// ...
default() {
if (path.basename(this.destinationPath()) !== this.props.appName) {
this.log(
'發(fā)現(xiàn)你不是在 ' + this.props.appName + ' 目錄下構(gòu)建\n' +
'我將主動(dòng)創(chuàng)建此目錄.(created folder with app name)'
);
mkdirp(this.props.appName);
this.destinationRoot(this.destinationPath(this.props.appName));
}
}
三、writing方法
此方法即用來(lái)把實(shí)際項(xiàng)目按照指定規(guī)則給寫出來(lái),主要有兩種寫法: 直接復(fù)制指定模板以及傳入?yún)?shù)渲染出目標(biāo)文件。
方式一: 直接拷貝
this.fs.copy(
this.templatePath('模板位置'),
this.destinationPath('目標(biāo)位置')
);
方式二: 傳入?yún)?shù)渲染模板
this.fs.copyTpl(
this.templatePath('模板位置'),
this.destinationPath('目標(biāo)位置'),
{
參數(shù)名: 值
}
);
比如說(shuō),在index.js的同級(jí)目錄下的templates目錄下有一個(gè)文件叫text.txt, 使用方法一將模板位置和目標(biāo)位置都寫text.txt,老頭就會(huì)直接復(fù)制這個(gè)text.txt作為輸出;而如果使用方法二,模板位置和目標(biāo)位置不變,并傳入?yún)?shù){ hello: '你好啊'},在text.txt中就使用ejs語(yǔ)法寫上<%=hello%>,最終老頭同樣會(huì)輸出一個(gè)test.txt文件,不一樣的是里面的內(nèi)容被渲染成了"你好啊"。
對(duì)此方法的總結(jié)就是根據(jù)需要使用copy或copyTpl進(jìn)行輸出,其中copyTpl中的渲染使用ejs語(yǔ)法進(jìn)行,而模板文件就都放在index.js的同級(jí)templates目錄里邊。
四、install方法
此方法即用來(lái)自動(dòng)執(zhí)行依賴的安裝,沒(méi)什么特別的,就是在構(gòu)建完成后自動(dòng)幫你npm install和bower install,也可以禁用其中一種:
install() {
this.installDependencies({bower: false});
}
效果就是下圖這句話了:

發(fā)布generator到npm
發(fā)布之前可以先使用npm link映射到本地進(jìn)行測(cè)試:
npm link yo ngtimo
確認(rèn)無(wú)誤后,發(fā)布流程就是一句代碼的事(記得定好版本,且更新發(fā)布時(shí)記得更新版本號(hào)):
npm publish
以上這篇使用yeoman構(gòu)建angular應(yīng)用的方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳細(xì)談?wù)凙ngularJS的子級(jí)作用域問(wèn)題
大家在使用angularjs的時(shí)候,很容易忽略AngularJS自帶指令的作用域問(wèn)題,有一些指令會(huì)產(chǎn)生獨(dú)立的自己作用域,造成子級(jí)無(wú)法與父級(jí)作用域雙向綁定的問(wèn)題。下面我們來(lái)看看這些問(wèn)題,有需要的可以參考借鑒。2016-09-09
AngularJS中控制器函數(shù)的定義與使用方法示例
這篇文章主要介紹了AngularJS中控制器函數(shù)的定義與使用方法,結(jié)合具體實(shí)例形式分析了AngularJS控制器函數(shù)的定義、綁定及相關(guān)使用技巧,需要的朋友可以參考下2017-10-10
快速學(xué)習(xí)AngularJs HTTP響應(yīng)攔截器
任何時(shí)候,如果我們想要為請(qǐng)求添加全局功能,例如身份認(rèn)證、錯(cuò)誤處理等,在請(qǐng)求發(fā)送給服務(wù)器之前或服務(wù)器返回時(shí)對(duì)其進(jìn)行攔截,是比較好的實(shí)現(xiàn)手段2015-12-12
關(guān)于angularJs指令的Scope(作用域)介紹
下面小編就為大家?guī)?lái)一篇angularJs指令的Scope(作用域)介紹。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10
AngularJS動(dòng)態(tài)綁定HTML的方法分析
這篇文章主要介紹了AngularJS動(dòng)態(tài)綁定HTML的方法,結(jié)合實(shí)例形式分析了AngularJS實(shí)現(xiàn)動(dòng)態(tài)綁定HTML的相關(guān)操作指令用法與使用注意事項(xiàng),需要的朋友可以參考下2016-11-11
Angular ng-repeat指令實(shí)例以及擴(kuò)展部分
這篇文章主要為大家詳細(xì)介紹了Angular ng-repeat指令實(shí)例以及擴(kuò)展部分,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12

