Windows環境でgenerator-angular-fullstackを使う

#はじめに
yeomanでお手軽にMEANアプリが作れそうなgenerator-angular-fullstackを使ってみたら全くお手軽でなかったのでメモを残します、、、（Windows環境だからな気もしますが）
ハマりポイントは後半に書いています。

#1.前提
以下の環境を前提に記述しています。

OS : Windows 10 (64bit)
Node.js : v4.4.7
npm : 3.10.6
monogodb : db version v3.2.7
generator-angular-fullstack : version 4.0.5

#2.環境構築
http://angular-fullstack.github.io/generator-angular-fullstack/Getting_Started/Prerequisites.html
に記載の通り環境を設定していきます。

(1) npmで必要なモジュールをインストール
`c:\dev\azure\generator-angular-fullstack>npm install -g yo gulp-cli generator-angular-fullstack`

(2) mongodbを起動
`c:\dev\mongodb>mongod --dbpath=data`

(3) npm環境変数設定
`c:\dev\azure\generator-angular-fullstack>npm config set python python2.7`
`c:\dev\azure\generator-angular-fullstack>npm config set msvs_version 2015`

(4)[Python2.7](https://www.python.org/downloads/)をインストール 

(5)[Visual C++ Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)をインストール


#3.generator-angular-fullstackの設定
`yo angular-fullstack`を実行し、authentication部分以外はデフォルト設定にします。

```
c:\dev\azure\generator-angular-fullstack>yo angular-fullstack

     _-----_
    |       |
    |--(o)--|   .--------------------------.
   `---------´  |    Welcome to Yeoman,    |
    ( _´U`_ )   |   ladies and gentlemen!  |
    /___A___\   '__________________________'
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

Out of the box I create an AngularJS app with an Express server.

# Client

? What would you like to write scripts with? Babel
? Would you like to use Flow types with Babel? No
? What would you like to write markup with? HTML
? What would you like to write stylesheets with? Sass
? What Angular router would you like to use? uiRouter
? Would you like to include Bootstrap? Yes
? Would you like to include UI Bootstrap? Yes

# Server

? What would you like to use for data modeling? (Press <space> to select)Mongoose (MongoDB)
? Would you scaffold out an authentication boilerplate? No
? Would you like to use socket.io? Yes

# Project

? What would you like to write tests with? Mocha + Chai + Sinon
? What would you like to write Chai assertions with? Expect
You're using the fantastic NgComponent generator.

Initializing yo-rc.json configuration.

(中略)

+-- webpack-dev-middleware@1.8.1
| `-- memory-fs@0.3.0
`-- webpack-stream@3.2.0
  +-- lodash.clone@4.5.0
  +-- lodash.some@4.6.0
  +-- memory-fs@0.3.0
  `-- vinyl@1.2.0

npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.14
npm WARN optional Skipping failed optional dependency /stylint/chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.14
npm WARN enoent ENOENT: no such file or directory, open 'c:\dev\azure\generator-angular-fullstack\node_modules\iltorb\package.json'
```

#4.サーバー起動
`gulp serve`を実行します。しばらくするとデフォルトブラウザが起動します。サーバーが立ち上がり切っていない状態ではブラウザで接続エラーが表示されますが、何度かリロードされ「Kick-start your next web app with Angular Fullstack」というメッセージが表示されます。

```
c:\dev\azure\generator-angular-fullstack>gulp serve
[00:53:31] Requiring external module babel-register
(node) crypto.createCredentials is deprecated. Use tls.createSecureContext instead.
(node) crypto.Credentials is deprecated. Use tls.createSecureContext instead.
[00:53:42] Using gulpfile c:\dev\azure\generator-angular-fullstack\gulpfile.babel.js
[00:53:42] Starting 'serve'...
[00:53:42] Starting 'clean:tmp'...
[00:53:42] Starting 'lint:scripts'...
[00:53:42] Starting 'lint:scripts:client'...
[00:53:42] Starting 'lint:scripts:server'...
[00:53:42] Starting 'inject'...
[00:53:42] Starting 'inject:scss'...
[00:53:42] Starting 'copy:fonts:dev'...
[00:53:42] Starting 'env:all'...
[00:53:42] Finished 'env:all' after 23 ms
[00:53:42] Finished 'clean:tmp' after 179 ms
[00:53:42] gulp-inject 3 files into app.scss.
[00:53:43] Finished 'inject:scss' after 1.62 s
[00:53:43] Finished 'inject' after 1.62 s
[00:53:45]
c:\dev\azure\generator-angular-fullstack\client\components\modal\modal.service.js
  42:22  warning  Avoid using Function.prototype.call, instead use Reflect.apply   prefer-reflect
  42:49  warning  Use the rest parameters instead of 'arguments'                   prefer-rest-params
  50:21  warning  Unexpected string concatenation                                  prefer-template
  68:13  warning  Avoid using Function.prototype.apply, instead use Reflect.apply  prefer-reflect

c:\dev\azure\generator-angular-fullstack\client\components\socket\socket.service.js
  40:17  warning  Unexpected string concatenation  prefer-template
  62:17  warning  Unexpected string concatenation  prefer-template
  77:33  warning  Unexpected string concatenation  prefer-template
  78:33  warning  Unexpected string concatenation  prefer-template

c:\dev\azure\generator-angular-fullstack\client\components\util\util.service.js
  59:99  warning  '===' should be placed at the beginning of the line  operator-linebreak

c:\dev\azure\generator-angular-fullstack\client\app\main\main.component.js
  35:23  warning  Unexpected string concatenation  prefer-template

✖ 10 problems (0 errors, 10 warnings)

[00:53:45] Finished 'lint:scripts:client' after 2.8 s
[00:53:45] Finished 'copy:fonts:dev' after 2.93 s
[00:53:45]
c:\dev\azure\generator-angular-fullstack\server\app.js
  16:17  warning  Unexpected string concatenation  prefer-template

c:\dev\azure\generator-angular-fullstack\server\index.js
  4:11  warning  Unexpected use of process.env  no-process-env
  4:34  warning  Unexpected use of process.env  no-process-env

c:\dev\azure\generator-angular-fullstack\server\routes.js
  20:33  warning  Unexpected string concatenation  prefer-template

c:\dev\azure\generator-angular-fullstack\server\config\express.js
  38:20  warning  Unexpected string concatenation  prefer-template
  65:25  warning  Unexpected use of process.env    no-process-env
  95:14  warning  Unexpected string concatenation  prefer-template

c:\dev\azure\generator-angular-fullstack\server\api\thing\thing.controller.js
   29:7  warning  Avoid using Function.prototype.apply, instead use Reflect.apply     prefer-reflect
   91:5  warning  Avoid using the delete keyword, instead use Reflect.deleteProperty  prefer-reflect
  102:5  warning  Avoid using the delete keyword, instead use Reflect.deleteProperty  prefer-reflect

c:\dev\azure\generator-angular-fullstack\server\api\thing\thing.events.js
  28:22  warning  Unexpected string concatenation  prefer-template

✖ 11 problems (0 errors, 11 warnings)

[00:53:45] Finished 'lint:scripts:server' after 3.13 s
[00:53:45] Finished 'lint:scripts' after 3.19 s
[00:53:45] Starting 'start:server'...
[00:53:45] Finished 'start:server' after 46 ms
[00:53:45] Starting 'start:client'...
[nodemon] 1.10.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: c:\dev\azure\generator-angular-fullstack\server/**/*
[nodemon] starting `node server`
(node) crypto.createCredentials is deprecated. Use tls.createSecureContext instead.
(node) crypto.Credentials is deprecated. Use tls.createSecureContext instead.
Express server listening on 9000, in development mode
[00:53:51] Finished 'start:client' after 5.89 s
[00:53:51] Starting 'watch'...
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
GET / 404 18.208 ms - 151
GET / 404 21.548 ms - 151
GET / 404 35.914 ms - 151
[00:53:51] Finished 'watch' after 88 ms
[00:53:51] Finished 'serve' after 9.24 s
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
GET / 404 31.518 ms - 151
GET / 404 31.845 ms - 151
GET / 404 34.225 ms - 151
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
Error: ENOENT: no such file or directory, stat 'c:\dev\azure\generator-angular-fullstack\client\index.html'
    at Error (native)
GET / 404 7.914 ms - 151
GET / 404 8.431 ms - 151
GET / 404 1041.198 ms - 151
GET / 404 1042.065 ms - 151
GET / 404 1040.841 ms - 151
GET / 404 1041.216 ms - 151
[BS] Proxying: http://localhost:9000
[BS] Access URLs:
 -------------------------------------
       Local: http://localhost:3000
    External: http://192.168.56.1:3000
 -------------------------------------
          UI: http://localhost:3002
 UI External: http://192.168.56.1:3002
 -------------------------------------
webpack: wait until bundle finished: /
webpack done hook
Hash: 5b2504243272267d110d
Version: webpack 1.13.2
Time: 11719ms
                  Asset     Size  Chunks             Chunk Names
          app.bundle.js   372 kB       0  [emitted]  app
    polyfills.bundle.js   206 kB       1  [emitted]  polyfills
       vendor.bundle.js  2.47 MB       2  [emitted]  vendor
      app.bundle.js.map   476 kB       0  [emitted]  app
polyfills.bundle.js.map   270 kB       1  [emitted]  polyfills
   vendor.bundle.js.map  2.88 MB       2  [emitted]  vendor
   ../client/index.html  1.39 kB          [emitted]
Child html-webpack-plugin for "..\client\index.html":
                   Asset     Size  Chunks       Chunk Names
    ../client/index.html  2.69 kB       0
webpack: bundle is now VALID.
SocketIO / [127.0.0.1:50538] CONNECTED
GET /api/things 200 22.420 ms - -
```

うまく起動できると以下の画面が表示されます。
![image](https://qiita-image-store.s3.amazonaws.com/0/131481/625e0852-1141-37a2-0865-efbc8b7f4e90.png)

#4.ハマりポイント
- node-gypがインストールされるがpythonとC++のビルド環境が必要となるので事前にインストールしておく必要がある
- pythonはv2.7系が必要 [^1]
- Visual Studio 2015 Community Edition(VS2015)ではbuildに失敗
- VC++単独ビルドツール[Visual C++ Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)でbuildすると成功する [^2]


#参考
https://www.npmjs.com/package/generator-angular-fullstack
http://angular-fullstack.github.io/generator-angular-fullstack/index.html
http://blog.chat.ac/yeoman%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6meanmongodbexpressangularjsnode-js%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%82%88%E3%81%86/
https://github.com/nodejs/node-gyp/issues/629
https://github.com/nodejs/node-gyp/issues/802


---
[^1]: python v3.x系は使用不可。v2.7系をインストールする必要があります。
[^2]: VS2015が入っていると[Visual C++ Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)がインストールできないため、VS2015を削除してからインストールする必要があります(削除も結構時間がかかります)。また、なぜVS2015だとビルドがうまくいかないのかは現時点では不明ですが、同様の事象に遭遇している人もいるようなのでVS2015の使用は避けたほうが無難です。