GraphQL 項目中的前端 mock 方案

在使用 GraphQL (如下簡稱 gql)的前端項目中,每每須要等待後臺同窗定義好 Schema 並架設好 Playground 之後才能進行聯調。若是後臺同窗阻塞了,前端只能被動等待。若是對於 gql 項目來講也可以和 REST 同樣有一套 mock 方案就行了。通過一系列實踐,我選擇了 mocker-apiApollo 的方案來實現。javascript

mocker-api

mocker-api 是一個基於 node 實現的接口 mock 工具(前身是webpack-api-mocker,依賴於 webpack-dev-server,如今可獨立運行)。因爲咱們的項目大都和 webpack 結合,因此這裏僅簡單介紹其與 webpack 結合的用法。前端

在 webpack 的 devServer 配置項中,引入如下內容:java

devServer: {
  before (app) {
    require('mocker-api')(app, resolve('./mock/index.js'))
  }
}
複製代碼

這樣便完成了 webpack 和 mocker-api 的結合。接下來咱們要到 /mock/index.js 裏面寫邏輯:node

// /mock/index.js

module.exports = {
  'POST /api': (req, res) => {
    return res.send('Hello world')
  }
}
複製代碼

此時開啓 webpack-dev-server,在頁面中使用 POST 方式請求 /api,便可獲得內容爲 Hello world 的響應。webpack

Apollo

Apollo 是一套完整的 GraphQL 實現方案,支持多種語言的服務端和客戶端,在這裏咱們主要使用 apollo-server 來搭建前端的 gql mock 服務。ios

/mock 目錄下新建 /gql 目錄,再往裏面分別創建 /resolvers 目錄,types 目錄和 index.js 入口文件。下面咱們以一個」查詢書籍信息「的例子來說述這個 gql mock 服務是怎麼作的。git

/types 目錄下新建 Books.jsgithub

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

module.exports = gql` """ 書籍 """ type Book { id: ID! "標題" title: String "做者" author: String } type Query { books: [Book] } type Mutation { addBook(title: String, author: String): [Book] } `
複製代碼

接下來,在 /resolvers 目錄底下新建 Books.jsweb

const books = [
  {
    id: parseInt(Math.random() * 10000),
    title: 'Harry Potter and the Chamber of Secrets',
    author: 'J.K. Rowling'
  },
  {
    id: parseInt(Math.random() * 10000),
    title: 'Jurassic Park',
    author: 'Michael Crichton'
  }
]

module.exports = {
  query: {
    books: () => books,
  },
  mutation: {
    addBook: (root, book) => {
      book.id = parseInt(Math.random() * 10000)
      books.push(book)
      return books
    }
  }
}
複製代碼

最後在入口文件 index.js 裏分別引入上面兩個文件:json

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

const typeDefs = [
  require('./types/Books')
]

const resolvers = {
  Query: {
    ...require('./resolvers/Books').query
  },
  Mutation: {
    ...require('./resolvers/Books').mutation
  }
}

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

server.listen().then(({ url }) => {
  console.log(`🚀 Apollo server ready at ${url}`);
})
複製代碼

運行 node ./mock/gql/index.js,便可在 localhost:4000 打開 Playground 進行調試了。

image

使用 mocker-api 把請求轉發到本地的 Playground

在實際的業務中,gql 接口每每被封裝成形如 /api/gql 的形式,和其餘的 rest 接口一塊兒供客戶端調用。爲了讓 /api/gql 接口可以被轉發到 localhost:4000 的 Playground,咱們能夠利用 mocker-api 進行轉發。

改寫 /mock/index.js,爲其增長一個 /api/gql 的地址:

const axios = require('axios')

module.exports = {
  'POST /api': (req, res) => {
    return res.send('Hello world')
  },
  'POST /api/gql': async (req, res) => {
    const reqBody = req.body
    const { data: result } = await axios({
      url: 'http://localhost:4000',
      method: 'POST',
      data: reqBody
    }).catch(e => e)
    return res.send({
      data: result.data
    })
  }
}
複製代碼

這裏我使用了 axios 往 apollo-server 發起請求。

此時在 webpack-dev-server 所啓動的頁面中往 /api/gql 發起一個 gql 請求,便可驗證接口:

fetch('/api/gql', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ query: 'query GetBooks { books { title }}' })
      })
        .then(res => res.json())
        .then(result => console.log(result))
複製代碼

image

因爲 mocker-api 支持 hot reload,因此當咱們何時再也不須要 mock 數據時,直接在 /mock/index.js 中把 'POST /api/gql' 這一段註釋掉便可,無需重啓 dev server。

至此,GraphQL 項目中的前端 mock 方案大功告成。

相關文章
相關標籤/搜索