LoginSignup
17
17

More than 5 years have passed since last update.

Yeomanのgeneratorを自作する

Last updated at Posted at 2015-05-12

Yeoman入門(第二部、generatorを作る)を参考にyoeman generatorを作成していたが、yeomanが更新されて現在は少し作り方が変わっているようなので新しい作成方法をメモ。

generator-generatorのインストール

generatorの雛形を生成するgenerator-generatorをインストール。

npm install generator-generator -g

helloworld generatorを作成するためのディレクトリを用意して移動。

mkdir generator-helloworld
cd generator-helloworld

generator-helloworldの雛形作成

generatorの雛形を生成

yo generator

コマンドを実行すると、gitのユーザ名を聞かれた後、generatorの名前を聞かれるのでhelloworldと入力してenter。
(そのままenterを押すとgeneratorの名前がgenerator-generator-helloworldになります。)

[?] What's the base name of your generator? (generator helloworld) helloworld

コマンドの実行が終了すると、以下のようなフォルダ構成になっているかと思います。

.
├── README.md
├── node_modules
├── generators
│   └── app
│       ├── index.js
│       └── templates
│           ├── _bower.json
│           ├── _package.json
│           ├── editorconfig
│           └── jshintrc
├── package.json
└── test
    └── test-app.js

generator-helloworldの動作確認

ここで一旦generator-helloworldの動作確認をします。
適当なディレクトリを作って、移動。

mkdir test-helloworld
cd test-helloworld

さらに、node_modulesディレクトリを作って、node_modulesディレクトリ以下にシンボリックリンクでgenerator-helloworldを配置します。

mkdir node_modules
cd node_modules
ln -s <generator-helloworldへのパス> .
.
├── README.md
├── node_modules
│   └── generator-helloworld

Yeomanは、node_modulesに配置されている'generator-'で始まるパッケージをgeneratorと認識するので、これによってgenerator-helloworldがgeneratorと認識されるようになります。

次に、yo helloworldでgenerator-helloworldを実行。

この際、以下のエラーがでる場合は、generators/app/index.jsのrequire('../package.json')require('../../package.json')に直して下さい。
(YeomanでError: Cannot find module '../package.json'が表示される問題の対策)

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: Cannot find module '../package.json'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at module.exports.yeoman.generators.Base.extend.initializing (/Users/ryo/Programming/web/generator-helloworld/generators/app/index.js:8:16)
    at /Users/ryo/Programming/web/generator-helloworld/node_modules/yeoman-generator/lib/base.js:421:16
    at processImmediate [as _immediateCallback] (timers.js:336:15)

コマンドの実行が終了すると、以下のような構成のファイルが生成されているかと思います。

.
├── .editorconfig
├── .jshintrc
├── bower.json
├── node_modules
│   └── generator-helloworld
└── package.json

generator-helloworldの編集

generatorの中核となる処理は、generators/app/index.jsに書かれているので、このファイルを開いてみます。

generators/app/index.js
'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');

module.exports = yeoman.generators.Base.extend({
  initializing: function () {
    this.pkg = require('../../package.json');
  },

  prompting: function () {
    var done = this.async();

    // Have Yeoman greet the user.
    this.log(yosay(
      'Welcome to the super-excellent ' + chalk.red('Helloworld') + ' generator!'
    ));

    var prompts = [{
      type: 'confirm',
      name: 'someOption',
      message: 'Would you like to enable this option?',
      default: true
    }];

    this.prompt(prompts, function (props) {
      this.props = props;
      // To access props later use this.props.someOption;

      done();
    }.bind(this));
  },

  writing: {
    app: function () {
      this.fs.copy(
        this.templatePath('_package.json'),
        this.destinationPath('package.json')
      );
      this.fs.copy(
        this.templatePath('_bower.json'),
        this.destinationPath('bower.json')
      );
    },

    projectfiles: function () {
      this.fs.copy(
        this.templatePath('editorconfig'),
        this.destinationPath('.editorconfig')
      );
      this.fs.copy(
        this.templatePath('jshintrc'),
        this.destinationPath('.jshintrc')
      );
    }
  },

  install: function () {
    this.installDependencies();
  }
});

ここに、ユーザ名を尋ねるpromptを表示する処理を追加します。

generators/app/index.js

    var prompts = [{
      type: 'confirm',
      name: 'someOption',
      message: 'Would you like to enable this option?',
      default: true
    },
    {
      name: 'yourname',
      message: 'What is your name?',
      default: "someuser"
    }];

次に、index.htmlをgenerators/app/templatesに配置します。

generators/app/templates/index.html
<html>
  <body>
    <h1>Hello, <%= yourname %></h1>
  </body>
</html>

上記の<%= yourname %>の部分にpromptで入力されたユーザ名を埋め込む処理をgenerators/app/index.jsに記述します。

generators/app/index.js
  writing: {
    app: function () {
      this.fs.copy(
        this.templatePath('_package.json'),
        this.destinationPath('package.json')
      );
      this.fs.copy(
        this.templatePath('_bower.json'),
        this.destinationPath('bower.json')
      );

      // generators/app/templates/index.htmlを対象のディレクトリにコピーして、
      // yournameにユーザ名を埋め込む
      this.fs.copyTpl(
        this.templatePath('index.html'),
        this.destinationPath('index.html'),
        {yourname: this.props.yourname}
      );
    },

promptで入力された値は、this.props経由でアクセスできます。

generator-helloworldの再実行

test-helloworldを一旦削除し、初期と同じ以下の構成に戻します。

.
├── README.md
├── node_modules
│   └── generator-helloworld
rm -rf test-helloworld
mkdir test-helloworld
cd test-helloworld
mkdir node_modules
cd node_modules
ln -s <generator-helloworldのパス> .

最後に、test-helloworld内に移動して、yo helloworldを実行し、promptで入力した名前が表示されていれば成功です。

cd test-helloworld
yo helloworld
open index.html

参考文献

17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17