>[success] # 使用Yeoman
~~~
1.安裝'yo' 后,他就想npm一樣,可以管理與生成器相關的所有內容,使用其他開發通過Yeoman封裝
上傳的node腳手架模板,直接生成了一個node項目開發的基本配置,如果通過Yeoman配置一個自己的
腳手架
~~~
[官網案例說明](https://yeoman.io/authoring/index.html)
>[info] ## 通過Yeoman 創建一個自己的腳手架
~~~
1.創建自己的'Yeoman generator',需要Yeoman的Generator的模塊名稱必須是'generator - < name >'的格式
如果不遵守,Yeoman后續工作時就無法找到你所提供的生成器模塊
2.創建一個自己的'Yeoman'
2.1.創建一個規定格式的文件夾名 例如'generator-sample'
2.2.創建'package.json' -- 'npm init -y'
2.3.安裝'yeoman-generator' -- 'npm install yeoman-generator' 這個某塊提供了生成器的基類 ,基類中提供
了一些工具函數,這些函數可以讓自己的'Yeoman generator',配置簡單地復制一堆樣板文件,
或者可以更高級地詢問用戶的喜好來搭建定制項目的腳手架
2.4.Yeoman的功能取決如何構造目錄樹,每個子生成器都包含在其自己的文件夾中,其中'默認生成器'
必須在'app' 目錄中,也就是說當通過'yo <生成器名稱例如generator-sample>' 時候實際相當執行是
在app目錄配置的生成器設置,也可以調用其他生成器(官網叫子集生成器)通過
'yo name:<子集生成器的名>'
~~~
[項目目錄規則](https://yeoman.io/authoring/index.html#folder-tree)
* 項目目錄的例子 在 generators/ 下注冊生成器
~~~
1.生成器描述文件 package.json,其中限定了 name、file、keywords 等對應字段的規范賦值。
2.作為主體的 generators/app 目錄,包含生成器的核心文件。該目錄是執行 yo 命令時的默認查找目錄,
Yeoman 支持多目錄的方式集成多個子生成器
3.app/index.js 是生成器的核心控制模塊,其內容是導出一個繼承自 yeoman-generator 的類,并由后者
提供運行時上下文、用戶交互、生成器組合等功能。
app/templates/ 目錄是我們需要復制到新項目中的腳手架模板目錄。
~~~
~~~
├───package.json
└───generators ------ '生成器的目錄'
├───app ------'默認生成器目錄'
│ ├── templates ----- '用于存放項目模板文件'
│ │ └─── temp.txt
│ └───index.js ------'默認生成器實現'
└───router -----'其他生成器目錄當然這個名字可以隨便起'
└───index.js ------'其他生成器實現'
~~~
* Yeoman 也允許直接在./ 目錄下注冊的生成器
~~~
├───package.json
├───app/
│ └───index.js
└───router/
└───index.js
// 這種配置需保將files屬性指向package.json所有生成器文件夾
{
"files": [
"app",
"router"
]
}
~~~
>[danger] ##### 編寫index.js 中文件
~~~
1.現在我們想做一個腳手架,執行命令后幫我們自動在當前目錄創建一個'temp.txt'文件,文件內容
是隨機數字
~~~
* 代碼實現
~~~
// 此文件作為 Generator 的核心入口
// 需要導出一個繼承自 Yeoman Generator 的類型
// Yeoman Generator 在工作時會自動調用我們在此類型中定義的一些生命周期方法
// 我們在這些方法中可以通過調用父類提供的一些工具方法實現一些功能,例如文件寫入
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing() {
// Yeoman 自動在生成文件階段調用此方法
// 我們這里嘗試往項目目錄中寫入文件
// 這里的fs模塊與Node中的fs不一樣,這是一個高度封裝的模塊,功能更加強大
this.fs.write(
this.destinationPath('temp.txt'),
Math.random().toString()
)
}
}
~~~
* 如何使用創建好的Generator
~~~
1.因為是在本地開發生成器,因此不能作為全局npm模塊使用。可以使用npm創建一個全局模塊
并將其符號鏈接到本地??模塊,在命令行上,從生成器項目的根目錄輸入指令 -- 'npm link'
2.在創建自己的'Generator '時候文件規范'generator - < name >',此時就可以配合'yo' 來執行自己創建的'Generator '
例如案例中起的名字'generator-sample' 在我們想生成項目的文件下就可以輸入指令 -- 'yo sample'
~~~
>[danger] ##### 關于'yeoman-generator'
~~~
1.可以回想在使用其他腳手架工具時候一般步驟
1.1.初始化,一般在這個時候會進行環境的初始化,做一些前置的檢查
1.2.用戶輸入,例如用 vue-cli 的時候,它會“問”你很多配置選項
1.3.生成配置文件
1.4.生成項目結構,這是候可能會使用一個項目模版
1.5.安裝依賴
1.6.清理、校驗等收尾工作
2.這些步驟過程都可以通過繼承'yeoman-generator' 來實現,'yeoman-generator'為整體提供了
類似的生命周期的方法:
2.1.'initializing' - 初始化方法,用于獲取項目狀態、配置等
2.2.'prompting' - 調用'inquire'方法接收用戶輸入階段,來處理終端的交互
2.3.'configuring' - 保存配置信息和文件創建 .editorconfig 等文件
2.4.'default' - 這里指的是自己自定義的方法,而不是名為default的方法,自己定義的方法如果不想被調用
那么需要確保方法名以_為開頭
2.5.'writing' - 執行文件寫操作,即項目文件寫入文件系統中
2.6.'conflicts':統一處理沖突,如要生成的文件已經存在是否覆蓋等處理
2.7.'install' -安裝項目的依賴,比如npm install 或者 bower install,需調用 this.installDependencies 方法
2.8.'end' - 生成器結束階段,可清除臨時文件
3.因此上面案例中想做到的創建文件并且寫入內容,這個操作放到了'writing' 方法的原因就是因為這個方法
可以 執行文件寫操作,即項目文件寫入文件系統中
4.除了上面案例yo 提供的額外的文件寫入這種api外,還提供了下面這些使用的api
4.1.'this.fs.read' - 讀取文件
4.2.'this.fs.readJSON' - 以JSON方式讀取文件
4.3.'this.fs.write' - 寫文件
4.4.'this.fs.writeJson' - 以JSON 方式寫文件
4.5.'this.fs.append' - 將內容已追加方式寫入文件
4.6.'this.fs.extendJSON' - 擴展JSON文件內容
4.7.'this.fs.delete' - 刪除文件
還有一系列路勁及模板接口:
4.8.'this.fs.copyTpl' - 復制模板文件,并按參數解析模板內容,寫入目標文件中
4.9.'this.templatePath' - 返回模板文件路徑,即上述 generator/app/templates 中的文件路徑
4.10.'this.destinationPath' - 返回目標文件路徑,即執行 yo 生成模板文件的路徑
4.11.'this.registerTransformStream' - 生命鉤子接口,用于轉化文件內容,兼容gulp插件
這些api 是由yo 的 mem-fs-editor 提供[https://github.com/sboudrias/mem-fs-editor]
~~~
[官網對于生命周期說明](https://yeoman.io/authoring/running-context.html#the-run-loop)
>[danger] ##### yo 的Ejs模板功能
~~~
1.上面的示例是通過'this.fs.write' 去寫文件,最大的我問題就是通過代碼控制一些相對的文件內容,當文件的
內容相對復雜的時候這種寫文件的成本也相對提高,yo 內部可以使用 EJS,這部分的文件需要放到templates
文件夾下的
~~~
~~~
// template/.txt
例如 <%= title %>
其他的 EJS 語法也支持
<% if (success) { %>
sgh
<% }%>
~~~
~~~
// index.js
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing () {
// 通過模板方式寫入文件到目標目錄
// 模板文件路徑
const tmpl = this.templatePath('temp.txt')
// 輸出目錄路徑
const output = this.destinationPath('temp.txt') //('src/temp.txt') 也可以將輸出文件指定到指定文件夾下
// 模板數據上下文
const context = { title:'Hello sgh~', success:false }
// 參數 模板文件的路徑 輸出文件的路徑 模板數據的上下文
this.fs.copyTpl(tmpl, output, context)
}
}
~~~
>[danger] ##### 安裝packjson 內容
~~~
1.有時候希望我們的模板生成后還可以安裝指定的 npm 包,這個時候除了使用上面介紹的,用esj這種生成
pack.json,也可以通'this.fs.writeJson' 來動態寫json文件的配置
2.后續配合'npmInstall' api 來安裝,當然也可以使用'yarnInstall'
~~~
[官網這部分介紹鏈接](https://yeoman.io/authoring/dependencies.html)
~~~
// index.js
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing() {
const pkgJson = {
devDependencies: {
eslint: '^3.15.0'
},
dependencies: {
react: '^16.2.0'
}
};
// 創建package.json 文件目錄
this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
}
// 調用安裝
install(){
// 調用yarn 來安裝指定庫
this.yarnInstall()
}
}
~~~
>[danger] ##### 接收用戶詢問 -- prompting
~~~
1.在常見的腳手架,其實可以看見,為了更加針對給用戶自由度體驗,會產生詢問用戶接下來的安裝
內容的選擇,這一部分的內容在'prompting'完成的
~~~
[官網參考鏈接](https://yeoman.io/authoring/user-interactions.html)
~~~
// index.js
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
async prompting() {
// 這里的變量名隨便起的也就是說可以不叫 answers
this.answers = await 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?"
}
]);
// this.log("app name", answers.name);
// this.log("cool feature", answers.cool);
}
writing() {
// 配合prompting 詢問來生成動態文件
const tmpl = this.templatePath('temp.html')
// 輸出目標路徑
const output = this.destinationPath('temp.html')
// 模板數據上下文
const context = this.answers
// 詢問的內容生成的對象 配合esj 模板生成想要的內容
this.fs.copyTpl(tmpl, output, context)
}
};
~~~
>[info] ## 定義一個 vue 腳手架
~~~
1.思路就是可以先在'templates' 定義好項目的結構目錄,利用'yeoman-generator' 來寫我們的腳手架
生成器
~~~

