読者です 読者をやめる 読者になる 読者になる

UTALI

書き溜めておいた技術記事や旅行記のバックアップです。

Yeomanの使い方 | 高速Webアプリケーション開発に有用?

f:id:mochizuki_p:20170119201001p:plain

Yeomanとは?

Googleのエンジニアが中心になって開発しているNode.jsで構築されたWebアプリケーションの雛形作成ツール

最近のWebアプリケーションの潮流として、言えるのはその開発手法やツールの使い方が非常に多様化しているということが挙げられます。

このような状況下で高速にWebアプリケーションを開発し、デプロイするには、

ほぼ無限に存在するツールの組み合わせについて、一から構築するのではなく、あらかじめ作成された雛形から始めるのが最適解となるでしょう。

Yeomanは開発者の負担を軽減し、より高速・安全にWebアプリケーションを作成するためのツールとなっています。

Yeoman自体は雛形を管理するだけ

Yeoman自体では何もすることはできません。別に用意された「ひな形」を個別にダウンロードして、管理・展開することだけを担当します。

初めてみよう

最初にNode.jsとnpmがインストールされているかを確認してください。もしインストールされていれば、いよいよYeomanをインストールする段階に移ります。

sudo npm install -g yo

インストールを実行すると以下のようになります。

npm WARN deprecated npmconf@2.1.2: this package has been reintegrated into npm and is now out of date with respect to npm

/usr/local/bin/yo -> /usr/local/lib/node_modules/yo/lib/cli.js

/usr/local/bin/yo-complete -> /usr/local/lib/node_modules/yo/lib/completion/index.js



> spawn-sync@1.0.15 postinstall /usr/local/lib/node_modules/yo/node_modules/spawn-sync

> node postinstall





> yo@1.8.5 postinstall /usr/local/lib/node_modules/yo

> yodoctor





Yeoman Doctor

Running sanity checks on your system



✔ Global configuration file is valid

✔ NODE_PATH matches the npm root

✔ Node.js version

✔ No .bowerrc file in home directory

✔ No .yo-rc.json file in home directory

✔ npm version



Everything looks all right!

- bl@1.0.3 node_modules/yo/node_modules/bl

- color-convert@1.0.0 node_modules/yo/node_modules/color-convert

- cross-spawn-async@2.1.9 node_modules/yo/node_modules/cross-spawn-async

- minimatch@3.0.0 node_modules/yo/node_modules/glob/node_modules/minimatch

- is-plain-obj@1.1.0 node_modules/yo/node_modules/is-plain-obj

- is-relative@0.1.3 node_modules/yo/node_modules/is-relative

- is-absolute@0.1.7 node_modules/yo/node_modules/is-absolute

- lru-cache@2.7.3 node_modules/yo/node_modules/minimatch/node_modules/lru-cache

- node-uuid@1.4.7 node_modules/yo/node_modules/node-uuid

- sigmund@1.0.1 node_modules/yo/node_modules/sigmund

- spdx-exceptions@1.0.4 node_modules/yo/node_modules/spdx-exceptions

- word-wrap@1.1.0 node_modules/yo/node_modules/word-wrap

- minimist@1.2.0 node_modules/yo/node_modules/yosay/node_modules/minimist

/usr/local/lib

