如何详细解析React中GraphQL应用的长尾关键词疑问?

2026-04-02 07:211阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2687个文字,预计阅读时间需要11分钟。

如何详细解析React中GraphQL应用的长尾关键词疑问?

目录- 什么是GraphQL- GraphQL出现的意义- 传输API存在的主要问题- GraphQL如何解决这些问题- GraphQL基本语法- 标准类型- 对象类型- 枚举类型- GraphQL内置指令- 什么是Apollo- apollo-server- 处理流程

1.解析阶段

目录
  • 什么是 GraphQL
    • GraphQL出现的意义
      • 传统API存在的主要问题:
      • GraphQL 如何解决问题
    • GraphQL基本语法
      • 标量类型
      • 对象类型
      • 枚举类型
      • GraphQL 内置指令
  • 什么是 Apollo
    • apollo-server
      • 处理流程
        • 1.解析阶段
        • 2.校验阶段
        • 3.执行阶段
      • Schema
        • 给server端带来的便利性
          • 创建client
          • 将client注入到react
          • 数据请求
          • 数据缓存
      • apollo-client
        • 总结
          • GraphQL 的优缺点
            • 优点
            • 缺点

        什么是 GraphQL

        GraphQL由Facebook发起,其手机客户端自2012年起,就全面采用了GraphQL查询语言, 2015年, Facebook全面开源了第一份GraphQL规范。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,是一种规范,使得客户端能够准确地获得它需要的数据,而且没有任何冗余.

        GraphQL出现的意义

        传统API存在的主要问题:

        • 接口数量众多维护成本高:接口的数量通常由业务场景的数量决定,为了尽量减少接口数量,服务端工程师通常会对业务做抽象,首先构建粒度较小的数据接口,再根据业务场景对数据接口进行组合,对外暴露业务接口,即便这样,服务端对前端暴露的接口数量还是非常多,因为业务总是多变的。
        • 接口扩展成本高:出于带宽的考虑移动端我们要求接口返回尽量少的字段,PC 端通常要展现更多字段;考虑首屏性能,我们又要求对接口做合并;传统 API 应对这些需求,前后端都面临改造,成本较高。
        • 接口响应的数据格式无法预知:由于接口文档几乎总是不能及时更新,前端工程师无法预知接口响应的数据格式,影响前端开发进度。

        GraphQL 如何解决问题

        请求参数在发送到服务端之前会先经过 GraphQL Client 转换成客户端 Schema,这段 Schema 其实是一段 query 开头的字符串,描述了客户端的对数据的述求:调用哪个方法,传递什么样的参数,返回哪些字段。服务端拿到这段 Schema 之后,通过事先定义好的服务端 Schema 接收请求参数并执行对应的 resolve 函数提供数据服务。

        GraphQL基本语法

        参考 [GraphQL][1] 官网文档

        标量类型

        GraphQL 自带一组默认标量类型: Int:有符号 32 位整数。 Float:有符号双精度浮点值。 String:UTF‐8 字符序列。 Boolean:true 或者 false。 ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化。

        对象类型

        一个 GraphQL schema 中的最基本的组件是对象类型,它就表示你可以从服务上获取到什么类型的对象,以及这个对象有什么字段

        type Character { name: String! list: [Episode!]! }

        myField: [String!] myField: null myField: [] myField: ['a', 'b'] myField: ['a', null, 'b'] myField: [String]! myField: null myField: [] myField: ['a', 'b'] myField: ['a', null, 'b']

        GraphQL 对象类型上的每一个字段都可能有零个或者多个参数,

        type Starship { id: ID! name: String! length(unit: LengthUnit = METER): Float }

        枚举类型

        enum Episode { NEWHOPE EMPIRE JEDI }

        这表示无论我们在 schema 的哪处使用了 Episode,都可以肯定它返回的是 NEWHOPE、EMPIRE 和 JEDI 之一。

        对象类型、标量以及枚举是 GraphQL 中你唯一可以定义的类型种类。但是当你在 schema 的其他部分使用这些类型时,或者在你的查询变量声明处使用时,你可以给它们应用额外的类型修饰符来影响这些值的验证。

        type Character { name: String! list: [Episode]! }

        GraphQL 内置指令

        GraphQL 中内置了两款逻辑指令,指令跟在字段名后使用。

        @include 当条件成立时,查询此字段

        query { search { actors @include(if: $queryActor) { name } } }

        @skip 当条件成立时,不查询此字段

        query { search { comments @skip(if: $noComments) { from } } }

        • 操作类型:指定本请求体要对数据做什么操作,类似与 REST 中的 GET POST。GraphQL 中基本操作类型有 query 表示查询,mutation 表示对数据进行操作,例如增删改操作,subscription 订阅操作。
        • 操作名称:操作名称是个可选的参数,操作名称对整个请求并不产生影响,只是赋予请求体一个名字,可以作为调试的依据。
        • 变量定义:在 GraphQL 中,声明一个变量使用符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的movie就可以改写成movie(name:符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的 movie 就可以改写成 movie(name: 符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的movie就可以改写成movie(name:name)。

        query Hero($episode: Int!, $withFriends: Boolean!) { hero(episode: $episode) { name friends @include(if: $withFriends) { name } } }

        什么是 Apollo

        Meteor 团队有着很丰富的数据流控制经验,他们发现了 Relay 的不便之处,引领业界通过使用他们开发的 Apollo 享受到更简洁的接口,Apollo 是基于GraphQL的全栈解决方案集合。包括了 apollo-client 和 apollo-server ;从后端到前端提供了对应的 lib ,使开发使用 GraphQL 更加的方便。

        apollo-server

        apollo-server是一个在nodejs上构建grqphql服务端的web中间件。支持express,koa 等框架。 参考 [apollo-server][2] 官网文档

        处理流程

        主要是通过官方graphql-js库进行处理

        1.解析阶段

        为了识别客户端 Schema, graphql-js 定义了一系列的特征标识符:

        export const TokenKind = Object.freeze({ BANG: '!', DOLLAR: '$', PAREN_L: '(', PAREN_R: ')', SPREAD: '...', COLON: ':', EQUALS: '=', BRACKET_L: '[', BRACKET_R: ']', ... });

        并定义了 AST 语法树规范,规定语法树支持以下节点:

        export const Kind = Object.freeze({ // Name NAME: 'Name', // Document DOCUMENT: 'Document', OPERATION_DEFINITION: 'OperationDefinition', VARIABLE_DEFINITION: 'VariableDefinition', VARIABLE: 'Variable', // Values INT: 'IntValue', FLOAT: 'FloatValue', STRING: 'StringValue', BOOLEAN: 'BooleanValue', ... });

        有了特征字符串与 AST 语法树规范,GraphQL Server 对客户端 Schema 进行逐字符扫描,如果客户端 Schema 不符合服务端定义的 AST 规范,解析过程会直接抛出语法异常。

        如何详细解析React中GraphQL应用的长尾关键词疑问?

        2.校验阶段

        校验阶段用于验证客户端 Schema 是否按照服务端 Schema 定义好的方式获取数据,比如:获取数据的方法名是否有误,必填项是否有值等等,校验范围一共有几十种,不一一举例。

        { "errors":[ { "message":"Cannot query field "getU" on type "Query". Did you mean "getUser"?", "locations":[ { "line":3, "column":9 } ] } ] }

        不仅返回结构化的报错信息,还非常人性化的告诉你正确的调用方式是什么。校验阶段通过之后会进入执行阶段.

        3.执行阶段

        执行阶段依赖的输入为:解析阶段的产出物 document ,服务端 Schema;其中 document 准确描述了客户端对数据的述求:请求哪个方法,参数是什么,需要哪些字段;服务端 Schema 描述了提供数据的方式。执行服务端 Schema 中的 resolve 函数,得到执行阶段的输出。每个类型的每个字段都由一个 resolver 函数支持,该函数由 GraphQL 服务器开发人员提供。

        Schema

        Schema可以说是GraphQL最具核心的部分,其描述了整个接口向外暴露的形式;像Restful API,我们会定义一个查询所有人的接口url定义为:/api/v1/user/getUsers,而查询人具体信息的接口url为:/api/v1/user/getUserById,前端人员调用起来很直观。但是graphql是完全不一样的使用方式,其向前端暴露的url就一个像/api/graphql之类的,那这么多接口怎么区分呢?

        一个graphql接口都有一个Schema定义,其定义三种操作方式:query(查询),mutation(变更)和subscription(监听)。再往下延伸,一个查询中包含多个field,也就是多种不同的查询,比如query user查询人,query message查询消息,query weather查询天气,通过这些就实现了Restful API使用多个url来达到不同操作的效果。

        给server端带来的便利性

        由于 GraphQL 通过客户端 Schema 而不是通过 URL 描述数据述求,所以理论上服务端只需要对客户端暴露一个地址即可, 解决了接口数量众多维护成本高的问题; 同时,服务端提供的是全量字段,客户端可按需获取,面对接口扩展的需求,服务端没有开发成本;

        import express from 'express'; import { graphiqlExpress, graphqlExpress } from 'apollo-server-express'; const app = express(); app.use('/graphql', graphqlExpress({ schema, })); app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));

        apollo-client

        参考 [apollo-client][3] 官网文档

        创建client

        import ApolloClient from "apollo-boost"; const client = new ApolloClient({ uri: "48p1r2roz4.sse.codesandbox.io" });

        在我们将Apollo Client连接到React之前,让我们先尝试发送查询。记住首先导入gql用于将查询字符串解析为查询文档。

        import gql from "graphql-tag"; ... client.query({ query: gql` { rates(currency: "USD") { currency } } ` }) .then(result => console.log(result));

        将client注入到react

        react-apollo提供ApolloProvider组件,ApolloProvider类似于redux的provider。它会把apollo客户端放入到React app的上下文里,以便在组件树的任何地方都是可以获取到apollo客户端。

        import React from "react"; import { render } from "react-dom"; import { ApolloProvider } from "react-apollo"; const App = () => ( <ApolloProvider client={client}> <div> <h3>My first Apollo app

        本文共计2687个文字,预计阅读时间需要11分钟。

        如何详细解析React中GraphQL应用的长尾关键词疑问?

        目录- 什么是GraphQL- GraphQL出现的意义- 传输API存在的主要问题- GraphQL如何解决这些问题- GraphQL基本语法- 标准类型- 对象类型- 枚举类型- GraphQL内置指令- 什么是Apollo- apollo-server- 处理流程

        1.解析阶段

        目录
        • 什么是 GraphQL
          • GraphQL出现的意义
            • 传统API存在的主要问题:
            • GraphQL 如何解决问题
          • GraphQL基本语法
            • 标量类型
            • 对象类型
            • 枚举类型
            • GraphQL 内置指令
        • 什么是 Apollo
          • apollo-server
            • 处理流程
              • 1.解析阶段
              • 2.校验阶段
              • 3.执行阶段
            • Schema
              • 给server端带来的便利性
                • 创建client
                • 将client注入到react
                • 数据请求
                • 数据缓存
            • apollo-client
              • 总结
                • GraphQL 的优缺点
                  • 优点
                  • 缺点

              什么是 GraphQL

              GraphQL由Facebook发起,其手机客户端自2012年起,就全面采用了GraphQL查询语言, 2015年, Facebook全面开源了第一份GraphQL规范。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,是一种规范,使得客户端能够准确地获得它需要的数据,而且没有任何冗余.

              GraphQL出现的意义

              传统API存在的主要问题:

              • 接口数量众多维护成本高:接口的数量通常由业务场景的数量决定,为了尽量减少接口数量,服务端工程师通常会对业务做抽象,首先构建粒度较小的数据接口,再根据业务场景对数据接口进行组合,对外暴露业务接口,即便这样,服务端对前端暴露的接口数量还是非常多,因为业务总是多变的。
              • 接口扩展成本高:出于带宽的考虑移动端我们要求接口返回尽量少的字段,PC 端通常要展现更多字段;考虑首屏性能,我们又要求对接口做合并;传统 API 应对这些需求,前后端都面临改造,成本较高。
              • 接口响应的数据格式无法预知:由于接口文档几乎总是不能及时更新,前端工程师无法预知接口响应的数据格式,影响前端开发进度。

              GraphQL 如何解决问题

              请求参数在发送到服务端之前会先经过 GraphQL Client 转换成客户端 Schema,这段 Schema 其实是一段 query 开头的字符串,描述了客户端的对数据的述求:调用哪个方法,传递什么样的参数,返回哪些字段。服务端拿到这段 Schema 之后,通过事先定义好的服务端 Schema 接收请求参数并执行对应的 resolve 函数提供数据服务。

              GraphQL基本语法

              参考 [GraphQL][1] 官网文档

              标量类型

              GraphQL 自带一组默认标量类型: Int:有符号 32 位整数。 Float:有符号双精度浮点值。 String:UTF‐8 字符序列。 Boolean:true 或者 false。 ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化。

              对象类型

              一个 GraphQL schema 中的最基本的组件是对象类型,它就表示你可以从服务上获取到什么类型的对象,以及这个对象有什么字段

              type Character { name: String! list: [Episode!]! }

              myField: [String!] myField: null myField: [] myField: ['a', 'b'] myField: ['a', null, 'b'] myField: [String]! myField: null myField: [] myField: ['a', 'b'] myField: ['a', null, 'b']

              GraphQL 对象类型上的每一个字段都可能有零个或者多个参数,

              type Starship { id: ID! name: String! length(unit: LengthUnit = METER): Float }

              枚举类型

              enum Episode { NEWHOPE EMPIRE JEDI }

              这表示无论我们在 schema 的哪处使用了 Episode,都可以肯定它返回的是 NEWHOPE、EMPIRE 和 JEDI 之一。

              对象类型、标量以及枚举是 GraphQL 中你唯一可以定义的类型种类。但是当你在 schema 的其他部分使用这些类型时,或者在你的查询变量声明处使用时,你可以给它们应用额外的类型修饰符来影响这些值的验证。

              type Character { name: String! list: [Episode]! }

              GraphQL 内置指令

              GraphQL 中内置了两款逻辑指令,指令跟在字段名后使用。

              @include 当条件成立时,查询此字段

              query { search { actors @include(if: $queryActor) { name } } }

              @skip 当条件成立时,不查询此字段

              query { search { comments @skip(if: $noComments) { from } } }

              • 操作类型:指定本请求体要对数据做什么操作,类似与 REST 中的 GET POST。GraphQL 中基本操作类型有 query 表示查询,mutation 表示对数据进行操作,例如增删改操作,subscription 订阅操作。
              • 操作名称:操作名称是个可选的参数,操作名称对整个请求并不产生影响,只是赋予请求体一个名字,可以作为调试的依据。
              • 变量定义:在 GraphQL 中,声明一个变量使用符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的movie就可以改写成movie(name:符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的 movie 就可以改写成 movie(name: 符号开头,冒号后面紧跟着变量的传入类型。如果要使用变量,直接引用即可,例如上面的movie就可以改写成movie(name:name)。

              query Hero($episode: Int!, $withFriends: Boolean!) { hero(episode: $episode) { name friends @include(if: $withFriends) { name } } }

              什么是 Apollo

              Meteor 团队有着很丰富的数据流控制经验,他们发现了 Relay 的不便之处,引领业界通过使用他们开发的 Apollo 享受到更简洁的接口,Apollo 是基于GraphQL的全栈解决方案集合。包括了 apollo-client 和 apollo-server ;从后端到前端提供了对应的 lib ,使开发使用 GraphQL 更加的方便。

              apollo-server

              apollo-server是一个在nodejs上构建grqphql服务端的web中间件。支持express,koa 等框架。 参考 [apollo-server][2] 官网文档

              处理流程

              主要是通过官方graphql-js库进行处理

              1.解析阶段

              为了识别客户端 Schema, graphql-js 定义了一系列的特征标识符:

              export const TokenKind = Object.freeze({ BANG: '!', DOLLAR: '$', PAREN_L: '(', PAREN_R: ')', SPREAD: '...', COLON: ':', EQUALS: '=', BRACKET_L: '[', BRACKET_R: ']', ... });

              并定义了 AST 语法树规范,规定语法树支持以下节点:

              export const Kind = Object.freeze({ // Name NAME: 'Name', // Document DOCUMENT: 'Document', OPERATION_DEFINITION: 'OperationDefinition', VARIABLE_DEFINITION: 'VariableDefinition', VARIABLE: 'Variable', // Values INT: 'IntValue', FLOAT: 'FloatValue', STRING: 'StringValue', BOOLEAN: 'BooleanValue', ... });

              有了特征字符串与 AST 语法树规范,GraphQL Server 对客户端 Schema 进行逐字符扫描,如果客户端 Schema 不符合服务端定义的 AST 规范,解析过程会直接抛出语法异常。

              如何详细解析React中GraphQL应用的长尾关键词疑问?

              2.校验阶段

              校验阶段用于验证客户端 Schema 是否按照服务端 Schema 定义好的方式获取数据,比如:获取数据的方法名是否有误,必填项是否有值等等,校验范围一共有几十种,不一一举例。

              { "errors":[ { "message":"Cannot query field "getU" on type "Query". Did you mean "getUser"?", "locations":[ { "line":3, "column":9 } ] } ] }

              不仅返回结构化的报错信息,还非常人性化的告诉你正确的调用方式是什么。校验阶段通过之后会进入执行阶段.

              3.执行阶段

              执行阶段依赖的输入为:解析阶段的产出物 document ,服务端 Schema;其中 document 准确描述了客户端对数据的述求:请求哪个方法,参数是什么,需要哪些字段;服务端 Schema 描述了提供数据的方式。执行服务端 Schema 中的 resolve 函数,得到执行阶段的输出。每个类型的每个字段都由一个 resolver 函数支持,该函数由 GraphQL 服务器开发人员提供。

              Schema

              Schema可以说是GraphQL最具核心的部分,其描述了整个接口向外暴露的形式;像Restful API,我们会定义一个查询所有人的接口url定义为:/api/v1/user/getUsers,而查询人具体信息的接口url为:/api/v1/user/getUserById,前端人员调用起来很直观。但是graphql是完全不一样的使用方式,其向前端暴露的url就一个像/api/graphql之类的,那这么多接口怎么区分呢?

              一个graphql接口都有一个Schema定义,其定义三种操作方式:query(查询),mutation(变更)和subscription(监听)。再往下延伸,一个查询中包含多个field,也就是多种不同的查询,比如query user查询人,query message查询消息,query weather查询天气,通过这些就实现了Restful API使用多个url来达到不同操作的效果。

              给server端带来的便利性

              由于 GraphQL 通过客户端 Schema 而不是通过 URL 描述数据述求,所以理论上服务端只需要对客户端暴露一个地址即可, 解决了接口数量众多维护成本高的问题; 同时,服务端提供的是全量字段,客户端可按需获取,面对接口扩展的需求,服务端没有开发成本;

              import express from 'express'; import { graphiqlExpress, graphqlExpress } from 'apollo-server-express'; const app = express(); app.use('/graphql', graphqlExpress({ schema, })); app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));

              apollo-client

              参考 [apollo-client][3] 官网文档

              创建client

              import ApolloClient from "apollo-boost"; const client = new ApolloClient({ uri: "48p1r2roz4.sse.codesandbox.io" });

              在我们将Apollo Client连接到React之前,让我们先尝试发送查询。记住首先导入gql用于将查询字符串解析为查询文档。

              import gql from "graphql-tag"; ... client.query({ query: gql` { rates(currency: "USD") { currency } } ` }) .then(result => console.log(result));

              将client注入到react

              react-apollo提供ApolloProvider组件,ApolloProvider类似于redux的provider。它会把apollo客户端放入到React app的上下文里,以便在组件树的任何地方都是可以获取到apollo客户端。

              import React from "react"; import { render } from "react-dom"; import { ApolloProvider } from "react-apollo"; const App = () => ( <ApolloProvider client={client}> <div> <h3>My first Apollo app