[转] 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 ...
随机推荐
- Sharepoint 问题集锦 - external list (外部列表)
使用Sharepoint开发过程中遇到的问题总结. 错误1: Unable to display this Web Part. To troubleshoot the problem, open th ...
- finalspeed服务器端和客户端安装
https://www.91yun.org/archives/2775 https://www.91yun.org/archives/615 1.首先安装服务器端:一键安装代码 wget -N --n ...
- Quartz1.8.5例子(六)
/* * Copyright 2005 - 2009 Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the ...
- Delphi 版本号(D1到XE6),发现一个delphi.wikia.com网站
Borland Compiler Conditional Defines Edit Talk1 2,909PAGES ONTHIS WIKI Product Name Version Cond ...
- 10.在Global全局文件中的Application_BeginRequest示例
只要有人访问本网站,都要执行全局文件的Application_BeginRequest事件.因此我们可以防盗链. 示例要求:凡不是网站本机登录的都给客户端提示,用图片显示. 分析:由于网页在加载时不是 ...
- lc面试准备:Number of 1 Bits
1 题目 Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also ...
- 利用WITH AS 优化FILTER
SQL> explain plan for select * from fxqd_list_20131115_new where (acct_no, oper_no, seqno, trans_ ...
- 【POJ】2503 Babelfish
字典树简单题. #include <cstdio> #include <cstring> #include <cstdlib> typedef struct Tri ...
- 数据结构与算法分析——C语言描述
P1.1 选择问题,选择出第K大的数,并画出N为不同值的运行时间,K=N/2 毕业两年半,重写排序,感觉良好.代码使用冒泡排序,库函数clock计算大致运行时间. // P1_1.cpp : Defi ...
- Automake
Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...