使用Apollo Server搭建GraphQL的服務端和客戶端

ZHANGYU發表於2019-04-01

不懂的地方還是有很多,分享一下學習的心得,如果有錯誤,還望各位大佬斧正~

什麼是GraphQL

GraphQL,是Facebook開源的一種api查詢語言,對查詢資料提供了一套完整的描述,客戶端可以精準的獲取需要的資料,而沒有任何冗餘

graphql

最基礎的查詢方式如上圖,左邊是請求,右邊是響應,我希望獲取todoList這個集合,集合裡的每一個元素都包括_id,content,completed欄位,服務端返回的資料就是我請求需要的資料,不會多也不會少

GraphQL的基礎概念——Query

    type todo {
        _id: ID!
        content: String!
        completed: Boolean!
    }
複製程式碼
  • todo表示這是一個GraphQL的物件
  • _idcontentcompletedtodo中的欄位,IDStringBoolean都是graphql內建的型別
  • String!表示這個欄位的值為String型別且不可為空

接著建立一個查詢

    type Query {
        todoList: [todo]!
    }
複製程式碼
  • QueryMutetion都是GraphQL的關鍵字,一個代表查詢,一個代表變更,在這裡使用了Query建立了一個查詢
  • [todo]!表示欄位todoList的值是一個上面定義的todo型別的陣列,[todo]!表示這個欄位要麼是空陣列[],要麼是元素為todo的陣列[todo,todo,...]

GraphQL中的資料型別

  • Int: 有符號的32位整數
  • Float: 有符號的雙精度浮點值
  • String: UTF‐8的字串
  • Boolean: 布林
  • ID: 唯一的標識,在序列化為String時表示人類不可讀的

還可以自定義型別

搭建GraphQL伺服器

瞭解了查詢,就來建立一個GraphQL的伺服器吧 我使用的是Apollo GraphQL,這是一個非常完整的GraphQL的實現,包括了客戶端和服務端 node伺服器使用的是koa 現在就開始吧

首先建立一個專案,然後安裝以下依賴

npm i -S apollo-server-koa graphql koa

根目錄建立app.js檔案

const Koa = require("koa");
const { ApolloServer } = require("apollo-server-koa");

const { gql } = require("apollo-server-koa");

// 定義從伺服器獲取資料的graphql方法
const typeDefs = gql`
  type todo {
    _id: ID!
    content: String!
    completed: Boolean!
  }
  type Query {
    todoList: [todo]!
  }
`;

const server = new ApolloServer({
  // 使用gql標籤和字串定義的graphql的DocumentNode
  typeDefs,
  // 開啟mock
  mocks: true
});

const app = new Koa();

// applyMiddleware將graphql服務連線到koa框架
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`? Server ready at http://localhost:4000${server.graphqlPath}`)
);

複製程式碼

接著執行node app.js,在http://localhost:4000/graphql就能看見apollo server提供的playground

查詢

{
  todoList{
    _id
    content
    completed
  }
}
複製程式碼

在左邊輸入上方的查詢,右邊就會出現mock的資料了

新增resolvers

resolvers是用於解析typeDefs查詢的解析器,是一個鍵為type名,值為一個函式的對映 在app.js中新增resolvers

// ...
// 建立一個資料
const data = [
  {
    _id: "5ca16ed7c39e5a03d8ad3547",
    content: "html5",
    completed: false
  },
  {
    _id: "5ca16ee0c39e5a03d8ad3548",
    content: "javascript",
    completed: false
  },
  {
    _id: "5ca16ee5c39e5a03d8ad3549",
    content: "css",
    completed: false
  }
];
// resolvers
// Query對應查詢,todoList是一個函式,返回的是資料
// 可以寫非同步函式,用於真實的資料庫查詢
const resolvers = {
  Query: {
    todoList: () => data
  }
};
// 新增resolvers,取消掉mocks
const server = new ApolloServer({
  typeDefs,
  resolvers,
});

const app = new Koa();
//...
複製程式碼

再次查詢,返回的結果就是data的資料了

GraphQL的基礎概念——Mutation

Mutation可以對應REST API中的CRUD,一個簡單的mutation如下 在typeDefs中增加

    type updateResponse {
        success: Boolean!
        todoList:[todo]!
    }
    type Mutation {
        addTodo(content: String): updateResponse!
    }
複製程式碼

這是一個Mutation的操作,增加一個todo項,返回一個updateResponse物件

  • addTodo(content: String)接收一個為String型別的引數
  • updateResponse值包括一個鍵名為success值為Boolean和一個鍵名為todoList值為todo的陣列

在playground中執行

修改resolvers

const resolvers = {
    Query: {
        todoList: () => data
    },
    Mutation: {
        addTodo: (_, { content }) => {
            console.log(content);
            data.push({
                _id:Math.random().toString(36).substring(3),
                content,
                completed:false
            });
            return { success: true, todoList:data };
        },
    }
};
複製程式碼

函式中具體的引數可查閱Resolver type signature

執行

mutation{
  addTodo(content:"css"){
    success
    todoList{
      _id
      content
      completed
    }
  }
}
複製程式碼

mutation表示這是一個mutation操作,操作名為addTodo,接收一個名為content型別為String的引數,返回的資料是successtodoList

在nodejs的控制檯能看見console出來的引數

在客戶端中使用GraphQL

官方提供了包括reactreact-nativevueaugularnative-ios...等 在creact-react-app中使用

雖然官方提供了元件模式的QueryMutation元件,不過我在學習過程中,用的還是直接以JS寫的方法模式,Client api參考

create-react-app的專案中安裝依賴

npm install apollo-boost react-apollo graphql --save

建立client.js,並在package.json中增加proxy

import ApolloClient from "apollo-boost";
const Client = new ApolloClient();
const getList = async () => {
    return await Client.query({
        query: gql`
            {
                todoList {
                    _id
                    content
                    completed
                }
            }
        `
    });
};
const add = async content => {
    return await Client.mutate({
		// 引數,content對應的下面的$content
        variables: { content },
        mutation: gql`
            mutation add($content: String!) {
                addTodo(content: $content) {
                    success
                    todoList{
                        _id
                        content
                        completed
                    }
                }
            }
        `
    })
};
export {getList,add};
複製程式碼

提供IDE支援

我使用的是webstorm是一款整合功能非常強大的IDE,在plugins裡搜尋安裝JS GraphQL

匯出schema.json

  • npm install -g apollo-codegen
  • 客戶端根目錄執行 apollo-codegen introspect-schema http://localhost:4000/graphql --output graphql.schema.json

webstrome就會提供非常智慧的graphql程式碼格式化和補全功能了

Demo

學習過程中寫了2個demo,資料庫使用的mongodb,以前也沒用過,也是現學的,好多都不懂……

客戶端

服務端

不懂的地方依舊很多,文件是英文的又特別複雜,路漫漫其修遠兮~

公司肯定不會用graphql的,rest api都成問題,唉……

相關文章