yeoman-generator入門教程

hubuke 8年前發布 | 7K 次閱讀 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的時候,你經常需要通過 npmBower來安裝一些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

 本文由用戶 hubuke 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!