Skip to content
导航

Apollo graphQL

Apollo 提供了一套完整的 graphQL 实现方案,它以MIT协议开源了 Node.js 服务端、多种客户端 SDK(JavaScript/React、Kotlin、iOS)。Apollo 团队也销售 graphQL 云服务。

client

npm社区有 facebook 维护的开源库 graphql 作为 JavaScript 参考实现,它的作用是根据输入的Schema、用户代码,输出符合graphQL 格式的查询代码。

Apollo 团队在 graphql 的基础上开发出 graphql-tag 库简化使用,提供一个模板标签函数gql根据用户代码输出符合graph QL 格式的查询代码,同时支持书写Schema,但不验证,以减小JS大小,毕竟在生产环境中Schema是由服务端确定校验的。

从npm下载量来看, graphql-taggraphql 提供了超过一半的下载量。

客户端使用Apollo分为两步:

  1. 初始化 ApolloClient 实例client,配置uri、cache
  2. 使用client.query()发起 graphQL 请求

本文客户端代码以Apollo官方文档 JavaScript React 为例。

Apollo为简化React使用,提供ApolloProvider组件在全局上下文挂载client,提供useQuery实现 React Hooks。

Demo源码

jsx
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
    uri: 'http://localhost:3000/apollo',
    cache: new InMemoryCache(),
})

export function(){
  return (
    <ApolloProvider client={client}>
      <App/>
    </ApolloProvider>
  )
}
jsx
// App.jsx
import { useQuery, gql } from '@apollo/client'

const gqlBooks = gql`
  query {
    books {
      title
    }
  }
`

function DisplayBooks() {
  const { loading, error, data } = useQuery(gqlBooks)

  if (loading) return <p>Loading...</p>
  if (error) return <p>Error : {error.message}</p>

  return data.books.map((item: { title: string }, index: number) => (
    <p key={index}>{item.title}</p>
  ))
}

export default function() {
  return (
    <DisplayBooks />
  )
}

server

在 Node.js 服务端,Apollo 实现为一个独立的 ApolloServer ,并提供express服务器中间件 expressMiddleware 、基于express服务器封装的一个独立服务器 startStandaloneServer 简化使用。

三者的区别是:

  • startStandaloneServer 用于快速实现一个graphQL HTTP服务器
  • expressMiddleware 用于接入 express 实现的HTTP服务器
  • ApolloServer 用于自定义接入 Node.js 实现的HTTP服务器

采用 expressMiddleware 开发的 Demo 源码

服务端代码结构如下

js
import http from 'http';
import express from "express";
import cors from 'cors';
import bodyParser from 'body-parser';
import { ApolloServer } from '@apollo/server'
import { expressMiddleware } from '@apollo/server/express4';

const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
  typeDefs, // graphQL类型定义,如Schema
  resolvers, // graphQL类型定义的解析器
})
await server.start()

app.use(
  '/apollo',
  cors(),
  bodyParser.json(),
  // expressMiddleware accepts the same arguments:
  // an Apollo Server instance and optional configuration options
  expressMiddleware(server, {
    context: async ({ req }) => ({ token: req.headers.token }),
  }),
);

app.listen(port)

参考文档