前言

社区里已有很多有关 GraphQL 入门和原理的文章,GraphQL 和 Apollo Client 的官方网站也有较为详细的介绍。相对于 RESTful API(简称 REST),社区也从各个方面分析了 GraphQL 的优劣利弊。本文主要是从前端角度出发,在如今前后端开发分离盛行的前提下,分享一些我们如何利用社区中热门的工具提高开发效率和工程质量的经验,希望对已经决心入坑 GraphQL 的朋友们有一些帮助。

GraphQL Playground

第一次接触 GraphQL 的时候一定会从官方文档里了解到 GraphQL Server 所提供的 Playground。
Playground 是一个完整的浏览器端 GraphQL IDE, 包括 Documentation, Schema 和一个可以编写和测试 GraphQL 请求的编辑器。

对于使用 GraphQL 的开发团队, Playground 基本可以代替如 Swagger 之类的的 API 文档和如 Postman 之类的的请求模拟工具。是一个较完备的开发手册,并且优点是零成本使用, 并且有团队在维护和迭代。GraphQL 社区绝大多数对于GraphQL Server的实现都会内置 Playground。

Apollo Client Devtool

Apollo Client Devtool 是 Apollo Client 提供的一款 Chrome 插件,可以在浏览器的 Console 中捕捉页面发送的 Query 和 Mutation,并且提供了编辑,修改和重试这些请求,还有最重要的查看 GraphQL Client 缓存的功能。
因为所有的 GraphQL 都是发送给统一的路径,Query Body 也是以字符串的形式发送,使得请求的可读性很差, Apollo Client Devtool 相较于通过传统 Network 的方式做了优化。
以上两个工具可以说是入门必备,类似我们前后端对接 Restful Api 时我们会用到的工具。GraphQL 依赖 Schema 提供了更多的提效工具。

GrahpQL VS Code Plugin

Visual Studio Code(简称 VS Code) Plugin GraphQL 提供了相当齐全的功能,包括语法检查,语法高亮,引用跳转,Schema 悬浮提示,Autocomplete 等。是一个必装的插件。
很重要的一个功能是,当我们在定义 Schema 的时候对每一个参数所定义的描述(有的实现是通过代码注释的方式插入 Schema )是可以通过这个插件的提示在 IDE 里展示的,也就是原本前后两端都需要的注释内容,包括对接口的描述,对接口参数的描述等, 现在可以只用在 Schema 里定义一遍就可以了。

该 Plugin 还提供了一个可以在 IDE 内执行 Query 和 Mutation 的功能。

但是个人认为实用性有限,对于不含参数的 Query 查询可以直接执行,对于需要传入参数的 Query 和 Mutation 需要在 VS Code 的弹窗中输入参数,如果是较为简单的字符串或者数字参数比较方便,但是如果是较为复杂的结构体就需要输入 Stringfy 过后的 JSON 格式,并且很多情况下链式请求的参数依赖上一个请求,发送请求所需的参数就更不容易手动获取了。

以上工具可以帮助我们更方便的查询和编写 Query, 但只有这些功能还是远远不够的,我们需要借助工具将 Schema 融入前端工程化的过程,提效的同时提高代码的健壮性。

GraphQL ESLint

GraphQL ESLint 最基础的前端代码检查就是 ESLint,我们有了统一的 Schema 之后, 就可以通过 Schema 生成的对应的规则来对 Query 进行类似Playground 中 Syntax 检查。

GraphQL Code Generator

GraphQL Code-Generator 最能提高前端代码健壮性的方法无疑是 TypeScript , 但是根据 Schema 手写项目全套的类型文件会有很大的工作量, GraphQL Code Generator 是一个根据 Schema 生成各类语言类型文件的 cli 工具, 工具本身是通过 Preset 和 Plugin 的方式来实现针对不同语言和功能的需求,官方本身也提供了很丰富的 Preset 和 Plugin 可以满足大部分的开发需求,自定义 Plugin 也有较为详细的文档和示例。这里我们只讨论 Typescript 和相关的 Plugin。

最核心的一点是通过 Code Generator 生成的 Type 文件是包含 Schema 描述的。所以我们在使用 GraphQL 返回的数据时,Typescript 是会提示数据类型的描述的。如下图,关于 Event 对象中 Description 字段的描述 “Maximum 50 characters” 是后端在定义 Schema 时写的注释,通过这个生成的类型文件,成为了前端 Typescript 类型文件中的注释,可以被 IDE 完美引用。等于说后端同学在写代码注释时,也在帮前端同学写代码注释。

下面就是我们该如何使用这些类型文件的问题,以在 VS Code Typescript 插件的帮助下我们在使用 UseQuery Hook 时,定义好 UseQuery 的伪类 就可以在使用返回数据时拥有完整的数据类型提醒,Autocomplete 和定义 Schema 时对字段的具体描述。这种方式在开发体验和效率上相比传统在项目和文档间来回切换提高了很多,也同时增强了代码的健壮性。
但是这种方式也存在一个问题,就是细心的朋友可能发现我们在定义Query的时候只请求了 Events 对象的 Name 属性,但是自动提示却提示了 Events 包含的所有可能字段,并不能完全满足我们的要求。

