MEANをAngularで構築してみる

# MEANとは
LAMP(Linux、Apache、MySQL・MariaDB、Perl・PHP・Python)のようなソフトウェアバンドルの一種。

- M:MongoDB(jsonを扱うことができるドキュメント指向DB)
- E:Express(Node.js上で動作するバックエンドフレームワーク)
- A:AngularJS(フロントエンドjsフレームワーク)
- N:Node.js(サーバサイドjs環境)

各要素を見ると分かると思いますが、jsだけで開発可能というのが一番の特徴。ただし、Node.jsを使うので、あまり大規模なシステムには向いてないかと思います。

# 今回やる事
- MEANを構築 
- AはAngularJSではなく、Angular(4.x.x)を使う
- angular-cliを利用してAngularのプロジェクトを作成してから構築

# MEANのN：Node.js
## インストール
インストール方法は以下の記事で詳しく書かれています。
- [nodistでNode.jsをバージョン管理](http://qiita.com/satoyan419/items/56e0b5f35912b9374305)

この時、nodistのバージョンは6.9.x、npmは3.x.x以上にしておいてください(Angularで必要となるバージョン)。

# MEANのA：Angular
## プロジェクト作成
まずはangular-cliを入れます。

````
npm install -g @angular/cli
````

インストールが完了したら、プロジェクトを作成します。

```
ng new mean-test
```

mean-testはプロジェクト名なので、任意のものに変更しても大丈夫です。
必要なパッケージも自動でnpmでインストールされるので、結構時間がかかります。

ここまで完了したら、作成したプロジェクトのディレクトリ(mean-test)の中に移動して、以下のコマンドでとりあえずAngularの起動確認をしてみます。
※以降はカレントディレクトリがmean-testになっていることを前提に進めます。

```
ng serve --open
```
`--open`オプションを付けると自動でブラウザで`localhiost:4200`が開きます。

こんな感じに表示されればOK。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/43798ad0-e1b9-9f2e-e4db-23a4f7ea33dd.png)


# MEANのE：Express
# インストール
作成したプロジェクトのディレクトリ(mean-test)の中に移動して、Expressをインストールします。

```
npm install --save express
```

## 起動設定
インストール出来たら、server.jsを作成します。

```server.js
// 使用するライブラリの読み込み
const express = require('express');
const path = require('path');
const http = require('http');

// api.js(サーバサイドの処理スクリプト)の読み込み
const api = require('./server/routes/api');

// expressの初期化
const app = express();

// 静的ファイルパスの設定
// ビルド後のAngularのパスを設定する
app.use(express.static(path.join(__dirname, 'dist')));

// /apiでアクセスしたときはapi.jsを表示
app.use('/api', api);

// 任意のURLでアクセスしたときはdist/index.html(Angularのindex.html)を表示
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});

/**
 * ポート設定
 */
const port = process.env.PORT || '3000';
app.set('port', port);

/**
 * HTTPサーバの作成
 */
const server = http.createServer(app);

/**
 * ポート監視を開始する
 */
server.listen(port, () => console.log(`API running on localhost:${port}`));

```

あと、server/routes/api.jsも作ります。

```server/routes/api.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.header('Content-Type', 'text/plain;charset=utf-8');
  res.send('これはサーバサイドスクリプトだよ');
});

module.exports = router;

```

ここまでできたら、以下のコマンドでnode.jsの上でserver.jsを動かします。

```
node server.js
```

`localhost:3000でHTTPサーバが起動したよ`と表示されれば成功。
ブラウザから`localhost:3000`にアクセスしてみる。
基本的にどのようなパスにアクセスしても、`dist/index.html`が表示されるため、Angularの時に見た「app works!」という文字が表示されます。
しかし、`localhost:3000/api`にアクセスすると次のように、api.jsが動きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/264ba61a-8b90-d0de-3c87-c0aadd6e7fff.png)


# MEANのM：MongoDB
## インストール
まずはMongoDBをインストールします。
[MongoDB Download Center](https://www.mongodb.com/download-center#community)からインストーラをダウンロードします。
インストーラを起動して、進めていけばインストールできます。
完了したら、インストールフォルダ内のbinのパスを環境変数Pathに追加して、コマンドプロンプトから実行できるようにしておくと便利です。
インストールが完了したら、`C:\data\db`のディレクトリを作成しましょう。
これはMongoDBのデータが格納されるパス(デフォルトなので、設定で変更は可能)になります。

## 起動とデータ作成
次のコマンドでMongoDBを起動します。

```
mongod
```

MongoDBが起動したら別のコマンドプロンプトを起動します。
MongoDBへの接続し、test_dbというDBへの切り替えを行います。

```
mongo
uset test_db
```

さらに、コレクション(RDBMSでいうテーブル)usersを作成し、そこにデータを登録します。
この先、mongooseというライブラリを使ってNode.jsからMongoDBを呼び出しますが、その時の命名規則がモデル名のlower caseにsを付けたものになります。
今回、モデル名をUserにしたいので、usersになります。
コレクション作成後に、「satoh ichiro」「suzuki jiro」をjsonとして登録します。

```
db.createCollection('users');
db.users.insert( { last_name:'satoh', first_name:'ichiro' } );
db.users.insert( { last_name:'suzuki', first_name:'jiro' } );
```

データが登録されているかどうかは次のコマンドで確認します。

```
db.users.find()
```

## Node.jsとの接続
Node.jsのスクリプトからmongooseライブラリを使ってMongoDBと接続を行います。
まずは、mongooseをインストールします。

```
npm install mongoose
```

その後、server/routes/api.jsにmongooseでの接続処理を追加します。
今回は、api/userにアクセスしたときに表示されるようにしました。

```server/routes/api.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');

// スキーマを定義
var Schema   = mongoose.Schema;
var UserSchema = new Schema({
  first_name:  String,
  last_name: String
});
mongoose.model('User', UserSchema);

// MongoDBに接続
mongoose.connect('mongodb://localhost/test_db');

var User = mongoose.model('User');

router.get('/', (req, res) => {
  res.header('Content-Type', 'text/plain;charset=utf-8');
  res.send('これはサーバサイドスクリプトだよ');
});

router.get('/user',(req, res) => {
  
  // MongoDBからデータを取得
  User.find({}, function(err, docs) {
    res.json(docs);
  });
});

module.exports = router;
```

# 最終確認
Node.jsを一度停止し、再度server.jsを起動します。
その後、`localhost:3000/api/user`に接続すると、先ほど登録したjsonデータが表示されます。
(登録時に自動的に振られる_idも表示されます)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/73df073f-83ca-73d9-e2dd-f224341b243f.png)


これで一通り、MEANスタックができました。
今回はjsonのReadのみでしたが、mongooseを使えばCRUDも実現できます。
扱うのがjavascriptやjsonだけなので、javascriptだけ知っていればサーバサイドの処理もかけるようになる・・・と言いたいところですが、Node.jsを少し触りましたが結構javascriptとは別物の感じなのでそううまくはいかないようです。


# 参考
[MEAN App with Angular 2 and the Angular CLI ― Scotch](https://scotch.io/tutorials/mean-app-with-angular-2-and-the-angular-cli)
[Easily Develop Node.js and MongoDB Apps with Mongoose](https://scotch.io/tutorials/using-mongoosejs-in-node-js-and-mongodb-applications)
[Mongooseを使ってmongodbにアクセスしてみる](http://semind.github.io/blog/2012/03/05/mongooseshi-tutemita/)