└─┬ yo@1.8.5 

  ├─┬ chalk@1.1.3 

  │ └── ansi-styles@2.2.1 

  ├── cli-list@0.1.8 

  ├─┬ configstore@1.4.0

  │ ├── graceful-fs@4.1.11 

  │ ├── object-assign@4.1.1 

  │ ├── os-tmpdir@1.0.2 

  │ ├── osenv@0.1.4 

  │ ├── uuid@2.0.3 

  │ └── write-file-atomic@1.3.1 

  ├─┬ cross-spawn@3.0.1 

  │ ├── lru-cache@4.0.2 

  │ └── which@1.2.12 

  ├── figures@1.7.0 

  ├─┬ fullname@2.1.0

  │ ├─┬ npmconf@2.1.2

  │ │ ├── config-chain@1.1.11 

  │ │ ├── inherits@2.0.3 

  │ │ ├─┬ nopt@3.0.6

  │ │ │ └── abbrev@1.0.9 

  │ │ └─┬ once@1.3.3

  │ │   └── wrappy@1.0.2 

  │ └── pinkie-promise@2.0.1 

  ├─┬ got@5.7.1 

  │ ├── create-error-class@3.0.2 

  │ ├── is-retry-allowed@1.1.0 

  │ ├── is-stream@1.1.0 

  │ ├─┬ readable-stream@2.2.2 

  │ │ ├── buffer-shims@1.0.0 

  │ │ ├── isarray@1.0.0 

  │ │ └── process-nextick-args@1.0.7 

  │ ├── timed-out@3.1.3 

  │ ├── unzip-response@1.0.2 

  │ └─┬ url-parse-lax@1.0.0

  │   └── prepend-http@1.0.4 

  ├─┬ humanize-string@1.0.1

  │ └── decamelize@1.2.0 

  ├─┬ inquirer@0.11.4

  │ ├── ansi-escapes@1.4.0 

  │ ├── ansi-regex@2.1.1 

  │ ├─┬ readline2@1.0.1

  │ │ └── code-point-at@1.1.0 

  │ └── string-width@1.0.2 

  ├─┬ insight@0.7.0

  │ ├─┬ os-name@1.0.3

  │ │ ├─┬ osx-release@1.1.0

  │ │ │ └── minimist@1.2.0 

  │ │ └─┬ win-release@1.1.1

  │ │   └── semver@5.3.0 

  │ ├─┬ request@2.79.0 

  │ │ ├── aws4@1.5.0 

  │ │ ├─┬ form-data@2.1.2 

  │ │ │ └── asynckit@0.4.0 

  │ │ ├─┬ har-validator@2.0.6

  │ │ │ └─┬ is-my-json-valid@2.15.0 

  │ │ │   └── jsonpointer@4.0.1 

  │ │ ├─┬ http-signature@1.1.1

  │ │ │ ├─┬ jsprim@1.3.1 

  │ │ │ │ └── json-schema@0.2.3 

  │ │ │ └─┬ sshpk@1.10.2 

  │ │ │   ├── assert-plus@1.0.0 

  │ │ │   ├── bcrypt-pbkdf@1.0.0 

  │ │ │   ├─┬ dashdash@1.14.1 

  │ │ │   │ └── assert-plus@1.0.0 

  │ │ │   ├─┬ getpass@0.1.6 

  │ │ │   │ └── assert-plus@1.0.0 

  │ │ │   └── tweetnacl@0.14.5 

  │ │ ├─┬ mime-types@2.1.14 

  │ │ │ └── mime-db@1.26.0 

  │ │ ├── oauth-sign@0.8.2 

  │ │ ├── qs@6.3.0 

  │ │ ├── tunnel-agent@0.4.3 

  │ │ └── uuid@3.0.1 

  │ └─┬ tough-cookie@2.3.2 

  │   └── punycode@1.4.1 

  ├─┬ meow@3.7.0

  │ ├─┬ camelcase-keys@2.1.0 

  │ │ └── camelcase@2.1.1 

  │ ├─┬ loud-rejection@1.6.0 

  │ │ ├─┬ currently-unhandled@0.4.1 

  │ │ │ └── array-find-index@1.0.2 

  │ │ └── signal-exit@3.0.2 

  │ ├── minimist@1.2.0 

  │ └─┬ normalize-package-data@2.3.5

  │   ├── hosted-git-info@2.1.5 

  │   └─┬ validate-npm-package-license@3.0.1

  │     ├─┬ spdx-correct@1.0.2

  │     │ └── spdx-license-ids@1.2.2 

  │     └── spdx-expression-parse@1.0.4 

  ├─┬ npm-keyword@4.2.0

  │ └─┬ registry-url@3.1.0 

  │   └─┬ rc@1.1.6

  │     └── minimist@1.2.0 

  ├─┬ package-json@2.4.0 

  │ ├── registry-auth-token@3.1.0 

  │ └── semver@5.3.0 

  ├─┬ parse-help@0.1.1 

  │ └─┬ execall@1.0.0 

  │   └─┬ clone-regexp@1.0.0 

  │     ├── is-regexp@1.0.0 

  │     └── is-supported-regexp-flag@1.0.0 

  ├─┬ read-pkg-up@1.0.1

  │ └── find-up@1.1.2 

  ├─┬ repeating@2.0.1 

  │ └─┬ is-finite@1.0.2 

  │   └── number-is-nan@1.0.1 

  ├─┬ root-check@1.0.0

  │ ├── downgrade-root@1.2.2 

  │ └─┬ sudo-block@1.2.0

  │   └── is-docker@1.1.0 

  ├─┬ sort-on@1.3.0 

  │ └─┬ dot-prop@2.4.0 

  │   └── is-obj@1.0.1 

  ├─┬ tabtab@1.3.2 

  │ ├─┬ debug@2.6.0 

  │ │ └── ms@0.7.2 

  │ ├─┬ inquirer@1.2.3 

  │ │ ├── cli-width@2.1.0 

  │ │ ├─┬ external-editor@1.1.1 

  │ │ │ ├─┬ spawn-sync@1.0.15 

  │ │ │ │ ├─┬ concat-stream@1.6.0 

  │ │ │ │ │ └── typedarray@0.0.6 

  │ │ │ │ └── os-shim@0.1.3 

  │ │ │ └── tmp@0.0.29 

  │ │ ├── lodash@4.17.4 

  │ │ ├── mute-stream@0.0.6 

  │ │ ├─┬ run-async@2.3.0 

  │ │ │ └── is-promise@2.1.0 

  │ │ └── rx@4.1.0 

  │ ├── minimist@1.2.0 

  │ └─┬ npmlog@2.0.4 

  │   ├── ansi@0.3.1 

  │   ├─┬ are-we-there-yet@1.1.2 

  │   │ └── delegates@1.0.0 

  │   └─┬ gauge@1.2.7 

  │     ├── has-unicode@2.0.1 

  │     ├── lodash.pad@4.5.1 

  │     ├── lodash.padend@4.6.1 

  │     └── lodash.padstart@4.6.1 

  ├─┬ update-notifier@0.6.3 

  │ ├─┬ configstore@2.1.0 

  │ │ └── dot-prop@3.0.0 

  │ └─┬ semver-diff@2.1.0

  │   └── semver@5.3.0 

  ├─┬ user-home@2.0.0

  │ └── os-homedir@1.0.2 

  ├─┬ yeoman-character@1.1.0

  │ └── supports-color@3.2.3 

  ├─┬ yeoman-doctor@2.1.0

  │ ├─┬ bin-version-check@2.1.0

  │ │ ├── minimist@1.2.0 

  │ │ └─┬ semver-truncate@1.1.2 

  │ │   └── semver@5.3.0 

  │ ├── semver@5.3.0 

  │ └─┬ twig@0.8.9 

  │   └─┬ minimatch@3.0.3 

  │     └─┬ brace-expansion@1.1.6 

  │       └── balanced-match@0.4.2 

  ├─┬ yeoman-environment@1.6.6 

  │ ├── diff@2.2.3 

  │ ├─┬ globby@4.1.0 

  │ │ ├─┬ array-union@1.0.2 

  │ │ │ └── array-uniq@1.0.3 

  │ │ └─┬ glob@6.0.4

  │ │   ├── inflight@1.0.6 

  │ │   └── path-is-absolute@1.0.1 

  │ ├─┬ grouped-queue@0.3.3 

  │ │ └── lodash@4.17.4 

  │ ├─┬ inquirer@1.2.3 

  │ │ ├── cli-width@2.1.0 

  │ │ ├── mute-stream@0.0.6 

  │ │ └── run-async@2.3.0 

  │ ├── lodash@4.17.4 

  │ └─┬ mem-fs@1.1.3 

  │   ├── through2@2.0.3 

  │   ├── vinyl@1.2.0 

  │   └─┬ vinyl-file@2.0.0 

  │     └─┬ strip-bom-stream@2.0.0 

  │       └── first-chunk-stream@2.0.0 

  └─┬ yosay@1.2.1 

    ├── cli-boxes@1.0.0 

    ├─┬ taketalk@1.0.0

    │ └── minimist@1.2.0 

    └── wrap-ansi@2.1.0 

