headlessCMSの1つGraphCMSについて 


この投稿は、[静岡 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/shizuoka)の6日目のものです。

11/16(土)に開催した[Shizuoka\.js\#5](https://connpass.com/event/147685/)でJAMstackのことについて話し、SanityというheadlessCMSが使われていることを紹介しましたが、この補足として会社で使われているheadlessCMSのGraphCMSについて紹介します。

と言っても自分はそのGraphCMSを使わている案件には関与していないので、社内で聞いた話になります。
また、好みや個人の感想レベルの部分もあるかと思いますので、あくまで参考程度にしてもらえればと思います。

# GraphCMSが選ばれた理由

headlessCMSで一番メジャーなのは[Contentful](https://www.contentful.com/)だと思いますが、会社では使用するheadlessCMSにGraphCMSが選ばれました。自分は最初なぜ一番メジャーなContentfulではないのか？と疑問を持ちましたが、社内で聞いてみたところ納得いく理由が得られたので、Contentfulと比較しつつそのことについて説明します。

- [Contentful](https://www.contentful.com/pricing/?faq_category=payments-subscriptions&faq=what-type-of-spaces-can-i-have)
- [GraphCMS](https://graphcms.com/pricing/)

## 理由1：GraphQLファースト

GraphCMSは名前から分かるようにGraphQLファーストなheadlessCMSです。headlessCMSならGraphQL普通に使えるでしょ？と勝手に思い込んでいましたが、そうでもないことがわかりました。

- GraphCMS
    - personal（フリー）プランから、GraphQLが使用可能
- Contentful
    - GraphQLを使うには月額9万近いプランを選ばないといけない（[Pricing \| Contentful](https://www.contentful.com/pricing/?faq_category=payments-subscriptions&faq=what-type-of-spaces-can-i-have)）

GraphCMSであれば、フリープランでも管理画面から[graphql](https://github.com/graphql/graphiql)をすぐに使えて、簡単にクエリーを試すことが出来るので大変便利です。


## 理由2：コーポレート・記事特化ではない

Contentfulはコーポレートサイトや記事などを扱うブログやニュースサイトに特化しているように感じられるとのこと。その点GraphCMSは、ある程度データ的なものに対しても使いやすいので、請け負う仕事内容的にもGraphCMSのほうが合っているということでした。

## 理由3：レコード数制限

会社で使い始めた当初はGraphCMSはレコード数制限がなかったそうで、この理由も大きかったとのこと。

ただし、2019年12月現在、GraphCMSのプランを改めて調べてみたところ、プランの改定が行われたようでContentfulと同様のレコード制限が掛かってしまったようです。有償の中で一番安い月額4000円ほどのプランで、それぞれ5000レコードの制限があります。

## 理由4：UIが分かりやすい

GraphCMSのUIが分かりやすかったとのことでした。GraphCMSがどのような感じなのかを後述しますが、その説明のために自分でも実際に触りましたが、特に迷うことはなく、モデルを構成していくつかデータを入れた後に、graphiqlからクエリーを飛ばしてレスポンスを得ることが出来ました。

## GraphCMSのデメリット

ここまではGraphCMSの良い点ばかりを挙げてきましたが、デメリットもあります。GraphCMSではStagesがEnterpriseを除くプランでは、一番高いGrowth（月額43000円ほど）のプランでやっと2つです。ContentfulではSandbox environmentsが一番安いプランから1つ付いてきます。

# GraphCMSことはじめ

下記のような案件を、それをGraphCMSを使ったJAMstack構成で作ってみるというシナリオでスキーマ作りを進めてみます。

- 複数のお客さんが任意のドメイン・サブドメインを指定して、コーポレートサイトを持つことができる
- お客さんはトップ・概要・問い合わせ・記事ページで構成されるサイトを公開できる

管理画面からモデル・フィールドを定義してデータを入力し、そのデータをgraphiqlで取得するところまで進めてみることにします。

## プロジェクトの作成

ログインすると、「Create New Project」のボタンがあるので、これをクリックします。すでに作られているプロジェクトがあればここに並べられます。
「From Scratch」と「From Template」がありますが、ここでは一から構築したいので、「From Scratch」を選択します。

ダイアログが開くので必要な情報を入力し、リージョンはLoadTimeが一番小さいAsaEastを選択しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/60a32330-0a3b-1117-930b-3399796b0be9.png)

次にプランを選択しすが、無料の「Personal」を選択します。

## モデルの作成とフィールドの定義

最初にやるべきことはモデルの作成です。Schemaのページからモデルの作成を選択します。モデルはRDBで言うところのテーブルに相当します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/0c1f4764-c90a-1e0f-220b-160970ba8ec9.png)

モデルを作成したら、そのモデルにフィールドを定義していきます。ここではPageというモデルを作成したので、Titleなどをフィールドとして追加していきます。
フィールドの追加は画面右側に張り付いている「Filed」のタブをクリックし、モデルに追加したいフィールドの型をD&Dします。このとき、フィールドの名前を決めるためのダイアログが表示されますが、ダイアログ下のAdvancedを開くと必須項目かユニーク項目なのか等を選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/b979768b-8b7a-0150-b6e2-e8bc40bb42b0.png)

Schemaのページから、モデルの他にEnumerationを定義することができます。先程シナリオで、トップ・概要・問い合わせ・記事ページで構成されるサイトと説明しましたが、これらをEnumerationにCategoryTypeとして定義しました。このEnumerationをフィールドとしてモデル内に定義することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/acf8cdde-18d2-4976-c435-36fce23953cb.png)

また、モデル間同士の結びつきも簡単に定義することができます。フィールドの種類にReferenceという型があるので、これを選んで他のテーブルを指定します。ここでは、サイトとページを紐付けています。1つのサイトは複数のページを持つので1対多の関係で紐付けをしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/f72591d6-9f6f-328f-a5c9-c6402654581e.png)

## データの追加

モデルを作成したら、そのモデルに対してデータを追加していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/ba62dc50-9612-6ccf-a836-769a95a94d32.png)

