[转] Initial Impressions on GraphQL & Relay
https://kadira.io/blog/graphql/initial-impression-on-relay-and-graphql
http://graphql.org/blog/subscriptions-in-graphql-and-relay/
Facebook recently made GraphQL and Relay open source, so now we can try them out. These are the two main components in Facebook's app architecture that focus on data management. They are in the very early stages.
Since we fixed some of Meteor's data-related issues, I'm really excited about these two projects. I played a bit with both of them and this is my experience and how I feel about them.
I am a die-hard Meteor fan. So, I might talk in favor of Meteor. But I'll try to be open minded and avoid mentioning Meteor.
What's GraphQL
Basically GraphQL is an application layer query language, which queries and mutates (or updates) data. You might think it's somehow related to a graph database. Yes, it has a good relationship with graphs, but it's not tied to a database.
Before looking at GraphQL, let's see what problems it's trying to solve:
- Client-side developers should have a way to ask for the data they need.
- Server-side developers should have a way to expose the data they have.
- There should be an easy and efficient way to query data (the REST API consumes a lot of resources, especially with mobile apps).
To clarify this, let's use Facebook as an example.
Whatever happens in the client apps or in the backend, there are millions of users who want to use Facebook every day. Mostly importantly, there are tons of ways to access Facebook. It has an app for every major platform and those apps have multiple versions. Technically, there might be 100's of apps.
So, adding a new feature should not break any of these apps.
That's where GraphQL is gonna help Facebook (and the rest of the developer community):
With GraphQL, a client-side developer can write a query against a GraphQL server and fetch data. Let's say that in a different version of the app, that developer wants more information. With GraphQL, they simply change the GraphQL query and get the data they need. They never need to ask the server-side developer to create a custom data endpoint.
You can also get most of the data for a given view using a single request to the server.
We'll talk more about GraphQL in a moment.
What's Relay?
Relay is a JavaScript application framework that can talk to a GraphQL server. With Relay, client-side developers can define data needs for each of their components with GraphQL.
Then when rendering a page, Relay aggregates all those GraphQL queries and invokes them against the GraphQL server very efficiently.
It can also mutate data and it supports cool features like optimistic updates. We'll also talk more Relay in a moment.
How GraphQL Works
GraphQL sits between the client apps and the actual data sources. It's a kind of agreement between the client and the server with an efficient querying system.
It's independent of platforms and data sources. You can create a GraphQL server in Node, PHP or any other platform you like. Mobile apps, web apps and anyone else should be able to connect to a GraphQL server. Then they can query and mutate data.
But GraphQL does not comes with a transport layer. That’s the responsibility of a high-level framework, like Relay.
GraphQL also has a very good type system. It's basically built on top of graphs with the types you define. You might feel that you don't need to expose your dataset as a graph. But, if you think closely, 90% of the time your data schema can be structured as a set of graphs.
Let's see some GraphQL
Enough talk. Let's see an example:
Just for a moment, assume that I am the developer who built Product Hunt.
Here, I'm trying to get the data for a typical Product Hunt page (like this). This is how I'm going to get them with GraphQL:
{
product(id: "react-native-for-android") {
name,
link,
votes,
comments {
text
}
}
}
So, it gives something like this as the result:
{
"data": {
"product": {
{
"name": "React Native for Android",
"link": "https://facebook.github.io/react-native/",
"votes": "167"
"comments": [
{
"Huuuuge for cross-platform progress.",
},
{
"Exciting stuff.",
}
]
}
}
}
}
Let's say, I am working on an upgraded version of Product Hunt and I need to display the author right next to the comment. To get that data, I simply change my GraphQL query like this:
{
product(id: "react-native-for-android") {
name,
link,
votes,
comments {
text,
author {
avatar
}
}
}
}
So, it's very easy to add features to the app without touching the server code or any other part of my app.
This is just the surface of GraphQL. Check out the GraphQL docs for more information.
What Does GraphQL Lack?
Everything in GraphQL looks good so far. But it's not the perfect solution.
One thing it's missing is the ability to update clients reactively. In the GraphQL spec, there is no way to subscribe and get updates. There have been some experiments and discussion on how to do so, but we don't have any examples yet.
Right now, to achieve real-time updates, we need to poll the server and get the changes.
What's the Catch?
These days, we talk about isomorphic concepts and sharing code between the client and server.
At the same time, now we are talking about decoupling the client and the server. So, I was confused a bit.
But, Facebook is right.
There should be a clear boundary between the client and the server with a common agreement. So, both parties can build and scale independently.
Isomorphic is not about sharing code between the server and the client. It's beyond that.
For an example, you might want to share some of the stuff you wrote for the web and use it in iOS. Maybe you can share some of the code in every part of your system, including in the server. It doesn't need to be code every time. May be it's some data definition or a set of images.
Finally, I think isomorphic means sharing resources between platforms.
If you need to grab a snack, this is the time. We are gonna discuss more stuff.
How Does Relay Work?
As I mentioned earlier, Relay is an application framework that connects to a GraphQL server and queries and mutates data. It's built on top of React components and it has an express-compatible network layer. But, it's possible to add custom network layers.
With Relay, you can express your data requirement for each UI component using GraphQL. Then, Relay will fetch them for you efficiently. It'll do the complex data management tasks such as:
- Mutations and handling changes (apply changes after a mutation)
- Optimistic updates (simulate mutation in the client, so the user doesn't need to wait for the server result to see the change they made)
- Data caching to reduce server round trips (simply reuse existing data)
If you are coming from Meteor, you’ll feel like these things are available by default in your app.
Oops! Did I just mention Meteor? Sorry!
The Good Parts of Relay
I really like the concept of defining the data requirement in the component itself. Relay can build GraphQL queries and decide what to fetch and when. That's brilliant.
Let's look at an example:
(It's a simple blog.)
This is our BlogPost
React component:
class BlogPost extends React.Component {
render() {
return (
<div className="post">
<h1>{this.props.post.title}</h1>
<p>{this.props.post.content}</p>
</div>
);
}
};
Next, we define the data requirements using GraphQL:
BlogPost = Relay.createContainer(BlogPost, {
fragments: {
// this is some GraphQL code.
// `fragment` keyword is used to create a subset of a type.
// (which is Post in this case)
post: () => Relay.QL`
fragment on Post {
title,
content
}
`,
},
});
Then, while loading the page, Relay will fetch these data for you:
Here's the interesting part. Let's say you want show the author right next to the title in the BlogPost component. Simply change the GraphQL query. It's that easy.
There is no need to change anything anywhere in your code.
What's Not Ideal in Relay?
I like the core concept behind Relay. But I don't like how it does mutations and handles changes.
Let's look at the problem first.
If Relay is all about querying data, there is no issue at all. Things start to blur when you call mutations. With a mutation, you update some part of your graph. Relay needs to get the changes done by the mutation and apply them into the app.
For instance, let's say in the above blog example, we called a mutation that adds a new comment. We keep both the comment count and the comments separately. So, for that mutation, we need to update two places in our graph.
The client needs to get these updates after the mutation and apply them correctly. This is a big issue.
How Relay Handles Mutation Changes
In Relay, we do this with fat queries. So, for every mutation, we need to define all the changes it makes as a special GraphQL query like this:
(We need to do this in the client.)
getFatQuery() {
return Relay.QL`
// Here when we add a new comment we need
// to get the new comment and the count again
fragment on Post {
comments,
commentCount
}
`;
}
I think this is a wrong decision.
Now the client-side developer needs to know the logic behind the mutation and use it inside the client code. It would have been better if Relay could figure it out automatically and apply the changes.
To do this, GraphQL could expose some information to Relay via its introspection functionality.
This would simplify the client-side developer's job.
How Relay Handles Optimistic Updates
With optimistic updates, we try to simulate the server-side mutation inside the client. Thus, we can reflect the UI changes without waiting for the server-side response. This concept is also known as latency compensation.
If we need to get optimistic updates in Relay, we need to run a simulation of that mutation inside the client. To do this in Relay, the client-side developer needs to write the logic.
But actually, this is the job of the server-side developer. It'd be great if the server-side developer could include these simulations while defining the mutation on the server using some sort of GraphQL.
This would simplify the client-side developer's job. They would simply have to call the mutation and Relay would know how to simulate and update the UI.
Suggestions
Finally, I think Facebook did an amazing job with GraphQL and Relay. However, Relay needs some improvements. Here are my suggestions:
- Allow the definition of mutation updates and simulations (mutation metadata) in the server. Make it a part of GraphQL.
- In the client, get the mutation metadata using GraphQL's introspection functionality.
- Then, Relay can apply the simulation and the data changes.
I'm really interested in these suggestions and I’m looking forward to experimenting on them. Let's see what we can do.
[转] Initial Impressions on GraphQL & Relay的更多相关文章
- [GraphQL] Create a GraphQL Schema
we’ll take a look at the GraphQL Language and write out our first GraphQL Schema. We’ll use the grap ...
- Spring Boot GraphQL 实战 03_分页、全局异常处理和异步加载
hello,大家好,我是小黑,又和大家见面啦~ 今天我们来继续学习 Spring Boot GraphQL 实战,我们使用的框架是 https://github.com/graphql-java-ki ...
- IOS 开发教程
http://www.raywenderlich.com/category/ios http://www.raywenderlich.com/50310/storyboards-tutorial-in ...
- JavaScript 2016年的概况
国外的网站stateofjs.com根据超过九千位开发人员的问卷调查,发布了2016年JavaScript的年度概况报名. 注:本文翻译的部分可能存在不准确的情况,请以原文为准. 调查结果的报告目录结 ...
- 2016年JavaScript技术栈展望
如果你正在筹划新的前端项目或者重构现有项目,那么你需要认识到现在的前端开发环境已经今非昔比,这其中有太多的选择了:React.Flux.Angular.Aurelia.Mocha.Jasmine.Ba ...
- ReactEurope Conf 参会感想
React 带来的革命性创新是前端世界过去几年最激动人心的变化.自从接触 React 以来,我深信 React 会改变客户端开发者(包括前端.iOS 和 Android)的开发体验.这次在巴黎举办的 ...
- Intel QuickAssist Technology and OpenSSL – Benchmarks and Setup Tips
Intel QuickAssist Technology and OpenSSL – Benchmarks and Setup Tips 来源:https://www.servethehome.com ...
- 1.1 React 介绍
1.1.1 React 是什么 React IS A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES 来自:React 官方网站 狭义来讲 React ...
- 一个iOS开发者对tvOS SDK的初探
http://www.cocoachina.com/ios/20151001/13652.html 作者:Chris Wagner原文地址:tvOS SDK: An iOS Developer’s I ...
随机推荐
- iOS: 学习笔记, Swift与Objective-C混用总结
Swift与Objective-C交互总结 在Swift中使用Objective-C(简单) 在创建OjbC文件时, XCode会提示创建XXX-Bridging-Header.h文件, 创建之 在创 ...
- 不支持关键字: “userid”。
运行程序提示:不支持关键字: “userid”. 找了很久在一篇博客里面提示web.config数据库字符串链接出错.
- HTML5峰会小记
5259月228日,在大连理工的伯川图书馆举办了一次HTML5峰会,小记一下这次峰会的内容. 名为HTML5峰会,其本质就是一次各大赞助商的轮番登场,产品介绍间隙插播一下HTML5.但是并不影响这次峰 ...
- C#事件(Event)学习日记
event 关键字的来由,为了简化自定义方法的构建来为委托调用列表增加和删除方法. 在编译器处理 event 关键字的时候,它会自动提供注册和注销方法以及任何必要的委托类型成员变量. 这些委托成员变量 ...
- 优先级和lisp式前缀表达式
if(f(a,b) > 0) # 1 if(f(a, b>0)) # 2 上面在调用f的时候,1使用括号表明了参数的优先级,不然会出现2这样的情况. 而使用lisp式的前缀表达式则不会有不 ...
- jquery判断邮箱格式问题
方法一: var search_str = /^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/; var email_val = $("#Email").val(); ...
- Hibernate 注解 字段不映射的注解
在字段前面加这个注解:@Transient
- linux平台的office文档转pdf(程序员的菜)
需要材料: 1. Openoffice3.4(我是32位的centos,可以根据自己的系统下载指定的openoffice软件包) 下载地址:http://sourceforge.net/projec ...
- WPF 界面布局DockPanel stackPanel WrapPanel 元素内容以及位置控制
1 DockPanel 1) 默认充满整个窗口. 2) 最后一个出现的部分,默认充满剩余空间. 3) 非最后一个出现的部分,根据其中内容,进行分配空间s 2 StackPanel 实现居左,居右,居中 ...
- Windows Azure云服务价格调整通知
好消息!由世纪互联运营的 Windows Azure推出优惠啦.我们采纳了多渠道客户的意见和建议,为了更好地服务大家,将降低多种云服务的价格,其中包括我们最受欢迎的服务 -虚拟机和 Block ...