使用无服务器架构的GraphQL,从AWS AppSync的模式进行codegen

从AWS AppSync生成的Schema中生成代码。

首先

我感受到了最近前端开发的稳定性日益增强,尤其是GraphQL生态系统,它旨在一举解决REST所面临的问题,给予了前所未有的开发体验。其中包括GraphQL和TypeScript在内的技术的发展,都为前端开发的稳健性做出了贡献。

虽然GraphQL非常方便,但AWS的AppSync可以通过无服务器方式为您提供它。目前,还没有很多能够以无服务器方式提供GraphQL的框架,所以这非常好。

因此,在本文中,我們將使用由AppSync生成的API輸出模式來生成前端代碼。

环境

項目バージョンnode16.13.2aws-cli2.4.15cdk2.10.0

实施概要

同步应用

这次我们只想纯粹地使用API,所以不使用Amplify,只创建AppSync。同时,不使用IaC等技术,直接在控制台上操作。

阿波罗客户端 React Hooks

通过模式信息,在GraphQL管理库Apollo Client中生成React Hooks。测试是否可以正常运作,包括类型补全等。

实施

AppSync 应用同步

image.png
image.png
image.png
Screen Shot 2022-02-03 at 21.29.38.png

阿波罗客户端的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
image.png

可以看出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;
image.png
image.png
image.png

看起来运行得很顺利。

最后

在AppSync上使用GraphQL,可以受益于其强大的生态系统。由于在无服务器环境下的选择还很有限,我认为GraphQL仍然是一个有效的选择,希望今后能积极采用。此外,对于AppSync本身的管理,有许多选项,如Serverless Framework、Amplify和CDK等。个人而言,Amplify具有强大的GUI等功能,但由于需要极度锁定,我还有些犹豫。我也希望在这方面积累更多经验。

广告
将在 10 秒后关闭
bannerAds