GraphQL Server Architecture and Implementation (Part 2)
In the last article, we learned a lot about the basic inner workings of the GraphQL server by learning about GraphQL Schema and its basic role in performing queries and variations.
While we’ve seen how the GraphQL server performs these operations using the GraphQL engine, we haven’t touched on the actual client-server communication aspect: the question of how queries and their responses are transmitted over the network. That’s the subject of this article!
The GraphQL server can be implemented in any programming language you like. This article focuses on JavaScript and some of the libraries available to help you build servers, especially Express-GraphQL, Apollo-Server, and GraphQL-Yoga.
Service GraphQL via HTTP
GraphQL is transport layer independent
The key to understanding GraphQL is that it has virtually nothing to do with how data is transferred over the network. This means that the GraphQL server may be able to work over protocols other than HTTP, such as WebSockets or lower-level TCP. However, this article focuses on the most common way to implement a GraphQL server today, which is indeed based on HTTP.
Express.js as a powerful and flexible foundation
The following sections focus on express.js and its middleware concepts for GraphQL libraries such as Express-GraphQL and Apollo-Server. If you are already familiar with Express, you can skip to the next section.
The above is due on January 31, 2020.
NPM trendonexpress.hapi.koa and sailThe comparison of
Express.js is by far the most popular JavaScript Web framework. Its simplicity, flexibility and performance make it dazzling.
To start experimenting with your own server, just use the following code:
const express = require('express')
const app = express()
// respond with "hello world" when a GET request is received
app.get('/'.function(req, res) {
res.send('<h1>Hello World</h1>')
})
app.listen(3000)
Copy the code
After executing this script using Node.js, you can access the website by typing http://localhost:3000 in the browser address bar:
You can easily add more endpoints (also known as routes) to the server API:
app.get('/goodbye'.function(req, res) {
res.send('<h1>Goodbye</h1>')})Copy the code
Or use another HTTP method, such as POST instead of GET:
app.post('/'.function(req, res) {
res.send('<h1>You just made a POST request</h1>')})Copy the code
Express provides great flexibility in implementing servers, allowing you to easily add functionality using middleware concepts.
Key to Express flexibility and modularity: middleware
Middleware allows incoming requests to be intercepted and specific tasks performed while the request is being processed or before a response is returned.
Essentially, middleware is nothing more than a function with three parameters:
req
: Incoming request from the clientres
: Response returned to the clientnext
: calls the next middleware function
Because middleware functions have (write) access to both incoming request objects and outgoing response objects, it is a very powerful concept to tailor requests and responses to specific purposes.
There are many use cases for middleware, such as authentication, caching, data transformation and validation, execution of custom business logic, and so on. Here is a simple logging example that will print the time when the request was received:
function loggingMiddleware(req, res, next) {
console.log(`Received a request at: ${Date.now()}`)
next()
}
app.use(loggingMiddleware)
Copy the code
The flexibility gained through this middleware approach is taken advantage of by frameworks such as GraphQL-Express, Apollo-Server, or GraphQL-Yoga, all of which are based on Express!
Express with GraphQL
With everything we learned about the GraphQL function and the GraphQL execution engine in the previous article, we can now expect how the Express-based GraphQL server will work.
Express provides everything you need to handle HTTP requests, while GraphqL.js provides the functionality to solve queries, and what we still need is the glue between them.
This glue is provided by libraries like Express-GraphQL and Apollo-Server, which are nothing more than middleware functions for Express!
GraphQL middleware glues HTTP and GraphqL.js together
express-graphql
Facebook’s GraphQL middleware version
Express-graphql is a version of Facebook’s GraphQL middleware that works with Express and graphqL.js. If you look at its source code, you’ll notice that its core functionality is implemented in just a few lines of code.
Really, its main responsibilities are twofold:
- Ensure that the GraphQL query (or variation) contained in the body of the incoming POST request can be executed by graphQL.js. Therefore, it needs to parse the query and forward it to the GraphQL function for execution.
- Append the execution result to the response object so that it can be returned to the client.
With Express-GraphQL, you can quickly start GraphQL server development as follows:
const express = require('express')
const graphqlHTTP = require('express-graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const app = express()
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: (root, args, context, info) => {
return 'Hello World'
}
}
}
})
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true // enable GraphiQL
}))
app.listen(4000)
Copy the code
Using Node. Js will execute this code at http://localhost:4000/graphql started a GraphQL server.
If you’ve read the previous article on GraphQLSchema, you’ll have a good idea of the purpose of lines 7 to 18: We built a GraphQLSchema that performs the following queries:
query {
hello
} # responds: { "data": { "hello": "Hello World" } }
Copy the code
What’s new in this code snippet, however, is the integration of the network layer. Instead of setting up the inline query and executing the query directly using GraphqL.js (as shown here), we set up the server to wait for the incoming query and then execute the query against GraphQLSchema.
You really don’t need a lot of preparation to start using GraphQL on the server side.
apollo-server
: Better compatibility outside the Express ecosystem
Apollo-server is essentially very similar to Express-GraphQL, with some subtle differences. The main difference between the two is that Apollo-Server also allows integration with many other frameworks, such as KOA and HAPI, as well as FaaS such as AWS Lambda or Azure Functions. You can install individual integrations by appending the appropriate suffix to the package name, for example: Apollo-server-Express, Apollo-server-KOA, or Apollo-server-lambda.
Ultimately, however, it is still middleware that Bridges the HTTP layer with the GraphQL engine provided by GraphqL.js. This is what the equivalent implementation of the express-GraphQL-based example above looks like in Apollo-server-Express:
const express = require('express')
const bodyParser = require('body-parser')
const { graphqlExpress, graphiqlExpress } = require('apollo-server-express')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: (root, args, context, info) => {
return 'Hello World'
},
},
},
}),
})
const app = express()
app.use('/graphql', bodyParser.json(), graphqlExpress({ schema }))
app.get('/graphiql', graphiqlExpress({ endpointURL: '/graphql'})) / /enable GraphiQL
app.listen(4000)
Copy the code
Graphql-yoga: The easiest way to build a GraphQL server
Remove the drag when building the GraphQL server
Even when using Express-GraphQL or Apollo-Server, there are a number of obstacles:
- Multiple dependencies need to be installed
- Prior knowledge of Express is assumed
- Subscribing with GraphQL requires complex setup
You can eliminate this resistance with GraphQL-Yoga, a simple library for building graphQL servers. It is essentially a convenience layer on top of Express, Apollo-Server, and several other libraries to provide a quick way to create a GraphQL server. (Think of it as similar to the Create-React-app for the GraphQL server.)
Here’s the same graphQL server code we saw in Express-GraphQL and Apollo-server:
const { GraphQLServer } = require('graphql-yoga')
const typeDefs = `
type Query {
hello: String!
}
`
const resolvers = {
Query: {
hello: (root, args, context, info) => 'Hello World',
},
}
const server = new GraphQLServer({ typeDefs, resolvers })
server.start() // defaults to port 4000
Copy the code
Note that GraphQLServer can be instantiated using either a ready-made instance of GraphQLSchema or a quick interface based on makeExecutableSchema from GraphQL-Tools. As shown in the code snippet above.
Built-in GraphQL playground, subscription, and tracking support
Graphql-yoga has built-in support for GraphQL-playground. Using the code above, you can open Playground at http://localhost:4000:
Graphql-yoga also has a simple API for off-the-shelf GraphQL subscriptions, built on top of graphQL-Subscriptions and WS-Subscriptions-Transport packages. You can see how it works in this straightforward example.
To enable field level analysis for GraphQL operations performed with GraphQL-Yoga, there is also built-in support for Apollo Tracing.
conclusion
After discussing the GraphQL execution process based on GraphQLSchema and the concept of a GraphQL engine (such as graphqL.js) in the previous article, this time we will focus on the network layer. In particular, the GraphQL server responds to HTTP requests by using the execution engine to process queries (or variations).
In the Node ecosystem, Express is by far the most popular framework for building Web servers because of its simplicity and flexibility. Therefore, the most common implementations for GraphQL servers are Express-based, most notably Express-GraphQL and Apollo-Server. Both libraries are very similar, with some subtle differences, most importantly apollo-Server is also compatible with other Web frameworks, such as KOA and HAPI.
Graphql-yoga is a convenience layer on top of many other libraries such as GraphQL-Tools, Express, GraphQL-Subscriptions, and GraphqL-Playground, and is the easiest way to build a GraphQL server.
In the next article, we’ll discuss the insides of the info parameter passed to the GraphQL resolver.
Click here for the original link