AWS AppSyncに生成したSchemaからcodegenする
はじめに
GraphQLやTypeScriptなど最近のフロントエンド開発は堅牢性を日々増していっているのを感じます。とくにRESTが抱えていた問題を一挙に解決する目的でつくられたGraphQLのエコシステムはこれまでにない開発体験を与えてくれます。
そんな便利なGraphQLですがAWSのAppSyncでは、それをサーバーレスで提供してくれます。サーバーレスでGraphQLを提供できるようなフレームワークはまだ多くないのでとてもいいですね。
ということでこの記事ではAppSyncで作ったAPIから出力されたスキーマを用いてフロントエンドで利用するコードを生成しようと思います。
環境
項目 | バージョン |
---|---|
node | 16.13.2 |
aws-cli | 2.4.15 |
cdk | 2.10.0 |
実装概要
AppSync
今回は純粋なAPIとしてのみ利用したいのでAmplifyを利用せず、AppSyncのみを作成します。
またIaCなどは利用せず、コンソール画面上からポチポチやっていきます。
Apollo Client React Hooks
スキーマ情報からGraphQL管理ライブラリであるApollo ClientのReact Hooksを生成します。
型補完などが動作するかも確認します。
実装
AppSync
画面でポチポチつくっていきます。
中身はなんでもいいのでイベントアプリというサンプルプロジェクトで開始します。
フロントのコード生成で利用するので設定 > API Details
でAPI URL、API ID、API KEYをコピーしておきます。
Apollo Client React Hooks
craを利用してReactのテンプレートを作成します。
npx create-react-app apollo-codegen --template typescript
cd apollo-codegen
npm install graphql @apollo/client @graphql-codegen/cli @graphql-codegen/introspection @graphql-codegen/typescript @graphql-codegen/typescript-react-apollo @graphql-codegen/typescript-operations dotenv
コード生成用のプログラムを記述します。
下記のファイルでは、src/graphql
フォルダ下に記述したxxxx.gql
を読み込み、その型情報やhooksをsrc/generated/graphql.tsx
に出力するようになっています。
module.exports = {
schema: [
{
[process.env.REACT_APP_GRAPHQL_API_URL]: {
headers: { "X-API-KEY": process.env.REACT_APP_GRAPHQL_API_KEY },
},
},
],
documents: ["./src/graphql/**.gql"],
overwrite: true,
generates: {
"./src/generated/graphql.tsx": {
plugins: [
"typescript",
"typescript-operations",
"typescript-react-apollo",
],
config: {
skipTypename: false,
withHooks: true,
withHOC: false,
withComponent: false,
},
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
};
REACT_APP_GRAPHQL_API_URL
とREACT_APP_GRAPHQL_API_KEY
は.env
に記述します。
AppSyncの設定画面からコピーします。(REACT_APP_
とついているのは後のReactのプログラムでも流用するためです。)
REACT_APP_GRAPHQL_API_URL=https://xxxxxxxxxx.appsync-api.ap-northeast-1.amazonaws.com/graphql
REACT_APP_GRAPHQL_API_KEY=xxxxxxxxxx
package.jsonのscriptsにqqlcodegen
コマンドを追加します。
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"gqlcodegen": "graphql-codegen --require dotenv/config --config .graphql.codegen.js"
},
最後にサンプルとして以下のGraphQLファイルを追加します。
query ListEvents {
listEvents {
items {
id
name
description
when
where
}
}
}
コード生成
以下のコマンドでコードを生成してみます。
npm run gqlcodegen
> apollo-codegen@0.1.0 gqlcodegen
> graphql-codegen --require dotenv/config --config .graphql.codegen.js
✔ Parse configuration
✔ Parse configuration
✔ Generate outputs
src/generated/graphql.tsx
を確認します。
hooksやその型情報が生成されていることがわかります。
動作確認
ApolloProviderを記述して
import React from "react";
import {
ApolloClient,
ApolloProvider as BaseApolloProvider,
InMemoryCache,
} from "@apollo/client";
const client = new ApolloClient({
uri: process.env.REACT_APP_GRAPHQL_API_URL!,
// API_KEYをフロントで使うのは基本的にNGだがテスト的に使う
headers: { "X-API-KEY": process.env.REACT_APP_GRAPHQL_API_KEY! },
cache: new InMemoryCache(),
});
const ApolloProvider: React.FC = ({ children }) => {
return <BaseApolloProvider client={client}>{children}</BaseApolloProvider>;
};
export default ApolloProvider;
index.tsxで呼び出して
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import ApolloProvider from "./ApolloProvider";
ReactDOM.render(
<React.StrictMode>
<ApolloProvider>
<App />
</ApolloProvider>
</React.StrictMode>,
document.getElementById("root")
);
App.tsxでlistEventを呼び出してみます。
import React from "react";
import "./App.css";
import { useListEventsQuery } from "./generated/graphql";
function App() {
const { data } = useListEventsQuery();
return (
<div className="App">
<ol>
{data?.listEvents?.items?.map((item) => {
return (
<li key={item?.id}>
{item?.name} 場所:{item?.where} 日時:{item?.when}
</li>
);
})}
</ol>
</div>
);
}
export default App;
いい感じに動作してそうです。
最後に
AppSyncでもGraphQLの強力なエコシステムの恩恵を受けることができそうです。GraphQLは今後も積極的に採用していきたいですが、まだまだサーバーレスでの選択肢は多くないので有効な選択肢になると思います。
またAppSync自体の管理ですがServerless FrameworkやAmplify、CDKなどさまざまあります。個人的にはAmplifyはGUIなどもあり、かなり強力ですが、猛烈にロックインする必要があるので少し躊躇するところでもあります。このあたりも知見をためていきたいです。