Graphcoolについて、チュートリアル等を通じて調べてみた

## はじめに
本記事はグロービス [Advent Calendar 2017](https://qiita.com/advent-calendar/2017/globis) 24日目の記事です。
グロービスでは[エンジニアを募集](https://www.wantedly.com/companies/globis)しております。

## 本記事のきっかけ
### そもそもの話
[【初級者】React/GraphQLで作るサーバレスWebアプリ開発ハンズオン★手軽なアプリ開発体験](https://ebisu-js.connpass.com/event/70710/)の勉強会に参加して、[GraphQL](http://graphql.org/)と出会ったのが、そもそものきっかけです。

上記勉強会で、GraphQLを使うためのサーバーレスなクラウド上のバックエンドサービス（BaaS）である[GraphCMS](https://graphcms.com/)を用いて、リッチなGUIの管理画面上で、GraphQLのModel定義からコンテンツの登録等を行いました。

### そこで、今回
同じくBaaSである[Graphcool](https://www.graph.cool/)をはじめて触ってみて、Graphcoolに関する日本語の記事がまだ少なかったこと（GraphCMSも少ないですが…）と、Graphcoolやその周辺技術（GraphQL、Apollo、React）に関する自身の理解を深める意味も含めて、Advent Calendarとして書いてみることとしました。

## 実行環境
- Mac OS Sierra: v10.12.6
- node: v8.2.0
- npm: v5.3.0
- Docker: v17.03.1-ce-mac12

## Graphcool概要
[公式サイト](https://www.graph.cool/)（2017年12月23日時点）には
> Open-source framework to develop and deploy production-ready serverless GraphQL backends. Including GraphQL database mapping, real-time subscriptions & flexible permission system.

と、TOPページのファーストビューに記載されており、軽く訳すと

1. 本番適用可能なサーバーレスのGraphQLバックエンドを開発およびデプロイするためのオープンソースのフレームワークである
2. GraphQLによるデータベースマッピング、リアルタイムな **subscriptions** および柔軟な **permission system** を含む

という感じになるかと思います。
1. の方がGraphcool自身の概要（特徴）っぽくて、2. の方はGraphQLを通じて出来ることについて書かれています。
`subscriptions`はデータ変更情報の受け取り通知の仕組みを指しています。
`permission system`は認証システムを指しており、*flexible*というのは、直訳すると「柔軟な」とか「融通の効く」という意味になりますが、Graphcoolでは[functions](https://www.graph.cool/docs/reference/functions/overview-aiw4aimie9/)をベースとして、この認証システムを構築することが出来ます。

### コアな部分を支えている技術はScala
> The core technology behind the Graphcool Framework is written in Scala to guarantee stable, high performance. As a developer using the framework, you can use JavaScript or any other language you like. Most open source tools by Graphcool are written in TypeScript.

安定性や高パフォーマンスを担保するために、ScalaがGraphcoolフレームワークのコアな部分を支える言語として採用されている様ですが、フレームワークのユーザーとなる開発者は、JavaScriptをはじめとする好きな言語を使える様です。

### 料金体型
クラウド上でホスティングサービスを展開しており、無料で使えるShared clusterからAWS等にデプロイ可能な有料のPrivate Clusterまで、2017年12月23日時点では、大きく分けて４つのタイプが存在しています。
[GRAPHCOOL CLOUD](https://www.graph.cool/cloud/)

### 人気度の比較
Graphcoolと先のGraphCMSを比較すると、Googleの検索ボリュームは2017年12月21日時点では、Graphcoolが勝っています。
![fff06294-4dde-03dc-d0d3-cd70983f39d5.png](https://qiita-image-store.s3.amazonaws.com/0/199911/2473e1f3-5663-503f-a232-adce69fe08cb.png)


## チュートリアル体験
習うより慣れろ、ということで、公式サイトの **GET STARTED** をポチッと押して、ドキュメントに隅々まで目を通すよりも、まずは[チュートリアル](https://www.graph.cool/docs/quickstart/)を試すことにします。

> Get started with your favorite technology

おたくの好きな技術を選んでね、ということなので、まずは業務でも使うフロントエンドのReactをチョイスし、[React & Apollo Quickstart](https://www.graph.cool/docs/quickstart/frontend/react/apollo-tijghei9go)からようやく始められます。

### React & Apollo Quickstart
React, Apollo ClientおよびGraphQLを用いて、シンプルなInstagramのクローンを作っていきます。

###1. リポジトリのクローンからquickstart-with-apolloへの移動
GitHubにチュートリアル用のリポジトリが用意されているので、ターミナルからgit cloneして、react-graphql/quickstart-with-apolloディレクトリに移動します。

> 1.　Clone the example repository that contains the React application:

```
$ git clone https://github.com/graphcool-examples/react-graphql.git
$ cd react-graphql/quickstart-with-apollo
```

### 2. 管理ツールをインストール 

次に、Graphcoolのサービスを管理するためのツールをインストールしましょう。

> 2.　Install the Graphcool CLI:

```
$ npm install -g graphcool
```

グローバルインストールなので、これが成功すると、ローカルのどこでも`graphcool`コマンドが使える様になり、Graphcoolサービスのデプロイ、初期セットアップ、メール認証によるテンプレートの追加等が実行出来ます。
その他、コマンド一覧は[こちら](https://www.graph.cool/docs/reference/graphcool-cli/commands-aiteerae6l/)。

### 3. graphcool initによる初期化

> 3.　Create the local file structure for a new Graphcool service inside a directory called server:

`graphcool init`コマンドを用いて、**server** という名前のディレクトリの内部に、Graphcoolサービス用のローカルファイル構造を作成します。

```
# Create a local service definition in a new directory called `server`
$ graphcool init server
```

### 4. データModelの設定
次にサービスのデータModelを設定（スキーマの定義）します。
作成したserverディレクトリの中に`types.graphql`という、GraphQLのデータModelを含んだファイルが一緒に生成されているので、次の **Post** というオブジェクト型の定義を追加します。（既存の **User** という型は、削除またはコメントアウトします ）
> 4.　Open ./server/types.graphql and add the following type definition to it (feel free to delete the existing User type):

```quickstart-with-apollo/server/types.graphql
type Post @model {
  id: ID! @isUnique    # read-only (managed by Graphcool)
  createdAt: DateTime! # read-only (managed by Graphcool)
  updatedAt: DateTime! # read-only (managed by Graphcool)

  description: String!
  imageUrl: String!
}
```

`id`や`createdAt`はフィールドと呼ばれており、`:`の後ろに続く`ID`や`String`でそれらのフィールドの型が何かを示しています。
`!`はNot Nullを指定します。
その他、これらの型やスキーマについて、詳しくは[GraphQLの公式ページ](http://graphql.org/learn/schema/)をご参照ください。

また、`@`が付いているものはディレクティブと呼ばれるもので、その名の通り、フィールドに対する指示を与えます。（上記例では、`id`フィールドに格納される値をユニークなものとする）
こちらも詳しくは公式の[Directivesの項](http://graphql.org/learn/queries/#directives)などをご参照ください。

### 5. graphcool deployによるデプロイ
続いて、`server`ディレクトリに移って、`graphcool deploy`コマンドを実行し、デプロイします。

> 5.　Navigate to the server directory and deploy your service:

```
$ cd server
$ graphcool deploy
```

`graphcool deploy`コマンドを実行すると、３つの質問をされます。
はじめの質問で、Shared Clusters（フリーで使えるクラウドのホスティングサービス）の指定を求められますので、いずれかのリージョンを指定します。

※）もし、クラウドではなく、ローカル環境にGraphcoolのサービスを構築して接続したい場合は、[こちらの手順](#ローカル環境での確認方法)より、Dockerを用いて`local`を指定することが可能になります。

次に、`target name`を聞かれますが、特にこだわりない場合は、enterキーを押せば、デフォルトの`prod`が適用されます。

続いて、`service name`を聞かれますが、こちらも特にこだわり無ければ、デフォルトの名前が適用されます。

また、初めてGraphcool CLIに認証を通す場合は、ブラウザが起動し、次の様に認証手続きを求められる画面が表示されますが、[GraphcoolのConsole](https://console.graph.cool/login)にログインしているかしていないかで、次の通り、表示される画面が異なります。 

＜未ログインの場合＞
![milogin.png](https://qiita-image-store.s3.amazonaws.com/0/199911/006d3253-374f-60e5-86ec-67b980157649.png)



Sign Up（アカウント登録）は、GitHubまたはGoogleによる登録が楽です。

＜ログイン済の場合＞
<img width="320" alt="loginzumi.png" src="https://qiita-image-store.s3.amazonaws.com/0/199911/9c7f80a1-8a5e-2a5a-3a6b-be2b8f4102d5.png">


**AUTHORIZE CLI** をクリックして進みます。

無事、認証に成功すると、次の画面が表示されます。
<img width="320" alt="success.png" src="https://qiita-image-store.s3.amazonaws.com/0/199911/f6d881c0-c1c6-3f7d-f1d9-ca68e5368523.png">

### 6. APIエンドポイントを取得
前回のステップで、ターミナルの最後に

```
Here are your GraphQL Endpoints:

  Simple API:        https://api.graph.cool/simple/v1/xxxxx
  Relay API:         https://api.graph.cool/relay/v1/xxxxx
  Subscriptions API: wss://subscriptions.graph.cool/v1/xxxxx
```

の様に、エンドポイントが出力されています。
この内、`Simple API`は後のApolloからの接続に必要な情報となりますので、手元にメモしておきましょう。（もし、忘れた場合でも、後から`graphcool info`コマンドで確認が可能です）

> 6.　Save the HTTP endpoint for the Simple API from the output of the graphcool deploy command, you'll need it later!

また、この時点で`graphcool playground`コマンドを実行すると、Graphcoolのconsole画面が立ち上がり、次の様なGraphQLのクエリをたたいて、DBから情報を取得（query）出来たり、新規にデータを作成（mutation）すること等が出来ます。

### 全記事の情報を取得

```
query {
  allPosts {
    id
    description
    imageUrl
  }
}
```
![listview.png](https://qiita-image-store.s3.amazonaws.com/0/199911/db3b0263-795b-b7b6-2886-228bd2f23e60.png)


### 新規記事を追加

```
mutation {
  createPost(
    description: "テスト投稿"
    imageUrl: "https://xxxxxx.imageurl.com"
  ) {
    id
  }
}
```
![add.png](https://qiita-image-store.s3.amazonaws.com/0/199911/fd500834-246b-358d-36e9-54cc464e41dc.png)


### 7. React（Apollo）からGraphcoolへの接続

次は、Simple APIのエンドポイントを`./src/index.js`に貼り付けて、自分で立てたGraphcoolサービスと、ローカルのReactアプリを接続します。
（接続には、GraphQLのフロントの実装ライブラリである[Apollo Client](https://github.com/apollographql/apollo-client)を使います）

> 7.　Paste the HTTP endpoint for the Simple API that you saved after running graphcool deploy into ./src/index.js as the uri argument in the HttpLink constructor call:

```
const httpLink = new HttpLink({ uri: '__SIMPLE_API_ENDPOINT__' })
```

↓

```
const httpLink = new HttpLink({ uri: 'https://api.graph.cool/simple/v1/xxxxx' })
```

### 8. Reactアプリの起動
最後に、package.jsonで指定されているパッケージをインストールし、アプリを起動します。
> 8.　Install dependencies and run the app:

```
$ cd ~/react-graphql/quickstart-with-apollo
$ yarn install
$ yarn start
```

（デフォルトではlocalhost:3000で立ち上がりますので、他のアプリで同じポートを使用して立ち上げている場合は一旦、他のアプリをstopしておいてください）

アプリが正常に起動すると、次の様な画面が表示されます。

<img width="320" alt="appli.png" src="https://qiita-image-store.s3.amazonaws.com/0/199911/34f4bae9-06a8-7542-9196-b5022030a2bf.png">


### ローカル環境での確認方法
Dockerがインストールされていることが前提です。

１）最新のClusterをリモートから取得

```
$ graphcool local pull
```

２）１）で取得したローカルのClusterを起動

```
$ graphcool local up
```

ここまで問題なければ、`docker ps`を実行すると、２つのコンテナが確認できます。

```
$ docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                      NAMES
c71fd2a3699b        graphcool/graphcool-dev:0.9.0   "/app/bin/single-s..."   14 minutes ago      Up 14 minutes       0.0.0.0:60000->60000/tcp   local_graphcool_1
69e7ae794928        graphcool/localfaas:0.9.0       "/app/bin/localfaas"     14 minutes ago      Up 14 minutes       0.0.0.0:60050->60050/tcp   local_localfaas_1
```

参考：[Deployment with Docker](https://www.graph.cool/docs/reference/deployment/overview-ohs4asd0pe#deployment-with-docker)

## さいごに
概要に書いた通り、GraphQLのsubscriptions（データ変更情報の受け取り通知の仕組み）や、Facebook、emailによる認証システム等の構築が、Graphcoolを通じて簡単に出来る様なので、これからももっと色々と触って試してみて、可能性を探ってみたいと思います。