* 在 index.js 完成的代碼,這里可以定義一些用戶的輸出配合esj模板更加動態定制
~~~
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
prompting () {
return this.prompt([
{
type: 'input',
name: 'name',
message: 'Your project name',
default: this.appname
}
])
.then(answers => {
this.answers = answers
})
}
writing () {
// 把每一個文件都通過模板轉換到目標路徑
const templates = [
'.browserslistrc',
'.editorconfig',
'.env.development',
'.env.production',
'.eslintrc.js',
'.gitignore',
'babel.config.js',
'package.json',
'postcss.config.js',
'README.md',
'public/favicon.ico',
'public/index.html',
'src/App.vue',
'src/main.js',
'src/router.js',
'src/assets/logo.png',
'src/components/HelloWorld.vue',
'src/store/actions.js',
'src/store/getters.js',
'src/store/index.js',
'src/store/mutations.js',
'src/store/state.js',
'src/utils/request.js',
'src/views/About.vue',
'src/views/Home.vue'
]
// 生成文件
templates.forEach(item => {
// item => 每個文件路徑
this.fs.copyTpl(
this.templatePath(item),
this.destinationPath(item),
this.answers
)
})
}
}
~~~
>[danger] ##### 發布 Generator
~~~
//Generator就是一個npm模塊,所以我們發布Generator實際就是去發布一個npm模塊。
1.創建 .gitignore 去忽略項目中的 node_modules
echo node_modules > .gitignore
2.初始化本地空倉庫
git init
3.查看本地倉庫狀態并提交
git status
git add
git commit -m "feat: initial commit"
4.在github創建一個新的倉庫并推送
git remote add origin [倉庫地址]
git push -u origin master
5.發布模塊(使用官方鏡像)
yarn publish [--registry=https://registry.yarnpkg.com]
6.如果需要你的Generator在官方的倉庫列表出現,可以為項目添加一個 yeoman-generator
的關鍵詞,官方會發現到此項目。
~~~
>[danger] ##### 快速創建yo 的generator
目錄
~~~
1.當然也可以直接使用已經為我們創建好的'generator' 項目使用,會幫我創建好一個自定義的'generator'
項目目錄格式的腳手架
npm i -g generator-generator
yo generator
~~~
>[danger] ##### 參考文章
[前端自動化工具 - yeoman](https://www.yuque.com/kongdepeng/rgpm60/qrluup)
[手把手入門 Yeoman 模板開發](https://juejin.im/post/6844903743012487181)
[如何快速開發一個自己的項目腳手架?](https://zhuanlan.zhihu.com/p/66190308)
[使用 Yeoman 定制自己的項目腳手架
](https://juejin.im/post/6844904191912050695)
- 工程化 -- Node
- vscode -- 插件
- vscode -- 代碼片段
- 前端學會調試
- 谷歌瀏覽器調試技巧
- 權限驗證
- 包管理工具 -- npm
- 常見的 npm ci 指令
- npm -- npm install安裝包
- npm -- package.json
- npm -- 查看包版本信息
- npm - package-lock.json
- npm -- node_modules 層級
- npm -- 依賴包規則
- npm -- install 安裝流程
- npx
- npm -- 發布自己的包
- 包管理工具 -- pnpm
- 模擬數據 -- Mock
- 頁面渲染
- 渲染分析
- core.js && babel
- core.js -- 到底是什么
- 編譯器那些術語
- 詞法解析 -- tokenize
- 語法解析 -- ast
- 遍歷節點 -- traverser
- 轉換階段、生成階段略
- babel
- babel -- 初步上手之了解
- babel -- 初步上手之各種配置(preset-env)
- babel -- 初步上手之各種配置@babel/helpers
- babel -- 初步上手之各種配置@babel/runtime
- babel -- 初步上手之各種配置@babel/plugin-transform-runtime
- babel -- 初步上手之各種配置(babel-polyfills )(未來)
- babel -- 初步上手之各種配置 polyfill-service
- babel -- 初步上手之各種配置(@babel/polyfill )(過去式)
- babel -- 總結
- 各種工具
- 前端 -- 工程化
- 了解 -- Yeoman
- 使用 -- Yeoman
- 了解 -- Plop
- node cli -- 開發自己的腳手架工具
- 自動化構建工具
- Gulp
- 模塊化打包工具為什么出現
- 模塊化打包工具(新) -- webpack
- 簡單使用 -- webpack
- 了解配置 -- webpack.config.js
- webpack -- loader 淺解
- loader -- 配置css模塊解析
- loader -- 圖片和字體(4.x)
- loader -- 圖片和字體(5.x)
- loader -- 圖片優化loader
- loader -- 配置解析js/ts
- webpack -- plugins 淺解
- eslit
- plugins -- CleanWebpackPlugin(4.x)
- plugins -- CleanWebpackPlugin(5.x)
- plugin -- HtmlWebpackPlugin
- plugin -- DefinePlugin 注入全局成員
- webapck -- 模塊解析配置
- webpack -- 文件指紋了解
- webpack -- 開發環境運行構建
- webpack -- 項目環境劃分
- 模塊化打包工具 -- webpack
- webpack -- 打包文件是個啥
- webpack -- 基礎配置項用法
- webpack4.x系列學習
- webpack -- 常見loader加載器
- webpack -- 移動端px轉rem處理
- 開發一個自己loader
- webpack -- plugin插件
- webpack -- 文件指紋
- webpack -- 壓縮css和html構建
- webpack -- 清里構建包
- webpack -- 復制靜態文件
- webpack -- 自定義插件
- wepack -- 關于靜態資源內聯
- webpack -- source map 對照包
- webpack -- 環境劃分構建
- webpack -- 項目構建控制臺輸出
- webpack -- 項目分析
- webpack -- 編譯提速優護體積
- 提速 -- 編譯階段
- webpack -- 項目優化
- webpack -- DefinePlugin 注入全局成員
- webpack -- 代碼分割
- webpack -- 頁面資源提取
- webpack -- import按需引入
- webpack -- 搖樹
- webpack -- 多頁面打包
- webpack -- eslint
- webpack -- srr打包后續看
- webpack -- 構建一個自己的配置后續看
- webpack -- 打包組件和基礎庫
- webpack -- 源碼
- webpack -- 啟動都做了什么
- webpack -- cli做了什么
- webpack - 5
- 模塊化打包工具 -- Rollup
- 工程化搭建代碼規范
- 規范化標準--Eslint
- eslint -- 擴展配置
- eslint -- 指令
- eslint -- vscode
- eslint -- 原理
- Prettier -- 格式化代碼工具
- EditorConfig -- 編輯器編碼風格
- 檢查提交代碼是否符合檢查配置
- 整體流程總結
- 微前端
- single-spa
- 簡單上手 -- single-spa
- 快速理解systemjs
- single-sap 不使用systemjs
- monorepo -- 工程
- Vue -- 響應式了解
- Vue2.x -- 源碼分析
- 發布訂閱和觀察者模式
- 簡單 -- 了解響應式模型(一)
- 簡單 -- 了解響應式模型(二)
- 簡單 --了解虛擬DOM(一)
- 簡單 --了解虛擬DOM(二)
- 簡單 --了解diff算法
- 簡單 --了解nextick
- Snabbdom -- 理解虛擬dom和diff算法
- Snabbdom -- h函數
- Snabbdom - Vnode 函數
- Snabbdom -- init 函數
- Snabbdom -- patch 函數
- 手寫 -- 虛擬dom渲染
- Vue -- minVue
- vue3.x -- 源碼分析
- 分析 -- reactivity
- 好文
- grpc -- 瀏覽器使用gRPC
- grcp-web -- 案例
- 待續