ひな形の導入

ひな形の導入はYeomanとは別に行う必要があります。 すべてのひな形の導入は以下の形式でnpmのレポジトリに保存してあります。

sudo npm install generator-{ひな形の名前} -g 

オプションの-gはグローバルにパッケージをインストールするという意味で、このオプションをつけることで、特定のディレクトリに依存せずにパッケージを利用できるようになります。 たとえば、angularJSの最も基本的なひな形である。angularであれば、以下のコマンドで導入します。

sudo npm install generator-angular -g

実際に実行してみましょう。

npm WARN deprecated graceful-fs@2.0.3: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.

npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

npm WARN deprecated CSSselect@0.4.1: the module is now available as 'css-select'

npm WARN deprecated CSSwhat@0.4.7: the module is now available as 'css-what'

npm WARN deprecated minimatch@0.2.14: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

npm WARN deprecated tough-cookie@0.9.15: ReDoS vulnerability parsing Set-Cookie https://nodesecurity.io/advisories/130

npm WARN deprecated node-uuid@1.4.7: use uuid module instead

- color-convert@1.0.0 node_modules/generator-angular/node_modules/color-convert

- lru-cache@2.7.3 node_modules/generator-angular/node_modules/file-utils/node_modules/lru-cache

- lru-cache@2.7.3 node_modules/generator-angular/node_modules/findup-sync/node_modules/lru-cache

