我尝试使用GraphQL实现了一个鸡尾酒搜索服务
首先
你好。我平常使用 React 来实现前端。最近对 GraphQL 充满了兴趣,因为了解了除了 REST 之外的选择,使得技术选型更加广泛。我尝试使用 GraphQL 来实现了一些服务,最后我在下面列举了实际运行的成果。希望我的感想能够帮助你更加深入理解 GraphQL。
示例和代码
示例:https://liquor-react.netlify.com/
客户端源代码:https://github.com/yoneda/liquor-react-client
服务器源代码:https://github.com/yoneda/liquor-graphql-server
-
- 2019年12月15日 追記
GraphQL サーバーのデプロイ先をGlitch からheroku に移行して表示速度を改善しました。
整个组织的结构
在寻找可用的免费数据时,我发现了一个名为RapidAPI的服务。在那里我找到了可以搜索酒和鸡尾酒的Cocktail DB API,所以这次我选择使用了它。客户端使用了React,服务器使用了GraphQL进行实现。GraphQL不仅可以连接数据库,还可以连接其他的REST API或者其他的GraphQL。通常我们会将GraphQL连接到数据库,但这次我连接了REST形式的RapidAPI。GraphQL可被视为BFF(后端适用的前端)的角色。图形化如下所示。
运用技术
这次使用的技术如下:
客户端:react、apollo-client、react-scripts、reach-router
服务器:express、express-apollo-server、superagent、nodemon
服务器端
我們使用 Express + ApolloServer 來實現伺服器端。在 ApolloServer 中,我們定義了結構並實現了相應的解析程序。我們根據 RapidAPI 返回的 JSON 定義了結構。查詢返回雞尾酒列表的操作如下所示。
enum DrinkCategory{
COCKTAIL
COFFEE
BEER
OTHER
}
type Query{
allDrinks(category: DrinkCategory): [Drink!]!
}
type Drink{
id: ID!
name: String!
url: String!
category: DrinkCategory
}
客户
客户端使用React + ApolloClient进行实现。在React中发出GraphQL查询非常简单。只需要在组件根部设置GraphQL的URI,并使用useQuery Hooks来获取数据,仅需这两个步骤就可以连接到服务器。
我的实施感受
Apollo Client的高效缓存功能非常方便
Apollo Client会将来自服务器的获取结果缓存在本地。当从组件A获取blog文章后,如果从组件B尝试获取相同的文章,Apollo Client会直接访问缓存中的数据,并且不需要再次向服务器发送请求,所以显示速度很快。以前,这种实现是由Redux完成的(为A和B组件准备可以访问的Redux值。将获取的博客文章结果存放在Redux中,当B组件尝试获取时,从Redux中访问值)。使用Apollo Client,这个缓存功能是一开始就准备好的,无需自己编写大量代码。
减少验证的工作量
在用Node.js实现服务器端的时候,如果想要进行验证,就需要额外添加中间件。这里所说的验证是指检查请求的参数值的类型,以及检查该值是否为必需等过程。使用GraphQL可以确保客户端和服务器之间的类型,这使开发人员感到安心。
GraphQL使不需要太多请求次数。
RESTとGraphQLの特徴を比較すると、どちらがデータを効率的に取得できるかというと、私はGraphQLの方が優れていると考えています。特に、あるデータとその関連するデータを取得するような場面では、GraphQLが優れているようです。例えば、ブログ記事とその記事に対するコメントを取得するAPIを実装する場合を考えてみましょう。
GET /articles/:id
GET /articles/:id/comments
在REST中,自然地实现是发送两次请求,就像上面所示。(当然,也可以实现同时获取博客文章和其评论的方式。但是,如果按照REST的设计原则,将GET / POST / PUT / DELETE分配给一个资源,我认为上述设计更自然。)
query{
article(id: $id){
title
body
postedComments{
comment
user
}
}
}
GraphQL允许在一次请求中获取所需的字段,并且可以只获取所需的字段,而不会获取额外的无用字段,这样非常高效。我觉得GraphQL的设计能够高效地获取数据。
下次(计划)
因为这一次只是查询,所以下一次我想实现变更和用户认证。一旦实现了,我会在这篇文章中进行更新,或者发布一篇新文章!