使用无服务器架构的GraphQL,从AWS AppSync的模式进行codegen
从AWS AppSync生成的Schema中生成代码。
首先
我感受到了最近前端开发的稳定性日益增强,尤其是GraphQL生态系统,它旨在一举解决REST所面临的问题,给予了前所未有的开发体验。其中包括GraphQL和TypeScript在内的技术的发展,都为前端开发的稳健性做出了贡献。
虽然GraphQL非常方便,但AWS的AppSync可以通过无服务器方式为您提供它。目前,还没有很多能够以无服务器方式提供GraphQL的框架,所以这非常好。
因此,在本文中,我們將使用由AppSync生成的API輸出模式來生成前端代碼。
环境
实施概要
同步应用
这次我们只想纯粹地使用API,所以不使用Amplify,只创建AppSync。同时,不使用IaC等技术,直接在控制台上操作。
阿波罗客户端 React Hooks
通过模式信息,在GraphQL管理库Apollo Client中生成React Hooks。测试是否可以正常运作,包括类型补全等。
实施
AppSync 应用同步
阿波罗客户端的React Hooks
我将使用CRA来创建React的模板。
在中文中,CRA是Create React App的缩写,代表创建React应用的工具。上述句子的意思是使用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
可以看出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等功能,但由于需要极度锁定,我还有些犹豫。我也希望在这方面积累更多经验。