Web API フレームワーク LoopBack で遊んでみる


## LoopBack とは

LoopBackは Web API フレームワークです。

最近は、よりリッチなユーザ体験を提供するために、Web アプリケーションをSPA化する流れが強くあるなーと思います。
それと同時に、バックエンドとしての API サーバ構築の需要もすごく高まってきていて、LoopBack はその API の生成がとても簡単にできるフレームワークです。

Node.js 製なので、フロントエンドとバックエンドを JavaScript のみで記述できます。Universal Web App！
Express がベースになっているのですが、大きな特徴として、モデルが生成されると同時に RESTful な API を自動で生成してくれます。
モデルの生成もジェネレータが用意されているので、一行もコードを書かずに API サーバを構築できます。

## LoopBack の特徴

[公式ドキュメント](https://docs.strongloop.com/display/JA/LoopBack)に特徴が載っていたので、さらっと転載しておきます。

- ほとんど、あるいは全くコードを書かずに、動的な end-to-end の REST APIs を作成できる
- 主要なリレーショナル・データベース、MongoDB、SOAPやREST APIのデータにアクセスできる
- モデル・リレーションシップと複雑なAPIへのアクセス制御を統合できる
- モバイルアプリのための、プッシュ通知、Geolocation、ファイル管理が扱える
- Android、iOS、JavaScript SDK のクライアントアプリを簡単に作ることができる
- オンプレミスでもクラウドでも動かすことができる

## 他の Node.js フレームワークとの比較

LoopBack と他のフレームワークの比較です。[公式の比較ページ](http://loopback.io/resources/#compare)を参照しつつ、調べてみました。

### LoopBack
- API framework
- StrongLoop社のAPIフレームワーク
- ブラウザから閲覧可能なAPIエクスプローラや、コードジェネレータを標準搭載
- Angular, Browser, Node.js, iOS, Android, Xamarin向けのクライアントサイド SDK がある
- プッシュ通知、ファイルストレージ、サードパーティログイン、位置情報と連携可能

### Express
- HTTP server liblary
- StrongLoop社のWebアプリケーションフレームワーク
- 最も知名度が高く、情報量も多い
- 機能はミドルウェアとして構築していく

### Hapi
- HTTP server framework
- コードを設定ファイルのように記述させることが大きな特徴
- 日本語の情報量は少ない

### Sails
- Web MVC framework
- RailsライクでフルスタックなWebアプリケーションフレームワーク
- 後から拡張していく思想の他のフレームワークとは異なり、単体で全部のせ
- Railsに似たジェネレータでCRUDなコードの生成が可能

### Meteor
- Full-stack JavaScript app platform
- SPA向けのフルスタックなWebアプリケーションフレームワーク
- GithubのStar数ではExpressを超え、昨年あたりから注目されている
- リアクティブアプリケーションを最小限のコードで構築可能
- JavaScript, Cordova for iOS and Android, React, AngularJS向けのクライアントSDKがある

LoopBackと他のフレームワークとの大きな違いは、APIフレームワークとして特化している点と言えそうです。

DBや外部APIとの連携もアドオンが一通り揃っていますし、iOS / Android 向けの SDK もあるのでネイティブアプリ開発にも利用できます。
多少のロジックも Express と同じように書けそうです。

Sails や Meteor のようなフルスタックフレームワークにも同等の機能はありますが、API サーバに使うにはちょっと重すぎると思います。
ライトな API サーバを、スピーディに構築するにはとても良さそうな印象。

## LoopBack で遊んでみる

さっそく、一通り LoopBack で遊んでみます。
分かりやすく、とても Minimal な Twitter の API を作ってみました。

### インストール
```
$ sudo npm install -g strongloop
```

### アプリケーションを作成
```
$ mkdir loopback-tutorial & cd loopback-tutorial
$ slc loopback
```

![loopback-tutorial-01.png](https://qiita-image-store.s3.amazonaws.com/0/44003/99303619-b8cf-0cae-100d-9a052039021e.png "loopback-tutorial-01.png")

アプリ名を聞かれるので、入力して Enter で進みます。
自動生成されるコードは下記の通り。

```
$ tree . -I node_modules
.
├── README.md
├── client
│   └── README.md
├── package.json
└── server
    ├── boot
    │   ├── authentication.js
    │   └── root.js
    ├── component-config.json
    ├── config.json
    ├── datasources.json
    ├── middleware.json
    ├── middleware.production.json
    ├── model-config.json
    └── server.js
```

### アプリケーションを起動
```
$ node .
```

`http://localhost:3000/`にアクセスすると、以下のようなJSONが表示されました。

```
{"started":"2016-02-25T12:48:39.571Z","uptime":39.405}
```

`http://localhost:3000/explorer/`にアクセスすると、このような画面に。

![loopback-tutorial-02.png](https://qiita-image-store.s3.amazonaws.com/0/44003/1f9f2166-ec43-50f4-14be-8ff4ebac988f.png "loopback-tutorial-02.png")

Userをクリックすると、既にAPIが作成されていることが分かります。

![loopback-tutorial-03.png](https://qiita-image-store.s3.amazonaws.com/0/44003/ebba9209-9128-8294-aec9-3c529970cdf3.png "loopback-tutorial-03.png")

### モデルを作成
```
$ slc loopback:model
? Enter the model name: Tweet                             // モデル名
? Select the data-source to attach Tweet to: db (memory)  // データの保存場所
? Select model's base class PersistedModel                // どのクラスを継承するか
? Expose Tweet via the REST API? Yes                      // REST APIとして公開するか
? Custom plural form (used to build REST URL):            // モデル名の複数形
? Common model or server only? common                     // 共有か、サーバのみか
Let's add some Tweet properties now.

Enter an empty property name when done.
? Property name: body                         // プロパティ名
   invoke   loopback:property
? Property type: string                       // 型
? Required? Yes                               // 必須かどうか

Let's add another Tweet property.
Enter an empty property name when done.
? Property name:[Enter]
```

`slc loopback:model`コマンドを終了すると、common ディレクトリが作られています。
React.js や Angular.js などと組み合わせて使う場合には、この common ディレクトリを共有します。

```
$ tree common
common
└── models
    ├── tweet.js
    └── tweet.json
```

`common/models`下には、`tweet.js`と`tweet.json`が新しく生成されています。
`tweet.json`には、下記のようなスキーマ情報が格納されています。

```common/models/tweet.json
{
  "name": "Tweet",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "body": {
      "type": "string",
      "required": true
    }
  },
  "validations": [],
  "relations": {},
  "acls": [],
  "methods": {}
}
```

もう一つの`tweet.js`は、実装ファイルです。まだ実装は何もありません。

```common/models/tweet.js
module.exports = function(Tweet) {

};
```

また、`server/model-config.json`の末尾に、モデルの情報が追加されています。

```
{
  ...
  "tweet": {
    "dataSource": "db",
    "public": true
  }
}
```

ちなみに、生成時に common ではなく server を選択すると、`common/models`ではなく`server/models`に生成されます。

`http://localhost:3000/explorer/`にアクセスすると、Tweet API が作られていることを確認できました。

![loopback-tutorial-04.png](https://qiita-image-store.s3.amazonaws.com/0/44003/85955007-313c-0bc0-6088-c2dd8e2c8dab.png "loopback-tutorial-04.png")

### DB との連携
```
$ npm install loopback-connector-mysql --save
```

使い方は [github](https://github.com/strongloop/loopback-connector-mysql) 上の README に書いてありますが、とても簡単。

`loopback-connector-mysql`パッケージをインストールしたら、`package.json`に依存関係のあるパッケージを追記して、`npm install`を実行します。

```
{
  ...
  "dependencies": {
    "loopback-datasource-juggler": "latest",
    "loopback-connector-mysql": "latest"
  }
}
```

あとは、`server/datasources.json`にDBの接続設定を書くだけとのこと。

```
    var DataSource = require('loopback-datasource-juggler').DataSource;
    var dataSource = new DataSource('mysql', {
        host: 'localhost',
        port: 3306,
        database: 'mydb',
        username: 'myuser',
        password: 'mypass'
    });
```

MySQL 以外にも、MongoDB / Oracle Database / PostgreSQL などに対応したコネクタが用意されているようです。
使用できるコネクタの一覧が下記に載っています。

[Connecting models to data sources](https://docs.strongloop.com/display/JA/Connecting+models+to+data+sources#Connectingmodelstodatasources-Connectors)

### モデルのリレーションを定義
```
$ slc loopback:relation
? Select the model to create the relationship from: Tweet  // リレーションを定義するモデル名
? Relation type: belongs to                                // リレーション定義
? Choose a model to create a relationship with: (other)    // どのモデルと関連付けるか
? Enter the model name: User                               // リレーション先のモデル名
? Enter the property name for the relation: user           // リレーション先のプロパティ名
? Optionally enter a custom foreign key:                   // カスタム外部キー
```

`slc loopback:relation`コマンドを実行すると、`common/models/tweet.json`にコードが追記されます。

```
  ...
  "relations": {
    "user": {
      "type": "belongsTo",
      "model": "User",
      "foreignKey": ""
    }
  },
  ...
```

### あれ？

ここで問題が発生。User モデルにリレーションを定義したかったのですが、モデルの候補に表示されず。
新しく User モデルを作ろうとしても、デフォルトで作られているからか `Validation error: invalid ModelDefinition - name: is not unique` が表示されてしまいました…。

(解決法をご存知の方がいたら教えてください！)

### もう一歩理解する

LoopBack がどのように動いているのかは、[LoopBack core concepts](https://docs.strongloop.com/display/JA/LoopBack+core+concepts) にまとまっています。
一読してみてから、簡単なロジックを書いてみる、外部連携を試してみる、などに手をつけてみると良いのかな？と思います。

実際に LoopBack を使ったアプリ開発をするなら、[Web 上の資料をまとめてくださっている記事](http://qiita.com/hashrock/items/ee440d9df36416826b63)があるので、一通り目を通しておくと良さそう。

## 感想

REST API の構築がすごく簡単で、いくつかコマンドを打ち込むだけでできてしまいました。

ちょうどタイミングよく [Web API The Good Parts](http://www.oreilly.co.jp/books/9784873116860/) を読んでいたところなのですが、
API の設計や、セキュリティや、外部 API との連携といった、そういった考えや知識を必要としないのは良いなーと思います。

LoopBack のようなフレームワークがあることで、デファクトスタンダードができ、私たち開発者一人一人が「ベストは何か」を考える必要がなくなっていくのは良いことだと、最近思っています。
[Rails の生みの親が唱える「設定より規約(CoC)」](http://postd.cc/rails-doctrine/)と同じで、より私たちが考えるべき問題に集中できるからです。

LoopBack がそういう立ち位置にはならないかもしれませんが、軽量な API サーバを立ち上げるには十分なフレームワークですし、今後もスピードが求められる場面で使ってみたいなと思えました。

余裕があれば、今度 [React-LoopBack](https://github.com/diogodoreto/react-loopback) に挑戦してみたいなと思います！

## 参考
- [メジャーなNode用Webアプリケーションフレームワークを比較する](http://qiita.com/nakahashi/items/15c016ff8beacd014fe4)
- [2014年 Webアプリケーションフレームワークトレンド（Node.js）](http://qiita.com/oukayuka/items/14bfdcb6b5411a2b4b7c)
- [ReactとLoopbackことはじめ / React.js meets Loopback](https://speakerdeck.com/tyshgc/react-dot-js-meets-loopback)
- [Loopbackでコード１行も書かないでAPIができた](http://qiita.com/chocopie116/items/612aaaba59fd88ffc5ad)
- [loopbackでアプリケーションを作成してユーザ登録APIを作るまで](http://hideack.hatenablog.com/entry/2015/05/04/112424)
- [loopbackでモデルのrelationを定義する](http://hideack.hatenablog.com/entry/2015/05/10/080000)