- async@1.5.2 node_modules/generator-angular/node_modules/form-data/node_modules/async

- process-nextick-args@1.0.6 node_modules/generator-angular/node_modules/process-nextick-args

- pseudomap@1.0.2 node_modules/generator-angular/node_modules/pseudomap

- util-deprecate@1.0.2 node_modules/generator-angular/node_modules/util-deprecate

- readable-stream@2.0.5 node_modules/generator-angular/node_modules/bl/node_modules/readable-stream

- bl@1.0.3 node_modules/generator-angular/node_modules/bl

- word-wrap@1.1.0 node_modules/generator-angular/node_modules/word-wrap

- yallist@2.0.0 node_modules/generator-angular/node_modules/yallist

- lru-cache@2.7.3 node_modules/generator-angular/node_modules/yeoman-generator/node_modules/lru-cache

/usr/local/lib

├─┬ generator-angular@0.15.1 

│ ├─┬ chalk@1.1.3 

│ │ └── ansi-styles@2.2.1 

│ ├─┬ wiredep@2.2.2

│ │ ├─┬ glob@4.5.3

│ │ │ ├─┬ inflight@1.0.6 

│ │ │ │ └── wrappy@1.0.2 

│ │ │ ├── inherits@2.0.3 

│ │ │ ├─┬ minimatch@2.0.10

│ │ │ │ └─┬ brace-expansion@1.1.6 

│ │ │ │   └── balanced-match@0.4.2 

│ │ │ └── once@1.4.0 

│ │ ├── propprop@0.3.1 

│ │ └─┬ through2@0.6.5

│ │   └── readable-stream@1.0.34 

│ ├─┬ yeoman-generator@0.16.0

│ │ ├─┬ cheerio@0.13.1

│ │ │ └─┬ htmlparser2@3.4.0

│ │ │   └── readable-stream@1.1.14 

│ │ ├─┬ download@0.1.19

│ │ │ ├─┬ decompress@0.2.5

│ │ │ │ └─┬ tar@0.1.20

│ │ │ │   ├── block-stream@0.0.9 

│ │ │ │   └─┬ fstream@0.1.31

│ │ │ │     └─┬ graceful-fs@3.0.11 

│ │ │ │       └── natives@1.1.0 

│ │ │ ├─┬ nopt@2.2.1

│ │ │ │ └── abbrev@1.0.9 

│ │ │ └─┬ request@2.79.0 

│ │ │   ├── aws4@1.5.0 

│ │ │   ├─┬ form-data@2.1.2 

│ │ │   │ └── asynckit@0.4.0 

│ │ │   ├─┬ har-validator@2.0.6

