Study Notes
本博主會持續(xù)更新各種前端的技術盈蛮,如果各位道友喜歡,可以關注械念、收藏沈条、點贊下本博主的文章牙瓢。
yeoman
現(xiàn)代 Web 應用程序的 Web 腳手架工具
- 全局安裝 yo
npm i yo -g
安裝對應的 generator
這里安裝generator-none
npm i generator-node -g
用法
- 通過 yo 運行 generator
mkdir my-module
cd my-module
yo node
- 子生成器使用
如果不需要主生成器提供的所有功能僧凰,則仍可以通過直接與子生成器組合來使用羡儿。
可以通過運行下面的命令來查看每個子生成器的選項败匹。
yo node:sub --help
這里我們使用 node:cli 子生成器
yo node:cli
link 到全局
npm link
查看是否 link 到全局
my-module --help
yeoman 使用步驟總結
- 1撮胧、明確你的需求
- 2桨踪、找到合適的 Generator
- 3、全局安裝 Generator
- 4芹啥、通過 yo 運行對應的 Generator
- 5锻离、通過命令行交互填寫選項
- 6、生成你所需要的項目結構
自定義 Generator
生成器的核心是 Node.js 模塊墓怀。
首先汽纠,創(chuàng)建一個文件夾,在其中編寫 generator傀履。 該文件夾必須命名為 generator-name(其中 name 是你的生成器的名稱)虱朵。 這一點很重要,因為 Yeoman 依靠文件系統(tǒng)來查找可用的生成器钓账。
進入 Generator 文件夾后碴犬,創(chuàng)建一個 package.json 文件。 該文件是 Node.js 模塊清單官扣。 你可以通過從命令行運行 npm init 或手動輸入以下內容來生成此文件:
{
"name": "generator-name",
"version": "0.1.0",
"description": "",
"files": ["generators"],
"keywords": ["yeoman-generator"],
"dependencies": {
"yeoman-generator": "^1.0.0"
}
}
name 屬性必須以 generator-為前綴翅敌。 關鍵字屬性必須包含yeoman-generator
羞福,并且存儲庫必須具有要由我們的 generators 頁面建立索引的描述惕蹄。
你應該確保將最新版本的 yeoman-generator 設置為依賴項。 你可以通過運行以下命令執(zhí)行此操作:
npm install --save yeoman-generator
files 屬性必須是生成器使用的文件和目錄的數(shù)組。
根據(jù)需要添加其他 package.json 屬性卖陵。
Generator 目錄結構
Yeoman 的功能取決于你如何構建目錄樹遭顶。 每個子生成器都包含在其自己的文件夾中。
調用你的名字時使用的默認生成器是應用生成器泪蔫。 它必須包含在app/
目錄中棒旗。
調用yo name:subcommand
時使用的子生成器存儲在與 sub 命令完全相同的文件夾中。
在一個示例項目中撩荣,目錄樹可能如下所示:
└───generators/........................生成器目錄
├───app/...........................默認生成器目錄
│ └───index.js..................默認生成器實現(xiàn)
└───router/........................其他生成器目錄
└───index.js...................其他生成器實現(xiàn)
├───package.json.......................模塊包配置文件
該生成器將顯示yo name
和yo name:router
命令铣揉。
Yeoman 允許兩種不同的目錄結構。 它會在./
和generators/
中查找以注冊可用的生成器餐曹。
前面的示例也可以編寫如下:
├───app/...............................默認生成器目錄
│ └───index.js......................默認生成器實現(xiàn)
└───router/............................其他生成器目錄
└───index.js.......................其他生成器實現(xiàn)
├───package.json.......................模塊包配置文件
如果使用第二個目錄結構逛拱,請確保將 files 屬性指向 package.json 所有生成器文件夾。
{
"files": ["app", "router"]
}
擴展 Generator
有了此結構后台猴,就可以編寫實際的生成器了朽合。
Yeoman 提供了一個基本生成器,你可以擴展它來實現(xiàn)自己的行為饱狂。 該基本生成器將添加你希望簡化任務的大多數(shù)功能曹步。
在生成器的index.js
文件中,以下是擴展基本生成器的方法:
const Generator = require('yeoman-generator');
module.exports = class extends Generator {};
我們將擴展的生成器分配給 module.exports 以使其可用于生態(tài)系統(tǒng)休讳。 這就是我們在 Node.js 中導出模塊的方式讲婚。
覆蓋構造函數(shù)
某些生成器方法只能在構造函數(shù)內部調用。 這些特殊方法可能會執(zhí)行諸如設置重要狀態(tài)控件之類的操作衍腥,并且可能無法在構造函數(shù)之外運行磺樱。
要覆蓋生成器構造函數(shù),請?zhí)砑右粋€構造函數(shù)方法婆咸,如下所示:
const Generator = require('yeoman-generator');
module.exports = class extends Generator {
// The name`constructor` is important here
constructor(args, opts) {
// Calling the super constructor is important so our generator is correctly set up
super(args, opts);
// Next, add your custom code
this.option('babel'); // This method adds support for a`--babel` flag
}
};
添加功能
調用生成器后竹捉,添加到原型的每種方法都會運行,并且通常是按順序進行的尚骄。 但是块差,正如我們將在下一節(jié)中看到的那樣,一些特殊的方法名稱將觸發(fā)特定的運行順序倔丈。
示例:
const Generator = require('yeoman-generator');
module.exports = class extends Generator {
method1() {
this.log('method 1 just ran');
}
method2() {
this.log('method 2 just ran');
}
};
當我們運行生成器時憨闰,將在控制臺看到日志輸出。
示例二:
// 此文件作為Generator的核心入口
// 需要導出一個繼承自Yeoman Generator的類型
// Yeoman Generator在工作時會自動調用我們在此類型中定義的一些生命周期方法
// 我們在這些方法中可以調用父類提供的一些工具方法來實現(xiàn)一些功能需五,例如文件寫入
const Generator = require('yeoman-generator');
module.exports = class extends Generator {
// Yeoman 自動在生成文件階段調用次方法
writing() {
// Generator將文件寫入本地的方法
// 調用Generator的fs中的write方法來寫入文件 第一個參數(shù)為寫入的絕對路徑鹉动,第二個參數(shù)為寫入內容
this.fs.write(this.destinationPath('temp.txt'), '1231');
}
};
運行 generator
接下來我們將運行 generator,看看它是否有效宏邮。
由于我是在本地開發(fā)生成器泽示,因此尚未作為全局 npm 模塊提供缸血。 可以使用 npm 創(chuàng)建一個全局模塊并將其符號鏈接到本地模塊。
在文件夾根目錄下械筛,執(zhí)行:
npm link
文件系統(tǒng)的使用
位置上下文和路徑
Yeoman 文件實用程序基于這樣一個理念:磁盤上總是有兩個位置有上下文捎泻。這些上下文是生成器最有可能讀取和寫入的文件夾。
目標上下文
第一個上下文是目標上下文埋哟。 目標是 Yeoman 將在其中存放新應用程序的文件夾笆豁。 這是你的用戶項目文件夾,你將在其中編寫大多數(shù)腳手架赤赊。
目標上下文定義為當前工作目錄或包含.yo-rc.json
文件的最近的父文件夾闯狱。.yo-rc.json
文件定義了 Yeoman 項目的根目錄。 該文件允許你的用戶在子目錄中運行命令并使它們在項目上運行抛计。 這樣可以確保最終用戶的行為一致扩氢。
你可以使用this.destinationRoot()
或通過使用this.destinationPath('sub/path')
聯(lián)接路徑來獲取目標路徑。
// Given destination root is ~/projects
class extends Generator {
paths() {
this.destinationRoot();
// returns '~/projects'
this.destinationPath('index.js');
// returns '~/projects/index.js'
}
}
模板上下文
模板上下文是用于存儲模板文件的文件夾爷辱。 通常是你要從中讀取和復制的文件夾录豺。
默認情況下,模板上下文定義為./templates/
饭弓。 你可以使用this.sourceRoot('new/template/path')
覆蓋此默認值双饥。
你可以使用this.sourceRoot()
或通過使用this.templatePath('app/index.js')
連接路徑來獲取路徑值。
class extends Generator {
paths() {
this.sourceRoot();
// returns './templates'
this.templatePath('index.js');
// returns './templates/index.js'
}
};
“內存中”文件系統(tǒng)
Yeoman 在覆蓋用戶文件時非常小心弟断。 基本上咏花,在預先存在的文件上發(fā)生的每個寫入都將經(jīng)歷沖突解決過程。 此過程要求用戶驗證將內容覆蓋到其文件的每個文件寫入阀趴。
此行為可防止出現(xiàn)意外情況并限制發(fā)生錯誤的風險昏翰。 另一方面,這意味著每個文件都異步寫入磁盤刘急。
由于異步 API 難以使用棚菊,因此 Yeoman 提供了一個同步文件系統(tǒng) API,其中每個文件都被寫入內存文件系統(tǒng)叔汁,并且只有在 Yeoman 完成運行后才被寫入磁盤统求。
此內存文件系統(tǒng)在所有組合的生成器之間共享。
文件工具
生成器在this.fs
上公開了所有文件方法据块,此文件是 mem-fs-editor-確保檢查模塊文檔中所有可用的方法码邻。
值得注意的是,盡管this.fs
公開了commit
另假,但您不應在生成器中調用它像屋。 在運行循環(huán)的沖突階段之后,Yeoman 在內部調用此方法边篮。
示例:復制模板文件
這是我們要復制和處理模板文件的示例己莺。
文件路徑app/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title><%= Title %></title>
</head>
<body></body>
</html>
然后因苹,在將內容作為模板處理時,我們使用copyTpl方法復制文件篇恒。copyTpl
使用 ejs 模板語法。
class extends Generator {
writing() {
this.fs.copyTpl(
this.templatePath('index.html'),
this.destinationPath('public/index.html'),
{ title: 'Templating with Yeoman' }
);
}
}
一種非常常見的情況是在提示階段存儲用戶輸入凶杖,并將其用于模板:
class extends Generator {
async prompting() {
this.answers = await this.prompt([{
type : 'input',
name : 'title',
message : 'Your project title',
}]);
}
writing() {
this.fs.copyTpl(
this.templatePath('index.html'),
this.destinationPath('public/index.html'),
{ title: this.answers.title } // user answer `title` used
);
}
}