Gatsby, Contentful, FirebaseでニュースアプリのMVPを作ってみた

# tl;dr
ニュースアプリのMVP（Minimum Viable Product）をGatsbyJS, Contentful, Firebaseで作りました。高速で構築できました。プロトタイピングと改善のプロセスを素早く回せる感触が得られました。

# MVPの要件

MVPの要件は経済ニュースコンテンツへの反応を探ることです。とても一般的なニュースアプリをMVPとして試すことにしました。この要件に最も適しているのが、GatsbyJS, Contentful, Firebaseという構成だと僕は考えました。

# GatsbyJS

GatsbyJS は静的PWA（Progressive Web App）ジェネレータです。Gatsby がその内部でどのように機能するのかを見てみましょう。アプリの実行時にAPIリクエストを行う SPA とは異なり、Gatsby はビルド時にローカルファイルからのデータの取得を含め、すべてのデータの取得を済ませてしまいます。GatsbyJSはこのデータをすべてHTML、JavaScript、およびCSSファイルの生成に使用します。このサーバーサイドレンダリング（SSR）はロードをとても速くします。動的にページを生成するためにサーバーに頼るのではなく、構築時にそれらのすべてを事前にレンダリングして CDN を使用することで、世界中のユーザーがすばやくスムーズに体験できるようにします。Gatsby アプリは初回ローディングの後は他のページのためにリソースをプリフェッチするので、読み込みを驚くほど速くすることができます。

# コンポーネント

コンポーネントはReactの重要な機能であり、現在では一般的なWebデザインパターンになっています。現在の複雑なレベルのユーザーインターフェイスでは、HTMLの長いページに保守可能なコードを記述したり、テンプレートエンジンを使用したりして一貫性を期待することはほとんど不可能です。代わりに、再利用可能なコンポーネントを構築してから、それらを使用してビューを構築します。このようにして別々のものを扱う別々のモジュールを使うことでその管理と維持がより簡単になります。GatsbyはReactを使用しているため、そのデザインパターンに従います。

# Webpack

Webpackは、HTML、JavaScript、およびCSSの最適化されたバンドルを作成します。 Babelおよびその他のプラグインで事前設定されている場合は、最新のES6 + JavaScriptとGraphQLを使用できます。ホットリロードとコード分割を内蔵しており、より良い開発経験とより良いサイトパフォーマンスを提供しています。 これは、開発者が最小限のツール構成を作成し、実際のサイト開発に集中することを目的としています。フロントエンドは近年”インフラ”が肥大化しており、それはあなたがスピーディにMVPを作りたいと考えたとき、まぎれもなく障害になります。あなたが静的ページを必要としている限りGatsbyJSはこの障害を軽減してくれます。

# Gatsby Plugin

Gatsbyは拡張性と柔軟性があります。プラグインはそれを活用するひとつの方法です。サイトのオフライン閲覧を可能にする、Googleアナリティクスを追加する、インラインSVGのサポートを追加するなど、さまざまな機能をプラグインを介して。リストはほぼ無限です。Gatsbyプラグインは、それを使い始めるための素早い方法を示すスターターをしばしば持っています。