│ │ │   │ ├─┬ is-my-json-valid@2.15.0 

│ │ │   │ │ └── jsonpointer@4.0.1 

│ │ │   │ └── pinkie-promise@2.0.1 

│ │ │   ├─┬ http-signature@1.1.1

│ │ │   │ ├─┬ jsprim@1.3.1 

│ │ │   │ │ └── json-schema@0.2.3 

│ │ │   │ └─┬ sshpk@1.10.2 

│ │ │   │   ├── assert-plus@1.0.0 

│ │ │   │   ├── bcrypt-pbkdf@1.0.0 

│ │ │   │   ├─┬ dashdash@1.14.1 

│ │ │   │   │ └── assert-plus@1.0.0 

│ │ │   │   ├─┬ getpass@0.1.6 

│ │ │   │   │ └── assert-plus@1.0.0 

│ │ │   │   └── tweetnacl@0.14.5 

│ │ │   ├─┬ mime-types@2.1.14 

│ │ │   │ └── mime-db@1.26.0 

│ │ │   ├── oauth-sign@0.8.2 

│ │ │   ├── qs@6.3.0 

│ │ │   ├── tough-cookie@2.3.2 

│ │ │   ├── tunnel-agent@0.4.3 

│ │ │   └── uuid@3.0.1 

│ │ ├─┬ file-utils@0.1.5

│ │ │ └─┬ minimatch@0.2.14

│ │ │   └── lru-cache@2.7.3 

│ │ └─┬ request@2.30.0

│ │   └─┬ tough-cookie@0.9.15

│ │     └── punycode@1.4.1 

│ └─┬ yosay@1.2.1 

│   ├── ansi-regex@2.1.1 

│   ├── cli-boxes@1.0.0 

│   ├─┬ repeating@2.0.1 

│   │ └─┬ is-finite@1.0.2 

│   │   └── number-is-nan@1.0.1 

│   ├─┬ string-width@1.0.2 

│   │ └── code-point-at@1.1.0 

│   └── wrap-ansi@2.1.0 

└── UNMET PEER DEPENDENCY generator-karma@>=0.9.0



npm WARN generator-angular@0.15.1 requires a peer of generator-karma@>=0.9.0 but none was installed.

この段階で、ひな形の"angular"が利用できるようになりました。いよいよ、このひな形を利用してプロジェクトを立ち上げてみましょう。

最初にホームディレクトリを作成します。

mkdir angular
cd angular

そしてYeomanを使って、先ほど導入した"angular"を展開します。

yo angular

すると、懐かしい感じのするアスキーアートが現れて・・

     _-----_     

    |       |    ╭──────────────────────────╮

    |--(o)--|    │    Welcome to Yeoman,    │

   `---------´   │   ladies and gentlemen!  │

    ( _´U`_ )    ╰──────────────────────────╯

    /___A___\   /

     |  ~  |     

   __'.___.'__   

 ´   `  |° ´ Y ` 

GulpとGruntどっちを使う?といった内容を尋ねてきます・

 Out of the box I include Bootstrap and some AngularJS recommended modules.



? Would you like to use Gulp (experimental) instead of Grunt? (y/N) 

Gulpを利用するのでyを入力して、エンター

? Would you like to use Gulp (experimental) instead of Grunt? (y/N) y

Sassを利用するか?BootStrapを利用するか?と次々と条件分岐が現れるので、Yes/Noと選択していきます

? Would you like to use Sass? No

? Would you like to include Bootstrap? Yes

AngularJSのモジュールで利用したいものを選べとのことです。

? Which modules would you like to include? (Press <space> to select, <a> to toggle all,
 <i> to inverse selection)
 ◉ angular-animate.js
❯◯ angular-aria.js
 ◉ angular-cookies.js
 ◉ angular-resource.js
 ◯ angular-messages.js
 ◉ angular-route.js
 ◉ angular-sanitize.js
 ◉ angular-touch.js

スペースキーを押して選択モードに移ります。iで個別の選択肢を反転、aですべての選択を反転します ここではすべてのモジュールを選択することにします。

