GraphQL Apolloを試す

GraphQLのフロントエンド&バックエンドのライブラリであるApolloを試す。

Apollo

  • GraphQL のサーバー・クライアント用のライブラリ
  • Meteor を開発している Meteor Development Group 社が開発
  • FE側ではapollo-clientを、BE側ではapollo-serverを導入する

apollo server

プロジェクト作成

mkdir graphql-server-example
cd graphql-server-example
npm init -y

パッケージインストール

npm install apollo-server

サーバー作成

以下コードのindex.jsを作成する

const { ApolloServer, gql } = require("apollo-server");

// スキーマ定義
const typeDefs = gql`
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`;
// データセット定義
const books = [
  {
    title: "Harry Potter and the Chamber of Secrets",
    author: "J.K. Rowling"
  },
  {
    title: "Jurassic Park",
    author: "Michael Crichton"
  }
];

// リゾルバー定義
const resolvers = {
  Query: {
    books: () => books
  }
};

// ApolloServer生成
const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

サーバー起動

$ node index.js
🚀  Server ready at http://localhost:4000/

リクエス

{
  books {
    title
    author
  }
}

f:id:kimai007:20200208160017p:plain

shcema定義を、ファイルから読み込むようにする

  • schema定義を、index.jsで定義していたが、実際はschema用ファイルを用意することが想定される。
  • そこで、schema.graphqlを読み込むようにしてみる。

schema.graphqlを用意する

type Book {
  title: String
  author: String
}

type Query {
  books: [Book]
}

index.js編集

fs.readFileSyncでgraphqlファイルを読み込むようにする

const { ApolloServer, gql } = require("apollo-server");

// スキーマ定義
const fs = require("fs");
const typeDefs = gql`
  ${fs.readFileSync(__dirname.concat("/schema.graphql"), "utf8")}
`;

// データセット定義
const books = [
:

あとはサーバーを起動しリクエストすれば、先程と同様のレスポンスを得られる

apollo client

apollo boost

今回はget-startedに沿って、こちらのパッケージを利用する

パッケージインストール

npm install apollo-boost @apollo/react-hooks graphql
npm install react react-dom react-scripts

プロジェクト作成

mkdir graphql-client-example
cd graphql-client-example
npm init -y

クライアント作成 (src/index.js)

以下コードのindex.jsを作成する。 Basic Apollo app - CodeSandbox のコードを参考に動かしてみる。

import React from "react";
import { render } from "react-dom";

import ApolloClient from "apollo-boost";
import { ApolloProvider, useQuery } from "@apollo/react-hooks";
import gql from "graphql-tag";

const client = new ApolloClient({
  uri: "http://localhost:4000/graphql"
});

function FetchBooks() {
  const { loading, error, data } = useQuery(gql`
    {
      books {
        title
        author
      }
    }
  `);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;

  return data.books.map(({ title, author }) => (
    <div key={title}>
      <p>
        {title}: {author}
      </p>
    </div>
  ));
}

const App = () => (
  <ApolloProvider client={client}>
    <div>
      <h2>My first Apollo app</h2>
      <FetchBooks />
    </div>
  </ApolloProvider>
);

render(<App />, document.getElementById("root"));

public/index.html作成

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <title>React App</title>
  </head>

  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>

クライアント起動

package.json編集・追記

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },

以下コマンド実行

$ npm run start

Compiled successfully!

You can now view graphql-client-example in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://10.138.142.229:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

その後、自動でブラウザが開き、以下の http://localhost:3000 の画面が表示される

f:id:kimai007:20200208165709p:plain

当然だが、GraphQL Serverが起動していない状態だと、エラーとなる

f:id:kimai007:20200208165956p:plain

  • consoleエラーはこんな感じ

f:id:kimai007:20200208170120p:plain