GraphQL apollo

Apollo GraphQL 快速上手

Ryan 2020/12/02 23:18:45
1025

Graphql vs RestAPI

 

在訊息取得和資料交換上,rest api 已經是業界的標準,透過其規格,我們可以快速輕易的取得對應的資訊。

而相較於成熟的rest api,GraphQL 則是仍在持續發展中的技術。

但從本質上來說,GraphQL的重點是針對性能和靈活性進行優化,這些彈性及優化也許能為很適切的符合某些情境

 

1、強型別語言

可以明確的定義資料型態,型別錯誤會直接被阻擋,也可以方便的自動產出文件--程式即文檔

2、減少資訊短缺或資訊過度獲取(Over Fetching / Under Fetching)的情況

類似SQL語言的方式,使用者可以精確的自定查詢調件、及回傳內容

3、相容性問題

不論是前端使用,和rest api混搭開發,或透過系統架構方式(如micro service架構),統一資料交換接口,都可以讓開發更有彈性

 

在整合應用上,Apollo Community 已經提供相當的工具及解決方案,

這邊介紹 apollo-server 應用,做為快速進入GraphQL開發世界的範例

 

開始使用

安裝上前我們要先確認nodejs已安裝完成,npm可正常使用,然後可以簡單的5個步驟來完成體驗

1、建立測試目錄

mkdir apolloDemo

2、npm 初使化

cd apolloDemo

npm init --yes

3、安裝apollo-server 及 graphql

npm install apollo-server graphql

4、建立index.js

vim index.js

內容設定如下,我們先依官網提供之範例建立:

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`

  type Book {

    title: String

    author: String

  }

  type Query {

    books: [Book]

  }

`;

const books = [

  {

    title: 'The Awakening',

    author: 'Kate Chopin',

  },

  {

    title: 'City of Glass',

    author: 'Paul Auster',

  },

];

const resolvers = {

  Query: {

    books: () => books,

  },

};

 

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {

  console.log(`Server ready at ${url}`);

});

5、啟動服務

node index.js

服務default設定,啟動在4000 port。

現在我們就可以連進去網頁看看精美的apollo介面了。

 

介面操作

左方是我們輸入參數的地方,這邊我們使用 query 的語法,將books 下的 title 及 author一次全部取回來

按下向右三角型圖式,我們就可以看到取回的結果。

 

當然,graqhql彈性空間就是我們可依不同的query 要求,我們可以取回想要的欄位置

 

現在我們在回頭來看一下index.js設定的內容

1、typeDefs下,我們定義了欄位的內容(Book)及查詢的條件(Query),

     GraphQL 有定義五種型別的純量型態:Int、String、Float、Boolean、ID

2、範例上設定了靜態的資料來源(books),包含兩本書的書名及作法

3、最後設定一組解析器(resolver),預設無指定查詢回傳條件

以上就完成了一個最簡單的graphQL apollo 設定及查詢

 

加入查詢條件

既然是有彈性的查詢語言,我們就應該能更有效率的使用"查詢"及"條件"

盡量發揮其 Query Language 的特性,首先我們來改寫設定:

我們定義一組新資料結構:

 type User {

    id: ID!

    name: String

  }

 type Query {

    user(id: ID!): User,

    users:[User]

  }

User下包含兩個欄位,id:唯一鍵值(ID!);name:字串(String)

Query 包含了使用者id查詢user(id: ID!): User及 查詢使用者列表users:[User]

 

user 寫入4筆資料:

const users = [

  {

    id: '1',

    name: 'Ryan',

    gender: 'M'

  },

  {

    id: '2',

    name: 'Annisa',

    gender: 'F'

  },

  {

    id: '3',

    name: 'James',

    gender: 'M'

  },

  {

    id: '4',

    name: 'Maggie',

    gender: 'F'

  }

];

最後,解析器定義查詢回傳的條件,符合query動作時,我們對應的解析回傳內容

const resolvers = {

  Query: {

    user(parent, args, context, info) {

      return users.find(user => user.id === args.id);

    },

    users: () =>users

  }

}

 

再次重新啟動服務node index.js

首先我們更新query為 users{id name}

已經可以看到資料結構的更新,

然後試著下下新的query語法查詢條件[id查詢],user(id:"1"){id name}

就完成透過id查詢特定對像了。

 

應用範例

現在 Apollo GraphQL已經建好了,那我們該如何透過程式來呼叫GraphQL資料呢?

目前,GraphQL支援的程式語言範圍已經相當完整了。

我們可以使用javascript的fetch功能來做一個簡單的呼叫範例

<script>

const query = 'query{users{id,name}}';

const url = "http://localhost:4000/";

const opts = {

  method: "POST",

  headers: { "Content-Type": "application/json" },

  body: JSON.stringify({ query })

};

fetch(url, opts)

  .then(res => res.json())

  .then(console.log)

  .catch(console.error);

</script>

 

就可以快速得到以下的結果

 

參考資料:

https://graphql.org/blog/

https://moonhighway.com/fetching-data-from-a-graphql-api

Ryan