# スターター
これらは基本的に定番のGatsbyサイトで、どの種類のサイトであるかに応じて迅速に開発を始めることができます。それらはあなたが直接あなたが構成と基本的な機能の開発に取り組むことに直接入るのを助けます。つまり、ツーリングの時間が減り、開発の時間が増えます。僕は[”gatsby-starter-gcn”](https://github.com/ryanwiemer/gatsby-starter-gcn) （作者 ryanwiemer）を採用しました。このスターターはデータソースとしてヘッドレスCMSの[Contentful](https://www.contentful.com/developers/)を採用しています。

# GraphQL

GraphQLはAPIのためのクエリ言語です。GraphQLは、特定のデータベースやストレージエンジンに結び付けられているのではなく、既存のコードやデータによって支えられています。スキーマは厳密に型指定されています。 スキーマでは、idの変数は整数でなければならないと規定されています。 クライアントが代わりに整数以外の値を送信した場合、GraphQLエンジンはクエリ全体を拒否します。

GraphQLの役割はRESTの代替であることです。利点としてはRESTではURLがひとつのリソースを示すため、複数のリソースが必要な複雑な画面では複数回のAPIリクエストが必要になります。パフォーマンスが落ちたりコードの複雑さが増す欠点がありました。

GraphQLは後述するマイクロサービスのGateway（中間層）として役割も期待されます。GatewayとしてのGraphQLサーバはスキーマ定義に対応するデータを複数のデータソースからフェッチします。その際には直接DBを叩いてもいいし、既存のRESTful APIを叩いてもいいです。

GraphQLの利点としてGraphQLがクエリとレスポンスの構造に対応関係があるおかげでクライアントのコーディングが簡単になったり、コーデリーディングやクエリの学習コストが低いことが挙げられます。他方、クライアントの実装に比べてGraphQL処理系を実装するのが難しかったり、画像や動画などの大容量バイナリの扱いが難しかったりする点が欠点と指摘されています。

# Contentful 

コンテンツのデータを提供するのがContentfulです。ヘッドレスCMSとは、あらゆるデバイスで表示するためにREST APIを介してコンテンツにアクセスできるようにするコンテンツリポジトリとしてゼロから構築された、バックエンド専用のコンテンツ管理システムです。

このContentfulのAPIを上記のGraphQLで叩きます。ヘッドレスCMSを採用した場合、フロントエンドを別個JSフレームワーク等で構築します。Contentfulにはアプリケーションの更新情報を他のアプリケーションへリアルタイム提供するWebhookという機能があります。

# build

ContentfulのAPIキーの入力等はすべてGatsby CLIを通じてコマンドライン入力で完了しました。サイトのビルドも`gatsby build`で行えます。`gatsby develop`でホットリロードしながら開発することもできます。

# Firebase Hosting

ビルドした後はFirebase Hostingでホスティングしました。GatsbyJSはNetlifyの利用を推奨していますが、CDNと今後の開発のための環境を検討した結果、Firebaseの方が好ましいとの結論に至りました。

# MVPの成否

素早く試すことができました。

# 今後必要な機能

ログインしたユーザーに対し推薦システムでユーザーの嗜好に合うコンテンツ群を提示することを検討しています。

将来的にモバイルクライアントを開発することが目に見えているため、それに適合するMicroservicesアーキテクチャを採用します。そのためWebアプリケーション開発の現段階からフロントエンドのためのバックエンド（サーバ）であるBackends For Frontends（BFF）を構築します。BFFサーバを立てることで、さまざまな処理をBFFに移譲させることができ、バックエンドでセッションなどを管理する必要はなくなります。

バックエンドでは記事、画像、動画コンテンツ等の管理、推薦システム等を構築します。Contentfulにコンテンツ管理とデリバリの責務を与えているように、サードパーティAPIを組み合わせる形でバックエンドを構成することを厭いません。

BFFの導入により、フロントエンドとバックエンドの境界を設けてアーキテクチャのレイヤーを分割することで役割を明確にし、独立して開発を進めやすくなります。推薦システムの開発は独立したチームが必要な、技術とビジネスの両面において重要な機能です。モノリシックな開発に比べ速度感が劣る点もあるかもしれませんが、長期的にはこのアプローチの方が利得が大きいと想定しています。

# 最後に

ここまで読んでくれてありがとうございます。Twitterのフォローお願いします。リポジトリはこちらにあります。
https://github.com/taxiyoshida/gatsby-firebase-app

# Reference
藤 吾郎（ふじ・ごろう）: 「GraphQL」徹底入門 ─ RESTとの比較、API・フロント双方の実装から学ぶ
https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000

Sam Newman "Pattern: Backends For Frontends"
https://samnewman.io/patterns/architectural/bff/