尝试使用GraphQL Mesh
本文是Ateam LifeDesign Advent Calendar 2022的第一日历的第四天的文章。
首先
GraphQL已成为一种在前端从取回数据的主要技术。本次介绍的是GraphQL Mesh,它不仅可以作为后端的GraphQL服务器,还可以使用GraphQL查询请求gRPC、REST API等,并将这些多个API整合为一个GraphQL服务器的技术。
使用GraphQL Mesh可以解决上述问题,并且可以轻松构建将多个服务绑定在一起的GraphQL网关。这样做的好处是不需要阅读和创建多个后端API的规范、架构和解析器等,从而节省了大量的工作量和维护难度。
试着使用
这次我们将使用Swagger Petstore作为REST API,使用SpaceX作为GraphQL API,然后试图启动一个将它们整合在一起的GraphQL服务器。
安装所需的软件包
为了使用REST API和GraphQL API,还需要安装OpenAPI和GraphQL的包。
$ yarn add graphql @graphql-mesh/cli @graphql-mesh/openapi @graphql-mesh/graphql
创建Mesh的配置文件
创建一个名为.meshrc.yaml的文件,并在其中描述每个API的配置。
sources:
- name: PetStore
handler:
openapi:
baseUrl: https://petstore3.swagger.io/api/v3
source: ./openapi.json
- name: Space
handler:
graphql:
endpoint: https://api.spacex.land/graphql
只需要按照以下方式在 REST API 中使用,将 handler 设为 openapi,并指定 baseUrl 和 API 文档的路径,Mesh 将会将 API 的 JSON 定义转换成 GraphQL 的模式。在 GraphQL API 中,只需要将 handler 设为 graphql 并设置端点即可完成基本配置。
这就是基本配置的全部内容!让我们立即启动 GraphQL 服务器来试试吧。
尝试启动由Mesh创建的GraphQL服务器。
完成.meshrc.yaml文件后,尝试启动GraphQL服务器。
$ yarn mesh dev
当您启动时,将显示以下日志。
? ?️ Mesh - Server Generating the unified schema...
(node:3356) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
? ?️ Mesh - PetStore Dereferencing the bundle
? ?️ Mesh - PetStore Creating the GraphQL Schema from dereferenced schema
Transformed schema is not set yet. Returning a dummy one.
? ?️ Mesh Generating index file in TypeScript
? ?️ Mesh - Server Serving GraphQL Mesh: http://0.0.0.0:4000
? ?️ Mesh Writing index.ts for ESM to the disk.
我认为它放出了蜘蛛网的表情符号,因为“mesh”意味着网眼,太棒了。
我想立即撰写查询,首先我们先看一下模式。
当您点击左上方类似书本的图标时,可以查看模式。
哦,確實可以看到由REST API(如findPetsByStatus和findPetsByTags)生成的模式和由GraphQL API(如capsules和capsulesPast)生成的模式結合在一起的新模式。更了不起的是,它還能讀取和反映REST API定義的描述。只需在先前提到的簡單設置上,就可以用GraphQL調用REST API,並且很容易地與另一個GraphQL API結合來創建服務器。
我将尝试执行这个查询。
我尝试同时调用REST API中的getPetById查询和GraphQL API中的capsules查询。
可以看到分别调用了每个API,并且正确地作为响应返回。太棒了。
尝试追加设置
您还可以在.meshrc.yaml中写入有关模式和查询等的详细选项。
这次我们将尝试设置查询的前缀和命名规则。
首先安装所需的包。
$ yarn add @graphql-mesh/transform-prefix @graphql-mesh/transform-naming-convention
然后,我们将在.meshrc.yaml文件中添加以下设置。
sources:
- name: PetStore
handler:
openapi:
baseUrl: https://petstore3.swagger.io/api/v3
source: ./openapi.json
+ transforms:
+ - prefix:
+ mode: wrap
+ includeRootOperations: true
+ value: pet_store_
+ - namingConvention:
+ typeNames: pascalCase
+ fieldNames: camelCase
+ fieldArgumentNames: camelCase
- name: Space
handler:
graphql:
endpoint: https://api.spacex.land/graphql
+ transforms:
+ - prefix:
+ mode: wrap
+ includeRootOperations: true
+ value: space_
+ - namingConvention:
+ typeNames: pascalCase
+ fieldNames: camelCase
+ fieldArgumentNames: camelCase
看起来设置的前缀和命名规则已经反映出来了。
似乎还可以进行其他各种设置。
以上是简单介绍GraphQL Mesh,可以轻松创建GraphQL集成模式。
有兴趣的人可以尝试一下。
多一個小禮物
介绍一种在从前端获取数据时可以使用的方便工具GraphQL Code Generator。使用它可以自动生成类型定义文件和包装自定义查询的useQuery。首先,安装所需的包。
$ yarn add @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
下一步,创建一个名为codegen.yml的文件,并按照以下方式填写内容。
schema:
- ".mesh/schema.graphql"
documents:
- "*.graphql"
generates:
graphql/generated/graphql.ts:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
在 `schema` 中,我们可以通过 `Mesh` 来指定生成的 GraphQL schema。`documents` 参数用于指定要创建的查询或片段的路径。`generaters` 参数用于指定生成文件的路径。
配置了 `typescript` 插件的话,它将根据 schema 生成类型。而 `typescript-operations` 插件则根据查询生成类型。如果设置了 `typescript-react-apollo`,它会从 `documents` 指定的 graphql 文件中加载查询,并帮助我们创建一个包装了 Apollo Client 的 `useQuery` 的自定义 hook。
我会试着创建一个查询。
query Test {
petStoreGetPetById(petId: 1) {
id
name
category {
name
}
}
spaceCapsules {
id
missions {
flight
name
}
}
}
创建查询后,运行graphql-codegen。
$ yarn graphql-codegen --config codegen.yml
当执行graphql-codegen时,将根据codegen.yml中的generate指定生成相应的文件。
通过查看生成的文件内容,可以确认为test查询生成了一个自定义的钩子函数。
.
.
.
/**
* __useTestQuery__
*
* To run a query within a React component, call `useTestQuery` and pass it any options that fit your needs.
* When your component renders, `useTestQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useTestQuery({
* variables: {
* },
* });
*/
export function useTestQuery(baseOptions?: Apollo.QueryHookOptions<TestQuery, TestQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<TestQuery, TestQueryVariables>(TestDocument, options);
}
export function useTestLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<TestQuery, TestQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<TestQuery, TestQueryVariables>(TestDocument, options);
}
export type TestQueryHookResult = ReturnType<typeof useTestQuery>;
export type TestLazyQueryHookResult = ReturnType<typeof useTestLazyQuery>;
export type TestQueryResult = Apollo.QueryResult<TestQuery, TestQueryVariables>;
如果您在组件中导入这个,您就可以进行数据获取,而无需每次导入 useQuery 或查询。
希望对未来的开发有所帮助。