angular-animate.js, angular-aria.js, angular
-cookies.js, angular-resource.js, angular-messages.js, angular-route.js, angular-saniti
ze.js, angular-touch.js
   create app/styles/main.css
   create app/index.html
   create bower.json
   create .bowerrc
   create package.json
   create gulpfile.js
   create README.md
   invoke   angular:common:/usr/local/lib/node_modules/generator-angular/app/index.js
   create     .editorconfig
   create     .gitattributes
   create     .jscsrc
   create     .jshintrc
   create     .yo-rc.json
   create     .gitignore
   create     test/.jshintrc
   create     app/404.html
   create     app/favicon.ico
   create     app/robots.txt
   create     app/views/main.html
   create     app/images/yeoman.png
   invoke   angular:main:/usr/local/lib/node_modules/generator-angular/app/index.js
   create     app/scripts/app.js
   invoke   angular:controller:/usr/local/lib/node_modules/generator-angular/app/index.js
   create     app/scripts/controllers/main.js
   create     test/spec/controllers/main.js
   invoke   karma:app

...

省略

...

├── open@0.0.5 
├─┬ rimraf@2.5.4 
│ └─┬ glob@7.1.1 
│   └── minimatch@3.0.3 
├── run-sequence@1.2.2 
└─┬ wiredep@2.2.2 
  ├─┬ bower-config@0.5.2 
  │ ├── graceful-fs@2.0.3 
  │ ├── mout@0.9.1 
  │ └── osenv@0.0.3 
  ├─┬ chalk@0.5.1 
  │ ├── ansi-styles@1.1.0 
  │ ├─┬ has-ansi@0.1.0 
  │ │ └── ansi-regex@0.2.1 
  │ ├── strip-ansi@0.3.0 
  │ └── supports-color@0.2.0 
  ├── glob@4.5.3 
  ├── lodash@2.4.2 
  ├── propprop@0.3.1 
  └─┬ through2@0.6.5 
    └── readable-stream@1.0.34 

npm WARN gulp-karma@0.0.4 requires a peer of karma@>=0.10 <=0.13 but none was installed.

・・と結構な時間がかかります。当方の環境では5分程度です。

基本的にYeomanを利用した開発手法ではgulpかGruntを利用するのが一般的です。

今回はgulpを選択しました。gulpfile.jsを見て、どのようなストリームが定義されているか確認するといいでしょう。

gulp.task('serve', function (cb) {

  runSequence('clean:tmp',

    ['lint:scripts'],

    ['start:client'],

    'watch', cb);

});

これを見るとserveで起動できるようです。実際にやってみます。

gulp serve

起動中


[20:00:17] Using gulpfile ~/Desktop/test/angular/gulpfile.js

[20:00:17] Starting 'serve'...

[20:00:17] Starting 'clean:tmp'...

[20:00:17] Finished 'clean:tmp' after 6.83 ms

[20:00:17] Starting 'lint:scripts'...

[20:00:17] Finished 'lint:scripts' after 88 ms

[20:00:17] Starting 'start:server'...

[20:00:17] Finished 'start:server' after 231 ms

[20:00:17] Starting 'styles'...

[20:00:17] Server started http://localhost:9000

[20:00:17] LiveReload started on port 35729

[20:00:17] Finished 'styles' after 90 ms

[20:00:17] Starting 'start:client'...

[20:00:17] Finished 'start:client' after 6.89 ms

[20:00:17] Starting 'watch'...

[20:00:18] Finished 'watch' after 465 ms

[20:00:18] Finished 'serve' after 892 ms

f:id:mochizuki_p:20170119201832p:plain

ブラウザが自動的に起動します。ここから少しづつオリジナルの仕様を追加していくことで、自分だけのアプリケーションを簡単にローンチすることができそうです。

まとめ

  • YeomanはNode.js製の"ひな形"展開ツール

  • “ひな形"はYeomanとは別に導入する

  • 導入した"ひな形"はYeomanを利用して何度でも利用できる。

  • Yeomanを使うことで、アプリケーションを高速にローンチすることが可能

今回は紹介することはできませんでしたが、オリジナルのひな形を作成して利用することもできます。

これはまた別の機会に