GraphQL在前端项目中的使用

215 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

简介

官网定义 A query language for your api

背景

在后端微服务化的环境中,很多时候一个页面的数据,需要多个微服务的聚合才能得到,后端同学为了保持单一性通常会在多个restful接口中返回数据. restful API 存在以下问题:

  1. 接口数量众多,难以维护(往往一个组件,页面所需要的QUERY数据,需要调用几个api才能完成)

  2. 接口扩展成本高 增加字段 只会越来越臃肿

  3. 虽然有 API文档作为联调契约,但经常存在某种原因,后端需要修改参数和返回值,导致每一次的修改,前后端都会联动修改

  4. 后端经常作为微服务,不止一个消费方,有充分的理由拒绝 为本次的场景修改接口 虽然有controller作为中间处理环节,但后端可能不认

场景

场景一:

接口数量众多,难以维护

image.png

  1. /commercial 与/base /detail/${commercial} 三个接口共同构成了 客户详情页的数据源 但是里面有很多冗余以及重复数据,浪费带宽
  2. 前端在拆分组件的时候,往往根据页面布局接口来拆,可是接口的数据往往并非如此,一个组件的字段可能由多个接口的字段东平西凑出来的,那么接口调用的时机 可能就会发生变化 同时传递给组件的data就像这样
<CommercialInfo {...data1} {...data2} {...data3} />
<BaseInfo data={compose(data1,data2,data3)} />

鉴于以上问题,优化方案大致如下:

  1. 合并接口,去除冗余字段,由于部分接口不止一个消费方,该条不行

  2. 往往通过把公共状态往上提 来保证数据传递的统一性 这样的话,在页面mount的时候 就要同时请求至少三个接口,使用状态管理工具 也会面临同样的问题 这样的话会给代码增加一些心智负担 而且根本问题还是没有解决

graphql出现

基本概念

  1. Schema 用来描述当前操作的结构模型

  2. Query 获取数据,比如查找

  3. Mutation 对数据作变更 例如 post put delete

  4. resolver 对schema做解析的处理函数

简单的例子 helloworld

  Query: {
    hello: () => "Hello world!",
  },
  // 返回
  {
  "data": {
    "hello": "Hello World"
  }
}

复杂一点的例子

// 创建user
mutation createUser ($id: ID!, $name: String!, $email: String!, $age: Int,$gender:Gender) {
  createUser(id: $id, name: $name, email: $email, age: $age,gender:$gender) {
    id
    name
    age
    email
    gender
  }
}

// 更新user
mutation UpdateUser ($id: ID!, $name: String!, $email: String!, $age: Int) {
  updateUser(id: $id, name: $name, email: $email, age: $age) {
    id
    name
    age
  }
}


// 监听

subscription subsUser($id: ID!) {
  subsUser(id: $id) {
    id
    name
    age
    email
  }
}

使用graphql后 前后端的变化

  1. 后端不再产出restful api接口 将Controller层转换成了resolver
  2. 前端端联调不再依赖单个接口文档 共同约定一套Schema结构 前端根据Schema来定制自己的请求

困难

  • graphql 对前端来说可以说是大大提高开发效率, 落地的话需要后端的全力配合
  • 对 field 来说 每一条都会对数据库跑一query 对数据库有一定的性能影响 需要对数据库作优化