dcloud官方暂时没有关于如何支持GraphQL的说明,不过uni-app配置GraphQL还是挺简单的,但不熟悉uni-app和GraphQL的童鞋配置起来还是会比较迷茫,到处是坑。。。
其实早已经有热心的童鞋提拱支持uni-app的GraphQL client,我看了一下他github上的源码,发现是移植自国外一位GraphQL大神的库,而且该库相关说明和用例比较缺乏,说白了就是生态支持不好,遇到问题很难找到解决方法,而且该童鞋也不维护了,很多时候还得自己看源码慢慢调试摸索,我用来开发了一个项目,涉及上传功能的时候弄到我想哭。。。
使用Axios请求GraphQL API
提到GraphQL client,了解GraphQL的童鞋可能第一反应想到的就是Apollo,其实如果你无需用到Apollo生态及其功能特性,即不必使用此类框架,你可以使用任何你想要的库。
GraphQL本身并不关心网络层,所以你完全可以使用普通的HTTP方法带上具有GraphQL查询和修改的结构内容对其进行操作。
有时候引入框架意味着对现有架构进行大量修改,以至于很多人不敢在老项目中使用或直接放弃GraphQL,对大多数前端开发者来说,可能所有http请求仅用Axios就能搞定是最理想的状态。。。
所以我们可以用Axios这样请求GraphQL API:
import axios from 'axios'
axios.post(graphqlURL, {
query: `
query albums {
albums(limit: ${this.limit) {
title
content
images
}
}
`}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
graphql-tag and print
graphql-tag用来把string转化成 GraphQL的AST。既然在客户端发请求时仍然使用string,为什么需要客户端转成AST呢?这有几个原因:
- 编译成 AST 可以在编译时检查确保 query 的合法性 (比如查询了不存在的字段)
- 可以按照特定条件对多个 query 进行合并,多个请求合并为同一个请求
- 可以按照客户端缓存对某些字段进行过滤 (skip),避免冗余查询
- ... 诸多好处
在服务器端也有诸多好处,如:
- 解析出来客户端请求的 field,与数据库一对比,按需请求数据库字段
- 添加新的 directives
- ...
而print的作用是:Converts an AST into a string, using one set of reasonable formatting rules
import axios from 'axios'
import gql from 'graphql-tag'
import { print } from 'graphql'
const LOGIN = gql`mutation login($identifier:String!, $password:String!){
login(input:{
identifier: $identifier
password: $password
}){
jwt
user {
username
}
}
}`
axios.post(graphqlURL, {
query: print(LOGIN),
variables: {
identifier: this.email,
password: this.password
}
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
让uni-app支持请求GraphQL API
好吧,说了那么多该进主题了,下面我们开始配置uni-app。
uni-app里直接使用Axios在App端和小程序端会报错,得自己定义适配,可参考
在uniapp设计的APP中引入axios,支持cookie(真机亲测可行)
我在这里就不折腾了,直接在uni-app插件市场下载仿Axios的库luch-request
// 如果你的项目还没有package.json文件
// npm init -y
// 安装
npm install graphql graphql-tag
// main.js
import Request from '@/utils/luch-request/index.js'
import gql from 'graphql-tag'
import { print } from 'graphql'
Vue.prototype.$http = new Request()
Vue.prototype.$gql = gql
Vue.prototype.$print = print
我们来测试一下请求是否能成功
const LOGIN = this.$gql`mutation login($identifier:String!, $password:String!){
login(input:{
identifier: $identifier
password: $password
}){
jwt
user {
username
}
}
}`
this.$http.post(graphqlURL, {
query: this.$print(LOGIN),
variables: {
identifier: this.email,
password: this.password
}
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
发现graphql报错
Uncaught ReferenceError: require is not defined
at eval (parser.mjs?2604:1)
at Module.../../../../project/uni-app-graphql/node_modules/graphql/language/parser.mjs (chunk-vendors.js:34)
at __webpack_require__ (index.js:787)
at fn (index.js:150)
at eval (index.js?f743:1)
at Object.../../../../project/uni-app-graphql/node_modules/graphql-tag/src/index.js (chunk-vendors.js:10)
at __webpack_require__ (index.js:787)
at fn (index.js:150)
at eval (main.js?3d9e:4)
at Object.../../../../project/uni-app-graphql/main.js (index.js:985)
不熟悉webpack和vue.config.js配置的估计到这里够呛。。。
google一下说是要让webpack支持mjs后缀,在vue.config.js中尝试了webpack的配置方法还是不行,后来才发现vue有自己的一套vue config命令。。。
根目录新建vue.config.js文件并添加以下代码
module.exports = {
chainWebpack: (config) => {
// GraphQL Loader
config.module // optional
.rule('graphql')
.test(/\.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end()
config.module
.rule('mjs')
.test(/\.mjs$/)
.include.add(/node_modules/)
.end()
.type('javascript/auto')
.end()
config.resolve.extensions
.add('.mjs')
.add('.gql')
.add('.graphql')
.end()
}
}
好了,现在你可以愉快地使用Axios一边请求GraphQL API,一边请求RESTful API。。。
enjoy life
参考:
https://github.com/Pines-Cheng/blog/issues/79
https://github.com/vuejs/vue-cli/issues/1637