はじめに
この記事はGithub Pagesで公開したReact × TypeSCriptアプリで、GraphQL(AppSync)を使えるようにする手順をまとめたものです。あくまで手段のまとめなので、知識がどうこう、というのは薄めです。
- GraphQLがなんとなくわかる(スキーマ等)
- react、TypeScriptをなんとなくでも使ったことがある。
といったレベルだとスムーズに読み進められるかな~と思います。
目次
0. 環境
1. 事前準備
2. AppSyncでGraphQLサーバーを作成する。
3. Apollo Client & GraphQL
3-1. Apollo Client
3-2. GraphQL
4. 環境変数の利用
4-1. Github Secrets
4-2. ワークフローファイルの作成(yaml)
0. 環境
Node
% node -v
v16.15.0
npm
% npm -v
8.5.5
1. 事前準備
Githubにてpublicでリポジトリを作成しておいてください。
ローカルで新規reactプロジェクトを作成します。今回はTypeScriptで開発するので、--template typescriptオブションをつけます。
% npx create-react-app "アプリ名" --template typescript
今作ったプロジェクトに移動し、gitのremoteの設定を行います。
% cd アプリ名
% git init
% git remote add origin "GithubのSSH"
なお、remoteが追加できているかどうかは、
% git remote -v
origin git@github.com:Githubの名前/リポジトリ名.git (fetch)
origin git@github.com:Githubの名前/リポジトリ名.git (push)
となっていれば成功です。
2. AppSyncでGraphQLサーバーを作成する。
これに関しては分かりやすい記事がすでに投稿されているのでそちらを参照していただけると幸いです。
こちら、今回は認証モードをAPIキーで構築しています。設定から変更、確認変更できます。また、
- API KEY
- API URL
の二つは後で使用するので、メモしておくとスムーズです。
機密情報なのでGithubにこれらの値を直接公開することの無いように注意しましょう。
3. Apollo Client & GraphQL
3-1. ApolloClient
次に、src/index.tsxにApollo Clientを使用するためのコードを書いていきます。
まず、@apollo/clientをインストールします。
% npm install @apollo/client graphql --save
次にsrc/index.tsxを以下のように書き換えます。
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './Pages/App';
import { ApolloClient, InMemoryCache, ApolloProvider, HttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
//GraphQL APIのエンドポイント用の変数
const endPoint = process.env.REACT_APP_GRAPHQL_ENDPOINT;
//APIキー認証用の変数
const apiKey = process.env.REACT_APP_API_KEY;
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
'x-api-key': apiKey,
}
};
});
// Apollo Clientのインスタンスを作成
const client = new ApolloClient({
cache: new InMemoryCache(),
link: authLink.concat(
new HttpLink({
uri: endPoint,
})
)
});
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
Apollo Clientを初期化し、ApolloProviderでラップします。
3-2. GraphQL
ついでにGraphQLも書いてしまいましょう。
src/Appに以下を追記します。
import React, { useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
import { gql, useQuery } from '@apollo/client';
function App() {
//バッククォートです
const GET_DATA = gql`
query ListEvents {
listEvents {
items {
id
name
where
description
}
}
}
`;
const { data, loading } = useQuery(GET_DATA);
useEffect(() => {
if (data) {
console.log(data);
}
}, [loading]);
return (
//省略
)
今回はAppSyncのイベントアプリを元にしているため、スキーマは上記の通りです。別環境でやっている場合はスキーマを都度変えてください。
Apollo Client、GraphQLを包括的にまとめていらっしゃる記事がありましたので、ぜひご覧ください。
4. 環境変数の利用
4-1. Github Secrets
一旦ソースコードから離れて、Githubに戻ります。
リポジトリの Setting -> Secrets and variables -> Actionから、環境変数の設定ページに飛びます。
右上の new repository secret から、環境変数を追加します。
- REACT_APP_API_KEY -> API KEY
- REACT_APP_GRAPHQL_ENDPOINT -> API URL
- MY_TOKEN -> Githubのトークン *1
を書き込みます。
*1: Githubのトークンは、ユーザーのsettings -> Developer settings -> Personal access tokens -> Tokensのgenerate new tokenで生成できます。
※注意 REACT_APP_○○ という名前で無いとReactが環境変数を認識してくれません。
4-2. ワークフローファイルの作成(yaml)
次に設定した環境変数をReactで読み込めるようにしていきます。
この為、Github Actionを利用し、build & deploy時に環境変数を取得できるようにする為のワークフローファイルを作成します。
ルートディレクトリに.github/workflows/main.ymlを作成します。
% mkdir -p .github/workflows
% cd .github/workflows
% touch main.yml
作成したyamlファイルに以下を記述します。
name: Build and Deploy
on:
push:
branches:
- master
env:
REACT_APP_API_KEY: ${{ secrets.REACT_APP_API_KEY }}
REACT_APP_GRAPHQL_ENDPOINT: ${{ secrets.REACT_APP_GRAPHQL_ENDPOINT }}
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build
run: |
npm ci
npm run build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.MY_TOKEN }}
publish_dir: './build'
この時、ルートディレクトリにbuildディレクトリを作成しておきます。
デフォルトでは./buildがgitIignoreに設定されているので、コメントアウトしておきます。
yamlファイルではありませんがpackage.jsonに
"homepage": "https://ユーザー名.github.io/リポジトリ名/"
を追加しておきましょう。
ここまで出来たらpushします。
(gitignoreの./buildは戻しておきます。)
終わりに
ここまでの流れで、gh-pageブランチが自動生成され、github pageが更新されているかと思います。正しくクエリ出来ていれば、開発者ツールのコンソール欄にデータが表示されているはずなので確認してみてください。
素人故に誤りがあるかもしれませんが、指摘いただけると幸いです。
Q & A
Q: github pageが真っ白です。
A : package.jsonにhomepageプロパティは追加しましたか? また、ルートディレクトリにbuildディレクトリは追加しましたか?
Q : pushしたら次のエラーが出てbuildが失敗したんだけど...
src/App.tsx
Line 25:6: React Hook useEffect has a missing dependency: 'data'. Either include it or remove the dependency array react-hooks/exhaustive-deps
A : このエラーは"useEffect"に渡された依存関係配列に、必要なデータである"data"が含まれていないことによります。が、これだとデータが描画されるたびに呼ばれてしまうので、今回は↓
useEffect(() => {
if (data) {
console.log(data);
}
// 以下のコメントによってEsLintのエラーを無視します、
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [loading]);
で対応しました。(別プロジェクトではこんなエラー出なかったんだけどなぁ...)