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 方案大功告成。

相关文章
相关标签/搜索