我们看一下 UseQuery 方法的类型定义:

useQuery: TData = any, TVariables = OperationVariables: (query: DocumentNode | TypedDocumentNode<TData, TVariables>, options?: QueryHookOptions<TData, TVariables>): QueryResult<TData, TVariables>;

接受两个伪类 TData 和 TVaraibles,我们需要在使用 Hooks 的时候传入这两个参数,如果要根据 Query 来自定义返回值,我们需要在第一个参数传入被Pick 或 Exclude 包装过后的类型,如果 Query 或 Mutation 有传入参数也需要从根路径的 Type。TS 去引用 Input 的类型,非常麻烦。

 {events: Pick<Event, 'name'>[]}
query GetEvents{
  events {
    id
    name
  }
}

Code-Generator 针对这个问题也有相应的方案,通过 Typescript-Operations 这个 Plugin 生成的文件生成的类型文件会自动排除缺省的字段。

export type GetEventsQueryVariables = SchemaTypes.Exact<{ [key: string]: never; }>;

// With Pick 
export type GetEventsQuery = { events?: SchemaTypes.Maybe<Array<SchemaTypes.Maybe<Pick<SchemaTypes.Event, 'id' | 'name'>>>> };

// Without Pick
export type GetEventsQuery = { events?: SchemaTypes.Maybe<Array<SchemaTypes.Maybe<{ id: string, name?: SchemaTypes.Maybe<string> }>>> };

对于使用 React + Apollo Client 的项目,typescript-react-apollo plugin 不仅可以生成类型,还可以可以生成和 Query 相对应的请求的 hook 包括封装好的UseQuery, UseLazyQuery 等,可以在保证代码类型完整的前提下极大的提高开发效率。

Code Generator 的插件很多,配置项也很多,自定义 Plugin 也比较容易,可以根据根据项目需要,配置出适合项目适合团队的工程化方案。

GraphQL Introspection

以上提到的所有工具都是依靠 GraphQL 标准中提供的 Introspection 接口实现的,该接口的能力其实也很简单明了,就是规定了对于 GraphQL 请求的根部永远是 __schema 节点,可以通过这个节点来查询整个 Schema 的内容。社区里的绝大部分工具也都是通过这个接口的能力开发。
Introspection, 感兴趣的朋友也可以参考 GraphQL 的官方文档去开发适合自己的工具。

GraphQL Config

最后要提的是 GraphQL Config, 一份配置文件支持所有和 GraphQL 相关的工具。该配置文件支持多种文件类型,例如 Json、Yaml、 Yml、 JS、TS 等等,社区里大部分工具都已支持 GraphQL Config 配置文件,GraphQL 官方也建议开发者使用 GraphQL Config 来作为配置文件。如果开发自己的工具也可以使用 GraphQL Config 作为配置文件。我们在使用和分享 GraphQL 生态中的这些工具时,只依赖一份配置文件是非常方便的。

schema: './schema/*.GraphQL'
extensions:
  codegen:
    generates:
      ./src/types.ts:
        plugins:
          - typescript
          - typescript-resolvers

总结

GraphQL 给予了前端工程在请求数据方面更好的灵活性,更为健全的类型定义,同时也为使用 Typescript 带来了更多的工作量。但是在社区的支持下,合理的运用工具可以在保证前端项目类型安全的前提下,极大的提高工程效率和工程质量,也从侧面解决了一些老生常谈的文档问题和注释问题。

参考目录

Apollo Grpahql (https://www.apollographql.com...
Graphql-playground (https://github.com/GraphQL/Gr...
Apollo Client Devtools (https://chrome.google.com/web...
GraphQL VS Code Plugin (GraphQL - Visual Studio Marketplace)
Graphql-eslint (dotansimha/graphql-eslint)
Graphql-code-generator (https://www.graphql-code-gene...
Graphql Orgnization (https://graphql.org/)
Graphql Config (https://graphql-config.com/)


作者:周兆庭 / 前端开发工程师

招聘信息

GrowingIO技术团队是一个活力四射、对技术充满激情的团队,多个岗位持续招聘中!诚招前端工程师/大数据工程师/Java工程师等
,欢迎有兴趣的同学投递简历至:jianli@growingio.com(邮件标题请注明具体岗位名称)
,更多职位及信息可进入招聘官网查看


关于 GrowingIO

GrowingIO 是国内领先的一站式数据增长引擎整体方案服务商,创立于2015年,以数据智能分析能力为核心,通过构建客户数据平台,打造增长营销闭环,帮助企业提升数据驱动能力,赋能商业决策、实现业务增长。


GrowingIO
57 声望10 粉丝

GrowingIO(官网网站www.growingio.com)的官方技术专栏,内容涵盖微服务架构,前端技术,数据可视化,DevOps,大数据方面的经验分享。