必須項目のフィールドが未入力であれば、検証エラーが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/55fbb3ba-f656-79d2-10a9-a679233144da.png)

また、時間の入力などは専用の入力UIが用意されているので、スムーズに入力することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/52d788a3-877d-44a0-6c72-6571e8668da1.png)

## graphiql

最後にgraphiqlでクエリーを投げて、データを取得してみます。ここは唯一迷った箇所なのですが、ページ上部の「Stage: xxxx」の部分をmasterにする必要があります。デフォルトではManagementAPIが選択されていて、このままだと自分で定義したモデルと入力したデータを取得することができません。

クエリーをこのように書いて実行すれば、入力したデータが指定した構成で取得することが確認できます。

```graphql
{
  pages {
    title,
    category
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691/85eeaa0b-7e7c-b787-2109-6e627b8d970a.png)

# おわりに

GraphCMSについてメリット付きでざっと紹介しましたが、今後Contentfulがフリーや安いプランでもGraphQLに対応するかもしれませんし、すでに改定されたように更にGraphCMSのプランが変わる可能性もあります。また、もっとお得で高機能なheadlessCMSが登場するかもしれません。

このあたりも移行のし安さも含め検討していく必要があるでしょう。

また、勉強会でも話したとおりJAMstackもheadlessCMSも選択肢が増えたという認識であり、今仕事で請け負っている全ての案件に適用できるとは全く考えていません。JAMstackやheadlessCMSに向いている案件もあれば全く向いていない案件もあると思いますし、規模の大きい案件によっては、うまく組み合わせることで有用になるケースもあると考えています。

## shizuoka.jsについて

最後に少し。
ありがたいことに、割とshizuoka.jsまだですか？と言われることがありますが、あんまり頻繁に開催できておらず申し訳ないです。

地方の名を冠した勉強会なのであまり個人や企業の持ち物になるべきではないと考えていますので、代わりにやりたいという人がいれば、ぜひお声がけください。
また、勉強会開いてくれれば自分が喋ります！と言ってくれる人がいれば、開催回数も増やしていきたいので、今後ともぜひよろしくお願い致します。