GraphQL allows us to define a generic, UI-agnostic data model on the server using a graph schema that encodes the natural relationships within the data. To wire our model to data, we define resolvers in the schema that leverage our db's own query language (SQL, NoSQL, or Graph query language, etc) or in-memory objects to resolve client-defined, graph-oriented queries against our generic data model.
With each components in the UI component tree declaring its own data dependencies, GraphQL/Relay creates a projection of the graph data model that maps to the UI component tree, thus allowing us to have a UI-agnostic data model on the server, while at once giving us and UI-specific projection of the data. The queries from GraphQL server to the database are composed in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component tree, thus eliminating redundant queries to the database.
GraphQL allows us to have a generic graph data model that can express all the relations between our data and that can be conceptually defined atop our db schema, and then visualized and comprehended without any knowledge of the internal SQL/NoSQL/Graph schema of our db, making it easier for front end folks and customers to work with, where our GraphQL Schema defined data model acts as an abstraction layer between the DBA realm (where writing GraphQL query resolvers and optimizing db structure happens) and the Application Developer realm, where the GraphQL Graph Schema and React/Relay components are constructed.
Relay also allows for mutation events from the UI to propagate to the GraphQL server which sync it to the db, while rendering the UI optimistically, and then merging to most current UI state. It can also update the UI when an external mutation (from another process/user) is recorded by the db.
Given how UI data dependencies are specified declaratively, the front end developer's job becomes a much more pleasant task consisting of simply building components and specifying their data dependencies and mutation resolvers. GraphQL and Relay take care of the rest.
Relay apps are regular React apps, so everything that can be done with a React app can be done with a React+Relay app, including access to the lifecycle methods and local state of components. Relay is simply the data/state sync layer. We can only have parent-child composition in the DOM and that is true for React's DOM renderer, too. The UI as a structure is a tree of composite components implementing various behavior that mutate the DOM. So whatever you can do in with React you'll be able to do with Relay.
The Facebook Relay team is also planning on providing time travel facility (time based app state inspection) for React/Relay apps (potentially using the dev tools part of Redux) making solutions like Redux not only redundant but also very brittle in comparison as they depend on a hardcoded app state data structure which means more rework when the data dependency tree of our UI changes. With GraphQL/Relay everybody, be them web, mobile or 3rd party developers, works with the same graph model of the data and declare their data dependencies at the UI component level, and have GraphQL in combination with Relay take care of generating an efficient query and shaping the query result for the UI. So it can be said that the GraphQL/Relay approach is less brittle.
In one fell swoop, GraphQL/Relay eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORM/OGM, client/server caches, and client-side solutions like Flux/Redux that aren't deep enough.
Based on the fact that only a deep architecture like GraphQL/Relay can allow us to make continuous changes to the UI without manual rework of the data model<->UI wiring, which, as explained above, cannot be done with by a client-side-only framework like Redux, I asked folks at Facebook if Redux is going to be made obsolete by GraphQL/Relay. Their reply seems more political than technical, and I can't really buy into it unless I buy into the idea that "Farmework XYZ" is always changing so it will never become obsolete. The truth is if Redux is to fit together with Relay it will need to be changed radically that it won't be the same thing.
![twitter exchange] (http://i.imgur.com/0aBjEGL.png)
###Limitations
Query resolution in GraphQL is defined in the schema, which implements data model transformations that maybe evaluated as part of the the query, e.g. OrderBy, InRange, hasSomeRelation etc.
This carries the interesting implication that GraphQL cannot be used (on its own) to support the kind of cient-defined queries that require ad-hoc model transformations. An example would be an app that allows the user to slice and dice her data in an arbitrary fashion.
Here are the responses I got to the above:
![twitter response] (http://i.imgur.com/pJrlXYf.png)
If we stop thinking of GraphQL as a Graph Query Language in the Graph DB sense, which it's not, and instead think of it as Graph-y RPC Language then it makes sense to use a Query DSL. The confusion beginners often have is with the idea implied by GraphQL, i.e. a graph query language. The chosen name is GraphQL where Q stands for "Query" but in reality it's a "Graph-y RPC Language" or "Graph-based Extensible API Protocol."
###References
- [Building a GraphQL Server with Node.js and SQL] (https://www.reindex.io/blog/building-a-graphql-server-with-node-js-and-sql/)
More coming soon... 2. ###Updated 1:
(after a Twitter chat with @en_JS (Joseph Savona), one of the GraphQL/Relay developers at Facebook)
Any app state that is not sync'd to the db is not something that Relay encompasses right now, but there is an ongoing [discussion] (facebook/relay#114) for handling things like form validation where the validation logic resides on the server and state updates from sources other than the db (e.g. websocket)
These important scenarios will be addressed according to the Relay Roadmap (https://github.com/facebook/relay/wiki/Roadmap):
-
API for resolving fields locally: #431.
-
Support querying & compiling client-only fields by extending the server schema, and a means for writing data for these fields into the cache: #114.
###Update 2:
@gaearon (Dan Abramov), author of Redux, was gracious enough to tweet this, and I give him a lot of credit for doing so.
Here is a section of the very long conversation that Dan started:
![twitter conversation] (http://i.imgur.com/BD2Wu5m.png)
###Update 3:
My follow up conversation with Dan below
![twitter follow up] (http://i.imgur.com/43lsGJo.png)
###Update 4:
Answer from @en_JS (Relay lead at Facebook?) to the first complex use case I ran into, which gives me a lot of confidence in Relay.
![twittter followup] (http://i.imgur.com/aWC9ur0.png)
[@en_JS' truncated link] (https://facebook.github.io/relay/docs/api-reference-relay-container.html#setvariables)
####Update 5:
I had a brief chat on Gitter with Jean-Jacques Dubray, author of [Why I No Longer Use MVC Frameworks] (http://www.infoq.com/articles/no-more-mvc-frameworks)
![gitter chat] (http://i.imgur.com/SAmptOC.png)
####Update 6:
I was wondering how to safely and properly expose typical DB operations to the client via GraphQL since not every UI is going to want canned query resolution specified in the query resolves. Some UI use cases call for composing queries with specific operators. Here is the answer:
![HN tip] (http://i.imgur.com/fGfZ8lI.png)
####Update 7:
Christopher from Facebook RT'd this about Datalayer, which can be used as cache to optimise query resolution:
![Twitter] (http://i.imgur.com/rTF8wLl.png)