GraphQL - ryantc94/Knights-of-Arthur GitHub Wiki
Facebook's GraphQL
http://facebook.github.io/graphql/October2016/ https://www.howtographql.com/
-
My understanding: so if when you're making changes to a website and you need new data you need to change the REST Api to return a different form of data, GraphQL disconnects this need by asking for specific data instead having the REST api do this for you.
-
GraphQL provides an alternative to REST.
-
GraphQL enables declarative data fetching, allowing client to specify the data that it needs from the API.
-
GraphQL is a query language and shouldn't be confused with a database language.
-
Due to increases in mobile usage, GraphQL helps mitigate this by decreasing the amount of data that gets sent back and forth.
Difference between REST Api and GraphQL
Context: You have page that displays 3 titles of a user's blog posts, and 3 followers of that user.
Rest Api
- With REST Api you would typically have multiple endpoints, which makes sense... imagine you put it in all 1 end point to return to you the 3 titles and 3 followers and the user. Well what if on another page you needed just the user, and on another just titles. You'd probably decouple these into individual endpoints to make this more maintainable especially or have one endpoint have a lot of logic. In this way REST Api is inflexible because the data structures returned by each endpoint is hardcoded by you to return a fixed data structure. (Kinda like you going to a restaurant and getting a pre fixe instead of a la carte)
- REST Api also introduces the concepts of underfetching + overfetching
Overfetching
- The endpoint you hit might need more than you actually need, you would probably hit an endpoint for a user for example and just need their name but get back a bunch of user info. (If you didn't want this you would need multiple endpoints to manage endpoints or very complicated and long logic?)
Underfetching & n+1 problem
- So under-fetching results from what I just brought up. If you have multiple endpoints to handle user info then you will have make requests to a lot of endpoints for additional data.
- The n+1 problem is that we would need to fetch user info for username and what not and then need to make another request for user followers, for example.
Rapid Product Iterations on the Frontend
- With REST Api a common pattern is to structure endpoints based off your views. I touched upon this in the top with one endpoint having a lot of logic. However this is very inflexible due to the potential of new data needs or under/overfetching.
GraphQL
- With GraphQL you send a single query to GraphQL server (which would be the equivalent of an express/node server for REST?) The server will respond with the query populated with necessary data. (this is the a la carte)
“Think in graphs, not endpoints.” Lessons From 4 Years of GraphQL by Lee Byron, GraphQL Co-Inventor.
- GraphQL can help with performance and data monitoring, determining which data field are no longer requested.
- GraphQL is strongly typed, using its GraphQL Schema Definition Language (SDL), this schema serves as the contract between the client and the server to define how a client can access the data.
GraphQL Core Concepts
SDL
- GraphQL has its own type system to define the schema (model) of an API, called SDL.
- Name/Age are fields
- ! means that this field is required
- A type can have relationship with other types, in this case a one to many relationship with type Post
type Person {
name: String!,
age: Int!
posts: [Post!]!
}
- In REST Api data requirements to endpoints are are encoded in the URL connecting to the endpoint
- Instead of having multiple endpoints, GraphQL only exposes a single endpoint
- This means that the client needs to send more information to the server to get back the specific data it wants in what is called a query
Query
- 'allPersons' is called a _**root field**_ of the query, everything after it is a _**payload**_ of the query
{
allPersons {
name
}
}
-
It seems like returned data, the sub data is returned as an array
-
How does allPersons know to return data of Person type???
-
In GraphQL, each field can have zero or more arguments if that’s specified in the schema. Meaning that the query can have params that specify a certain response, like how many Persons to return and such.
Mutations
- With GraphQL, changes to data stored in the backend are called mutations
- 3 types of mutations
- Creating new data
- Updating existing data
- Deleting existing data
Example of creating a new person
Mutations are follow same structure as query except it starts with 'mutation' keyword
You can query information as you mutate other information as well
mutation {
createPerson(name:"Foo", age:"1") {
name,
age
}
}
- GraphQL types have unique ids when server generates them so you can do this
type Person {
id: ID!
name: String!
age: Int!
}
Subscriptions
- GraphQL allows for real time connections to servers, they call it subscriptions
- When a client subscribes to an event it will hold a steady connection to the server, whenever that event happens it pushes data to the client.
- Whenever a new person is added to the database this new person data is sent back to the client that subscribed to this information
subscription {
newPerson {
name
age
}
}
Making a Schema (To tie it all together)
- The schema in GraphQL specifies the capabilities of the API and defines how clients can request the data, often seen as a contract between the server and client.
- Generally a schema is in GraphQL is just a collection of types.
- There are some special root types for GraphQL schemas, that are entry points for requests
- type Query {...}
- type Mutation {...}
- type Subscription {...}
- Example for 'allPersons' query, 'createPerson' mutation, and 'newPerson' subscription we would need to create
type Query {
allPersons(last: Int): [Person!]!
}
type Mutation {
createPerson(name: String!, age: Int!): Person!
}
type Subscription {
newPerson: Person!
}
Architecture
-
GraphQL has been released only as a specification, so you can build your own GraphQL server. http://graphql.org/code/
-
Some ways to architect with GraphQL
- GraphQL server with a connected database
A standard greenfield architecture with one GraphQL server that connects to a single database.
- In this setup you have on web server that implements GraphQL specifications.
- When a query arrives at the GraphQL server, it reads its payload and gets required info from database. This is called resolving the query.
- It then constructs response according to specifications and sends to client.
- GraphQL is transport-layer agnostic, meaning it can be potentially used with any network protocol.
- GraphQL doesn't care what kind of database is used or format data is stored.
- GraphQL server that is a thin layer in front of a number of third party or legacy systems and integrates them through a single GraphQL API
GraphQL allows you to hide the complexity of existing systems, such as microservices, legacy infrastructures or third-party APIs behind a single GraphQL interface.
- Basically it can act as a middle man for new technologies to talk to old technologies, get the data from them and package it for the new technologies.
- Here GraphQL doesn't care about the data source.
3/ A hybrid approach of a connected database and third party or legacy systems that can all be accessed through the same GraphQL API
Both approaches can also be combined and the GraphQL server can fetch data from a single database as well as from an existing system - allowing for complete flexibility and pushing all data management complexity to the server.
- Possible to have its own connected database and grab data from other legacy or third party databases
Resolver Function
- In a GraphQL server implementation each field in a payload actually corresponds to one function called a resolver, whose sole purpose is to fetch data for its field.
- When server receives a query it will call all functions that correspond to the payload fields.
- Once all resolvers return the server will package data up into the format specified by the query and send it back to the client.
GraphQL allows you to hide the complexity of existing systems, such as microservices, legacy infrastructures or third-party APIs behind a single GraphQL interface.
GraphQL Client Libraries
Complexity is pushed to the server-side where powerful machines can take care of the heavy computation work. The client doesn’t have to know where the data that it fetches is actually coming from and can use a single, coherent and flexible API.
- With imperative data fetching from a REST API, most applications will have to go through the following steps:
- construct and send HTTP request (e.g. with fetch in Javascript)
- receive and parse server response
- store data locally (either simply in memory or persistent)
- display data in the UI
- With the ideal declarative data fetching approach, a client shouldn’t be doing more than the following two steps:
- describe data requirements
- display data in UI (... it'll still need to fetch right, make requests to the server? ... I don't really understand the above differences come back to this after) <- (ans: I think basically with GraphQL you should like a client library manage this stuff, its abstracted away)
Clients
- Apollo Client
- Relay (Facebook)
- GraphQL steps up the abstraction ladder and abstracts away the need for low-level networking.
- With GraphQL you just need to define the query and let the client library implementation deal with response and request.
- We will need to update UI with response and there different ways for different libraries. (Look into it)
- You will want to maintain a cache of data previously fetched from server, and a local cache will greatly improve efficiency with data fetches and user experience. (https://dev-blog.apollodata.com/the-concepts-of-graphql-bc68bd819be3)
- ^ Normalizing the data means that the (potentially nested) query result gets flattened and the store will only contain individual records that can be referenced with a globally unique ID.
- Schema Validation helps debug a lot better.
- Colocation is big perk of GraphQL: the tight coupling of views and their data dependencies greatly improves the developer experience. The mental overhead of thinking about how the right data ends up in the right parts of the UI is eliminated.
Server
https://dev-blog.apollodata.com/graphql-explained-5844742f195e
- GraphQL does not specify a way to describe schemas or getting information for them, but does specify an algorithm for transforming them into data.
- Algorithm: Query traverses field by field and execute resolvers on each field, (BFS on type).
Batched Resolving
(Not really sure...)
Tooling + Ecosystem
Introspection
- GraphQL allows the Client to ask the Server about its schema, called Introspection
- ^ This can be accessed by querying the the '__schema' metafield which is always available on a root type.
- One of the most useful tools you will need as you build and use GraphQL APIs uses introspection heavily. It is called GraphiQL. (http://graphql.org/swapi-graphql/)
Security
https://www.howtographql.com/advanced/4-security/
- How do we mitigate risks of a crashing GraphQL Server from very large queries from either legit or malicious clients? A couple of ways...
Time Outs
- ...
Common Questions
- ...
GraphQL JS Tutorial
https://www.howtographql.com/graphql-js/0-introduction/
React + Apollo Tutorial
https://www.howtographql.com/react-apollo/1-getting-started/
Front End: React + Apollo 2.0 Back End: graphql-yoga (GraphQL server) + Prisma (GraphQL Api Layer)
- This introduction will use Apollo as GraphQL client library to side-step the need to implement caching and networking by ourselves.
Extra Information
https://dev-blog.apollodata.com/graphql-explained-5844742f195e https://blog.risingstack.com/graphql-overview-getting-started-with-graphql-and-nodejs/ https://github.com/graphql/graphql-js https://medium.com/@gethylgeorge/setting-up-a-simple-graphql-server-with-node-express-and-mongoose-ff8a1071af53 https://dev-blog.apollodata.com/tutorial-building-a-graphql-server-cddaa023c035