對大多數一個前端團隊來講,Yeoman(簡稱yo)是一個很是值得學習的工具,它爲前端項目提供了一種行之有效的方法,開發、分發、使用項目手腳架,提升項目啓動速度,複用項目結構。javascript
本文以generator-iview-admin 爲例,簡單說明手腳架,即generator的開發過程。前端
開發 Yeoman 模板,需預先安裝yo
:vue
npm i -g yo
yo 細心的爲咱們準備了手腳架項目的手腳架generator-generator:java
npm i -g generator-generator
安裝後,進入開發目錄,運行:webpack
yo generator
執行上述命令後,主要生成以下文件:git
├── .yo-rc.json ├── package.json ├── generators │ ├── app │ ├── templates │ ├── dummyfile.txt │ ├── index.js
其中github
.yo-rc.json
用於存儲項目配置,通常不會用到,無需關注package.json
npm 項目信息文件,主要關注 author、version 域便可generators
目錄即項目模板代碼generators/templates
用於存放項目模板文件generators/app/index.js
定義項目手腳架的代碼每一個generator都會繼承yeoman-generator
類,即上述的generators/app/index.js
文件。該類有幾個重要的生命週期節點:web
initializing
- 初始化方法,用於獲取項目狀態、配置等prompting
- 調用inquire方法獲取用戶輸入configuring
- 保存配置,建立 .editorconfig
等文件writing
- 執行文件寫操做,即項目文件寫入文件系統中install
- 執行安裝操做,需調用 this.installDependencies
方法end
- 最後執行,可清楚臨時文件等上述方法均支持返回
Promise
方式實現異步操做,僅當返回的Promise
實例resolve
時纔會執行下一步操做。npm
首先,咱們須要在 prompting
中詢問用戶配置(完整實例在此處):json
prompting() { // Have Yeoman greet the user. this.log(yosay('Welcome to the divine ' + chalk.red('generator-iview-admin') + ' generator!')); const prompts = [{ type: 'input', name: 'name', message: 'Your project name', default: this.appname }, { type: 'confirm', name: 'lint', message: 'Use ESLint to lint your code?' }, { name: 'lintStyle', type: 'list', message: 'Pick an ESLint preset', when(answers) { return answers.lint; }, choices: [{ name: 'Airbnb (https://github.com/airbnb/javascript)', value: 'airbnb', short: 'Airbnb' }, { name: 'Standard (https://github.com/feross/standard)', value: 'standard', short: 'Standard' }] }]; return this.prompt(prompts).then((props) => { // To access props later use this.props.someAnswer; this.props = props; }); }
這裏,將用戶輸入的結果配置到 this.props
對象中,方便後續訪問。
yo 的核心,本質上是按需修改模板文件,通常包含三種方法:
以ejs方式爲例,編寫模板(完整實例在此處):
<% if(vueFile==='standalone'){ %> // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. <% } %> ... /* eslint-disable no-new */ new Vue({ el: '#app', router,<% if(vueFile==='runtime'){ %> render: h => h(App)<% } else if(vueFile==='standalone'){ %> template: '<App/>', components: { App }<% } %> });
獲取配置後,能夠正式開始將模板寫入硬盤中(完整實例在此處):
writing() { this.initPackage(); this.renderTplFile(); } initPackage() { let pkg = this.fs.readJSON(this.templatePath('package.json'), {}); const { props } = this; pkg = _.merge(pkg, { name: props.name, description: props.description }); ... this.fs.writeJSON(this.destinationPath('package.json'), pkg); } renderTplFile() { let target = [ ... 'src/components/Hello.vue', ]; if (this.props.unitTest) { target = target.concat([ ... 'build/webpack.test.conf.js' ]); } ... _.forEach(target, (file) => { this.fs.copyTpl( this.templatePath(file), this.destinationPath(file), this.props ); }); }
yo 提供mem-fs-editor實例接口,包含一系列fs工具:
this.fs.read
- 讀取文件this.fs.readJSON
- 以JSON方式讀取文件this.fs.write
- 寫文件this.fs.writeJson
- 以JSON 方式寫文件this.fs.append
- 將內容已追加方式寫入文件this.fs.extendJSON
- 擴展JSON文件內容this.fs.delete
- 刪除文件此外,還有一系列路勁及模板接口:
this.fs.copyTpl
- 複製模板文件,並按參數解析模板內容,寫入目標文件中this.templatePath
- 返回模板文件路徑,即上述 generator/app/templates
中的文件路徑this.destinationPath
- 返回目標文件路徑,即執行 yo 生成模板文件的路徑this.registerTransformStream
- 生命鉤子接口,用於轉化文件內容,兼容gulp
插件至此,咱們已瞭解開發一個yo模板所須要的全部接口。
yo容許添加任意數量的子模板,只需執行:
yo generator:subgenerator [name]
以yo generator:subgenerator test
爲例,生成以下文件:
├── generators │ ├── app │ ├── test │ ├── templates │ ├── dummyfile.txt │ ├── index.js
templates、 index.js 文件的做用與上述無異,可直接開發。
能夠經過以下方式,將項目加入本地generator 庫:
npm link
以後,就能夠執行以下命令,生成手腳架:
yo [your template name]
模板開發完畢後,如需發佈可執行以下命令:
npm publish
注意:
- 若是npm還沒有登陸,可執行
npm adduser
操做進行登陸- 發佈npm包必須使用
https://registry.npmjs.org/
源,切記切換。