为什么要用graphql?
让我们先回顾一下我们现在所使用的API设计风格
纯rest:一个endpoint对应一个资源
优点:灵活、解构
缺点:由于一个endpoint对应一个资源所以需要很多次请求
类rest:一个endpoint对应一个视图
优点:一次请求、所得即所需
缺点:不够灵活、高度耦合、很高的维护成本、迭代慢
上面是我们两种常用的接口方式,两种都有各自的优缺点,有没有可以包揽所有优点的方案呢?我们需要一个标准的API层,那这就是GraphQL,请注意GraphQL是一个规范,是由facebook倡导的一个规范,不是一个实现。
GraphQL有下面三个定义:
- 一个用来描述数据类型和关系的API定义语言
- 一个可以描述具体需要获取哪些数据的查询语言
- 一个可以resolve到数据单个属性的可执行模型
GraphQL是长什么样子的呢?
可能这样看起来还比较难理解,没事,我们直接coding。
GraphQL实践
由于GraphQL是一种规范,它不是一种实现,如果要自己实现还是比较难的,不用担心,强大的开源社区已经帮我们准备好了,这就是Apollo开源项目。Apollo提供了丰富的后端实现(node支持:express、koa、hapi、restify等框架)和前端(React、RN、Angular、IOS、Android等)实现。官方文档:http://dev.apollodata.com/too...。下面的实践都是基于Apollo以nodejs的Express框架来实现的。
Demo代码:https://github.com/jasondu/ap...
一、如何搭建GraphQL服务端
步骤
搭建服务器
import express from 'express';
import {
graphqlExpress,
graphiqlExpress,
} from 'apollo-server-express';
import bodyParser from 'body-parser';
import schema from './data/schema'; // 定义GraphQL查询格式
const GRAPHQL_PORT = 3002;
const graphQLServer = express();
graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({ schema })); // 实现GraphQL接口功能
graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })); // 实现GraphQL浏览器调试界面
graphQLServer.listen(GRAPHQL_PORT, () => console.log(
`GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
));
懂Express的童鞋应该都可以看到上面的代码,我做一下解释:
- apollo-server-express 是由Apollo提供在express环境下实现grapql的库,这里使用了里面两个类
- graphqlExpress是实现grapql接口功能的类
- graphiqlExpress是实现grapql浏览器调试界面(An in-browser IDE for exploring GraphQL.)的类,就多了一个“i”,这个调试界面可以在后面看到
- schema就是上文讲的是定义GraphQL查询格式的
-
编写Schema
让我们看看Schema.js是怎么写的
import {
makeExecutableSchema,
} from 'graphql-tools';
import resolvers from './resolvers';
// 定义schema
const typeDefs = `
type Author { # 作者的字段有:id,名字,还有 发表的帖子
id: Int
firstName: String
lastName: String
posts: [Post]
}
type Post { # 帖子的字段有下面这些,包括 这个帖子是哪个作者写的
id: Int
title: String
text: String
views: Int
author: Author
}
type Query { # 定义查询内容
author(firstName: String, lastName: String): Author # 查询作者信息
getFortuneCookie: String
}
`;
const schema = makeExecutableSchema({ typeDefs, resolvers });
export default schema;
这里用到Apollo提供的makeExecutableSchema方法,这个方法是将Schema结构的数据转换成GraphQLSchema实例。
typeDefs里面定义了三个格式Author,Post,Query,这里Query就是查询的时候返回的结构,Author,Post是解释了在Query中的结构类型。
接下来,我们就可以编写具体的实现了。
编写Resolvers
const resolvers = {
Query: {
author(root, args){ // args就是上面schema中author的入参
return { id: 1, firstName: 'Hello', lastName: 'World' };
},
},
Author: {
// 定义author中的posts
posts(author){
return [
{ id: 1, title: 'A post', text: 'Some text', views: 2},
{ id: 2, title: 'Another post', text: 'Some other text', views: 200}
];
},
},
Post: {
// 定义Post里面的author
author(post){
return { id: 1, firstName: 'Hello', lastName: 'World' };
},
},
};
export default resolvers;
上面这段代码比较简单,就不做解释了。
至此,我们就完成了一个GraphQL服务端的开发,加下来我们npm i & npm start
呐,这样就启动啦!打开http://localhost:3002/graphiql就可以看到刚才前面说的graphiql,就是GraphQL浏览器调试界面。
graphiql可以支持联想功能,可以非常快的书写查询语句。
二、如何在客户端查询GraphQL数据(以react为例)
步骤
使用create-react-app创建一个项目,并且按照Apollo客户端解决方案库:react-apollo
create-react-app client & yarn add react-apollo
修改App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
// -------- 添加内容 -------- //
import {
ApolloClient,
ApolloProvider,
createNetworkInterface,
gql,
graphql,
} from 'react-apollo';
// 设置接口地址
const networkInterface = createNetworkInterface({ uri: 'http://localhost:3002/graphql' });
const client = new ApolloClient({
networkInterface,
});
const Test = ({ data: { loading, error, author } }) => {
if (loading) {
return <p>Loading ...</p>;
}
if (error) {
return <p>{error.message}</p>;
}
return (
<h3>{author.firstName} {author.lastName}</h3>
);
};
// 查询语句
const query = gql`
query AuthorQuery {
author (firstName: "firstName", lastName: "lastName") {
firstName,
lastName
}
}
`;
const Gtest = graphql(query)(Test);
// -------- 添加内容 -------- //
class App extends Component {
render() {
return (
<ApolloProvider client={client}>
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<Gtest />
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
</ApolloProvider>
);
}
}
export default App;
这里的写法跟redux类似,使用<ApolloProvider>包裹项目,通过graphql方法将数据注入到组件中。
然后执行yarn start 这样项目就启动了,如下图
注:这里存在跨域问题,所以服务器端需要使用cors解决跨域问题,具体看代码。
下面是我收集的相关学习资料:
https://dev-blog.apollodata.c...
《Tutorial: How to build a GraphQL server》讲解了如何搭建node GraphQL服务器,如何定义schema,还有如何链接以前的SQL数据库,rest等,入门必读
https://dev-blog.apollodata.c...
《Full-stack React + GraphQL Tutorial》讲解如何和客户端结合起来,还有如果实现ws实时通信等
https://launchpad.graphql.com...
这个是apollo提供的线上编辑器,可以在线上编写schema和resolve,然后可以下载下来部署
这个网站详细讲解了如何在各种服务器客户端使用graphql
http://taobaofed.org/blog/201...
《Node.js 服务端实践之 GraphQL 初探》阿里在15年写的文章
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。