In our last article on GraphQL, we looked at what GraphQL is, and why it matters. We also looked at some basic queries and what the server returns in response. If you are not familiar with the basics of GraphQL, you may want to read that article. However, if you are more hands-on, you may want to just dive right in to this tutorial about GraphQL server.
In this article, we’ll set up the server, as well as the GraphiQL browser so that we can play around with some queries and try out our server. We’ll utilize mocking to return some mock data and show how simple it is to get set up and running with fake data that can actually be used in creating applications.
I mentioned in the last article that, with GraphQL, we can coordinate work between our front-end and back-end teams by creating a GraphQL schema on our server. The schema represents the types of data available to query against. So let’s create a schema that we’ll use to get our server up and running.
First let’s create a project folder and also a folder for our server.
Fire up your command line. (I’m putting the project in the Documents folder. I’m a macOS user, as you may guess.)
$ cd ~/Documents $ mkdir _GraphQL $ cd _GraphQL/ $ mkdir server $ cd server $ mkdir mock $ cd mock
In order to get our server going, we’ll use the Node Package Manager (npm) to install the libraries we’ll use for our server. We’ll run our server using Node Express. If you don’t already have Node (and npm) installed head over to the npm docs to do so. When you install Node.js, then npm is also installed.
Second, let’s initialize our project and create a package.json file:
$ npm init \\This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields and exactly what they do.
Use `npm install –save` afterwards to install a package and save it as a dependency in the package.json file.
Press ^C at any time to quit. name: (mock) mock-server version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC)
About to write to /Users/chrislivdahl/Documents/_GraphQL/server/package.json:
{ "name": "mock-server", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this ok? (yes) yes
When prompted, name the server “mock-server”, and then just hit enter on each other prompt to let npm populate with defaults, and then type “yes” to confirm. You should now have a package.json file in your directory. Let’s start installing the packages we’ll need in order for our server to run.
$ npm install express --save
This will load the package for Express and update your package.json file so that, for anyone else installing your project, Express will be installed as a dependency. A bunch of files and package dependencies will also show up in a folder called node_modules.
Let’s create an index.js file, and add the following code:
const express = require('express') const app = express() app.get('/', (req, res) => res.send('Hello World!')) app.listen(3000, () => console.log('Example app listening on port 3000!'))
Let’s run our basic Express server:
$ node index.js
This will launch your server on port 3000. Point your browser to http://localhost:3000, and you should be able to receive a response from the server.
Our vanilla Express server.
Okay, now we need to add the GraphQL parts of our server.
Thanks to the work by the fine folks in the Apollo community, we have a collection of open-source front-end and back-end libraries for working with GraphQL. We can easily create the server using their apollo-server-express library. We’ll also need to install a helper library called graphql-tools, a library of massively useful tools built by the Apollo community. We also need the core graphql JavaScript implementation of the GraphQL specification from Facebook.
$ npm install --save apollo-server-express graphql-tools graphql express body-parser
Third, let’s modify our index.js file to the code given in the below link:
https://github.globant.com/gist/stay-relevant/2a0cc7f4fe5802e87ef816c5f6ba5cff
Here we have our type declarations in the typeDef string. This string contains GraphQL schema language for making a root set of queries, along with a set of types of data that could be returned from a query.
We’ll take this list of types in our schema and feed it into the makeExecutableSchema function for our Express server. The makeExecutableSchema function will feed our schema into our server so that we can make queries against it.
Along with the schema, we’ll use addMockFunctionsToSchema in order to automatically get mock data returning from our server. With that one line, we get mock data that automatically populates all the fields for each type in our schema!
Note that now we have a couple new endpoints. Our front end app can make calls with GraphQL queries to http://localhost:3000/graphql to get data.
But, for perusing GraphQL queries visually, we can run http://localhost:3000/graphiql in our browser to play around with our GraphQL server (note the “i” in “graphiql”).
We’ll need to shut down our server and re-run it. In the command line, run control-C to shut down the existing Node process. Then restart it:
$ node index.js
Let’s enter the GraphiQL address into our browser and make a simple query in the playground:
A simple GraphQL query in our GraphiQL playground.
We enter our query in the left side, and hit the run button (the large “play” triangle). And on the right side our mock data shows up! Note that the data returned matches the type of each field. The “id” field is of type “ID” and thus returns something that looks like a hashed string. The title is a simple string, the popularity field is a Float, and so on.
So, with a relatively small amount of code on our part, we’ve created a working GraphQLserver, along with the ability to browse the mock data using the GraphiQL browser.
Our mock data is a little bit odd, admittedly. Our movie has a negative popularity value like “-51.7321…” which is not necessarily helpful when putting this information in a user interface to see how real data looks. Let’s modify our mock data to be a little more realistic. For that, we can use a helpful package called casual. Let’s install it:
$ npm install casual --save
Also, we’ll create a “resolver” file that contains functions that resolve the query for a field to the data we want to return.
Fourth, let’s add a file that contains our mock resolvers and call it mocks.js:
https://github.globant.com/gist/stay-relevant/af68e7941db7a901bebb3695f6d72786
What this code is doing is creating a function for each type in our schema, along with a function for each field. The casual library will return a realistic string for each field.
Let’s import these mocks into our index.js file near the top:
const express = require('express') const bodyParser = require('body-parser') const { graphqlExpress, graphiqlExpress } = require('apollo-server-express') const { makeExecutableSchema, addMockFunctionsToSchema } = require('graphql-tools') const { mocks } = require('./mocks')
And where we call addMockFunctionsToSchema, let’s add our mocks:
addMockFunctionsToSchema({ schema, mocks })
Now we need to shutdown and restart our Node server (control-C and $ node index.js). Refresh your browser on http://localhost:3000/graphiql, and let’s try our movie query again:
The result of our movie query, with better mock data.
As you can see, now we’re getting back data that may be a little more realistic, featuring good ol’ Lorem Ipsum placeholder text. This kind of mock data can be helpful if we’re building a client app consuming this data and our UI depends on fields being a certain length, or at least where we want the displayed data to be more realistic. With mocked data, we can plug away on our front-end development and user experience using an agreed-upon schema, without being hampered by server-side work that may still be in-progress in terms of returning actual data.
Now let’s add some more to our schema and show how we can add relationships between objects.
Fifth, change your index.js file to the following:
https://github.globant.com/gist/stay-relevant/ec4968824bd65f57600b167b834a2344
Note that now we’re using an “Interface” in our schema called “Media.” This interface is implemented by both the Movie and TVShow types. We can use interfaces for things like lists, such as the list of Media in our Genre type. In other words, when we query for genres, we can get a list of movies and TV shows for each genre. We’ve also added a query called “allGenres” to our Query type so that we can get a list of all the genres.
Let’s also make our mocks a bit more robust.
Sixth, modify your mock.js to the following:
https://github.globant.com/gist/stay-relevant/9438f94cd2a59429e19b825fd8acb9d4
Here we’ve added the usage of MockList from graphql-tools. We can use MockList to say we want a number of objects as specified. You can pass in a single number to say that you always want a certain number of mock objects. Or, you can pass in an array of numbers to say that you want a number of mock objects between a minimum and maximum number. So, for example, above we stated that we want MockList(5) for the “allGenres” query, so we’ll get back exactly 5 mock genre objects when we run this query.
With all of that in place, stop the server (using control-C on a Mac) and restart it, and let’s try it out:
$ node index.js
A query for all genres along with the movies and TV shows in each genre
Great! Now we see a list of genres (albeit with fake Latin titles), along with mocked movies and TV shows for each genre. Note here on the left how we have a query for “allGenres,” and inside that query, we are asking for a list of media for each genre.
We’ve also added a query for a paginated list of movies.
movies(year: Int, page: Int): Movies
And we’ve added a Movies type to our schema:
type Movies { pages: Int results: [Movie] }
Essentially, this says that, when we make a movies query, we’ll get back an object of type “Movies” that contains a number of pages and a number of results. In our resolving function, we can return a mock number of pages from 0 to 3. And we can return 10 mocked movies in our “page” of results:
Movies: () => ({ pages: (movies) => { return casual.integer(from = 0, to = 3) }, results: () => new MockList(10) }),
Here’s how it looks when we run this query:
Running a query for movies, along with genres and trailers
So, we’ve now asked for a list of movies. We get back the number of pages in the response, along with a list of mocked movies with their genres and trailers. Now, when it comes to actually connecting this query to real data, we would take the page number passed in and our resolver would then fetch the correct “page” of data accordingly. We’ll cover resolving to actual data in a future article.
Outro
And that’s it! With a few lines of code, we’ve been able to stand up a GraphQL server that is capable of returning mocked data movies and TV shows, along with their genres and trailers. The simple setup and data mocking could enable a front-end team to begin work on movies and TV show pages for a website or app, while the server-side team is constructing the infrastructure needed to supply the actual data later.
In our next article, we’ll look at returning real data with our queries, by connecting to The Movie Database, an free, community-led API for movies and TV shows.