GraphQL 官方解释为:一种用于 API 的查询语言前端
(文章不断完善中...我是写一点更新下)node
前面有写过一篇文章《Next.js服务端渲染框架实战》中有提到会把数据请求与后端交互的方式从restful API方式切换成GraphQL方式。这篇文章将会尝试用GraphQL的方式与后端进行数据交互,先立个Flag,写个本地demo,实现基本的CURD(数据的增删改查)操做,欢迎你们一块儿交流讨论。程序员
从入门作前端以来,前台的数据展现由最初的混合开发模式,后端模板渲染静态页面,同时后端将从数据查询到的数据变量嵌入模板,实现了前端的数据展现。后来演变到先后端分离了,前端经过异步请求,restful API的方式请求后台接口拿到数据而后渲染到页面。页面的一些增删改查操做也是经过API接口的方式跟后端作交互。那问题就来了,平常开发的时候并不能保证提早定下的API接口字段百分百的准确,这就涉及到后续较大可能性要修改接口字段了。还有更奇葩的后端提供的接口是这样的。抛出一个接口,包含的数据层级特别深,你问他我要的字段在哪,回答是反正你要的字段在里面,本身找去。。。后台仁兄提早乐呵呵的下班了,你加班找来找去,顿时心中一万个XXX.固然若是后来越来樾规范,就不存在这种恶心的接口了。但接口字段变更是不太可能消除的,那有没有什么方法能够本身修改字段名称,修改数据结构,拿到本身想要的数据?哈哈,本身写后端接口算一个解决办法。固然还有更好的解决办法,就是今天的主角GraphQL了。web
题外话:我自学的编程技术,野生程序员,刚入门的时候老是迷茫不知所措。看文档N遍仍是不知因此然,后来尝试这按照教程去写代码,刚开始本身都知道写的是什么意思,可是写的过程当中会遇到不少文档里没有提到的东西。逼迫着你去百度找到解决办法,那个时候也没人指导,身边页也没有搞程序开发的。自学起来真的很痛苦,后来发现学编程文档要看。更重要的是要实践,实际的写代码,会发现掌握的速度远比看文档要快。亲身体会建议你们,想学习更透彻,直接写代码吧。固然如今不少时候真的能够作到看文档就能够学会新技术了,那是由于有这几年的技术积累,无论是计算机概念仍是原理都比刚开始入门时一贫如洗时的基础好太多了,当你沉淀下来的时候你会发现,其实本身的知识体系超过了不少科班出生的程序员。最后:想深刻理解技术原理,直接写代码吧!express
正式开始: 技术栈很简单:Express+GraphQLnpm
这里会展现一个基于 Express web服务器的一个 GraphQL API 服务端参考实现.首先新建一个文件夹express,在当前文件夹执行编程
npm install express express-graphql graphql faker --save
复制代码
在express 文件夹下新建 server.js文件,文件内容先丢出来,而后逐句解释说明json
var express = require('express'); var graphqlHTTP = require('express-graphql'); var { buildSchema } = require('graphql'); var faker = require('faker'); var randomName = faker.name.findName(); // Rowan Nikolaus var randomEmail = faker.internet.email(); // Kassandra.Haley@erich.biz var randomCard = faker.helpers.createCard(); // random contact card containing many properties var { graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLList, GraphQLFloat, GraphQLID } = require('graphql'); const articleType = new GraphQLObjectType({ name: 'Citys', fields: { time: { type: GraphQLString }, title: { type: GraphQLString }, order: { type: GraphQLInt} } }) var Articleschema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'RootQueryType', fields: { id: { type: GraphQLID, description: '惟一id', args: { id: { // 这里定义参数,包括参数类型和默认值 type: GraphQLID, defaultValue: 1 } }, resolve : (_, args) => { console.log(_, args.id) return Number(1 + args.id) } }, hashed:{ type: GraphQLFloat, description: '随机值', resolve : () => { return Math.random() } }, name: { type: GraphQLString, description: '姓名', resolve : () => { return randomName } }, hello: { type: new GraphQLList(articleType), resolve() { return [ {'time':'2019-2-1', 'title':'武汉', 'order':1}, {'time':'2019-2-2', 'title':'南昌', 'order':2}, {'time':'2019-2-3', 'title':'贵阳', 'order':3}, ] } }, age: { type: GraphQLString, resolve: () => 18 }, list: { type: new GraphQLList(articleType), description: '城市信息数组', resolve: async (_, args) => { return await [ {'time':'2019-2-1', 'title':'武汉', 'order':1}, {'time':'2019-2-2', 'title':'南昌', 'order':2}, {'time':'2019-2-3', 'title':'贵阳', 'order':3}, ] } }, } }) }); var Commentschema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'RootQueryType', fields: { id: { type: GraphQLID, description: '惟一id', args: { id: { // 这里定义参数,包括参数类型和默认值 type: GraphQLID, defaultValue: 1 } }, resolve : (_, args) => { console.log(_, args.id) return Number(1 + args.id) } }, hashed:{ type: GraphQLFloat, description: '随机值', resolve : () => { return Math.random() } }, name: { type: GraphQLString, description: '姓名', resolve : () => { return randomName } }, hello: { type: new GraphQLList(articleType), resolve() { return [ {'time':'2019-2-1', 'title':'武汉', 'order':1}, {'time':'2019-2-2', 'title':'南昌', 'order':2}, {'time':'2019-2-3', 'title':'贵阳', 'order':3}, ] } }, age: { type: GraphQLString, resolve: () => 18 }, list: { type: new GraphQLList(articleType), description: '城市信息数组', resolve: async (_, args) => { return await [ {'time':'2019-2-1', 'title':'武汉', 'order':4}, {'time':'2019-2-2', 'title':'南昌', 'order':5}, {'time':'2019-2-3', 'title':'贵阳', 'order':6}, ] } }, } }) }); var app = express(); app.get('/', (req, res) => res.send('Welcome Graphql!')) app.use('/graphql', graphqlHTTP({ schema: Articleschema, graphiql: true, })); app.use('/comment', graphqlHTTP({ schema: Commentschema, graphiql: true })) app.listen(5000, () => console.log('Now browse to localhost:4000/graphql')); // # 每一个字段都有对应的执行函数,也就是resolver函数 复制代码
接下来修改package.json 加入npm 执行脚本。这里的nodemon 是node的工具,你也能够直接用node server.js.可是没法自动监听 server.js 文件修改后自动重启。nodemon 能够实现server.js 文件修改后自动重启服务。后端
{ "scripts": { "dev":"nodemon server.js" }, "dependencies": { "express": "^4.16.4", "express-graphql": "^0.7.1", "graphql": "^14.1.1" }, "devDependencies": { "faker": "^4.1.0" } } 复制代码