- Creating a GraphQL Server with NodeJS
- By Aman Mittal
- The Nuggets translation Project
- Permanent link to this article: github.com/xitu/gold-m…
- Translator: Raoul1996
- Proofread by: KarthusLorin, Weibinzhu, Leviding
Hello World! In this GraphQL tutorial, you can learn how to build a GraphQL Server based on NodeJS and Experss using Apollo Server Library version 2.0.
When it comes to web requests between clients and application servers, REST, which stands for state transitions at the presentation layer, is one of the most common options for connecting the two. In the world of REST apis, it’s all about making resources accessible urls. We then perform CURD operations (New, read, update, DELETE), which are basic HTTP methods such as GET, POST, PUT, and DELETE to interact with the data.
Here is an example of a typical REST request:
/ / sample request response {https://swapi.co/api/people/ / / the above request JSON format "results" : [{" name ":" Luke Skywalker is ", "gender" : "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/", "https://swapi.co/api/films/7/" ], } { "name": "C-3PO", "gender": "n/a", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/5/", "https://swapi.co/api/films/4/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/" ], } ] }Copy the code
The response format of REST apis is not necessarily JSON, but it is the preferred method for most apis today. In addition to REST, another method for handling web requests has emerged: GraphQL. It opened source in 2015 and is changing the way developers write apis on the server side and handle them on the client side. Developed and actively maintained by Facebook.
The disadvantages of REST
GraphQL is a query language for developing apis. In contrast to REST (an architecture or “a way of doing things”), GraphQL was developed with the idea that clients only request the set of items they need from the server at a time.
In the example above, REST or some similar architecture is used. When we asked for Luke Skywalker movies from the Star Wars movies, we got a list of movies or Homeworld names, and they included different API urls that led us to the details of different JSON datasets. This is certainly an example of over fetching. The client can only make multiple requests to the server to obtain details of Luke Skywalker’s appearance in the movie and the name of his home planet.
With GraphQL, you can parse it into a single network request. Turn to the API website: https://graphql.github.io/swapi-graphql/, view, run the following query (query) and have a look.
Note: In the following example, you can ignore the behind-the-scenes workings of the GraphQL API. I’ll build your own (possibly first) GraphQL API step-by-step later in this tutorial.
{
allPeople {
edges {
node {
name
gender
homeworld {
name
}
filmConnection {
edges {
node {
title
}
}
}
}
}
}
}
Copy the code
We will get the data we need. Examples include the names of the characters, their gender, their homeworld, and the titles of the films in which they appear. Run the query above and you will get the following results:
{
"data": {
"allPeople": {
"edges": [{"node": {
"name": "Luke Skywalker"."gender": "male"."homeworld": {
"name": "Tatooine"
},
"filmConnection": {
"edges": [{"node": {
"title": "A New Hope"}}, {"node": {
"title": "The Empire Strikes Back"}}, {"node": {
"title": "Return of the Jedi"}}, {"node": {
"title": "Revenge of the Sith"}}, {"node": {
"title": "The Force Awakens"}}]}}, {"node": {
"name": "C-3PO"."gender": "n/a"."homeworld": {
"name": "Tatooine"
},
"filmConnection": {
"edges": [{"node": {
"title": "A New Hope"}}, {"node": {
"title": "The Empire Strikes Back"}}, {"node": {
"title": "Return of the Jedi"}}, {"node": {
"title": "The Phantom Menace"}}, {"node": {
"title": "Attack of the Clones"}}, {"node": {
"title": "Revenge of the Sith"}}]}}}}Copy the code
If the application’s client is correctly triggering the GraphQL URL, it only needs to make a request over the network to get the desired result. This eliminates any possibility of over-fetching or sending multiple requests.
A prerequisite for
To follow this course, all you need to do is install NodeJS and NPM on your local computer.
- Nodejs
^ 8.12.0
- npm
^ 6.4.1
GraphQL briefly
In short, GraphQL is a syntax that explains how to request data, typically used to retrieve data from a client (also known as query) or make changes to it (also known as mutation).
GraphQL has few defining features:
- It allows clients to specify exactly what data they want. This is also known as declarative data extraction.
- There are no special requirements for the network layer
- Easier to combine data from multiple sources
- It uses a strong typing system when declaring data structures in the form of schema and Query. This helps validate the query before sending the network request.
GraphQL API building blocks
The GraphQL API has four building blocks:
- schema
- query
- mutations
- resolvers
Schemas are defined on the server in the form of objects. Each object corresponds to a data type, making it easy to query them. Such as:
type User {
id: ID!
name: String
age: Int
}
Copy the code
The schema above defines what a user object looks like. Where the required field ID is used! Symbol identifier. It also contains other fields, such as name of type string and age of type Integer. This also validates the schema when querying the data.
Queries are the methods you use to make requests to the GraphQL API. For example, in our example above, as we did when we fetched Star Wars-related data. To simplify things, if you’re querying in GraphQL, you’re querying for a specific field of an object. For example, using the same API above, we can get the names of all the characters in Star Wars. You can see the difference below, with queries on the left and results on the right. On the right-hand side is the image.
The advantage of using GraphQL queries is that they can be nested to the depth you want. This is difficult to do in REST apis. Operations become much more complex (in REST apis).
Here is an example of a more complex nested query:
Mutations: In the REST architecture, to modify data, we either use POST to add data, or PUT to update data for existing fields. In GraphQL, the overall concept is similar. You can send a Query to perform a write on the server. But. This form of query is called Mutation.
Resolvers are the link between schema and data. They provide functionality that you can use to interact with the database through different operations.
In this tutorial, you will learn to use the artifacts we just learnedNodejsBuild the GraphQL server.
Hello World! Using GraphQL
Now let’s write our first GraphQL server. In this tutorial, we will use Apollo Server. We needed to install three packages for Apollo Server to use the existing Express application as middleware. Apollo Server’s advantage is that it can be used with several popular Frameworks for Node.js: Express, Koa, and Hapi. Apollo itself is library-neutral, so it can connect to many third-party libraries in both client and server applications.
Open your terminal to install the following dependencies:
Create an empty folder first
mkdir apollo-express-demo
Then initialize
npm init -y
Install required dependencies
npm install --save graphql apollo-server-express express
Copy the code
Let’s take a quick look at what these dependencies do.
graphql
Is a support library, and is a required module in our case- Add to an existing application
apollp-server-express
Is the corresponding HTTP server support package express
Is the Web framework for Nodejs
You can see in the figure below that I installed all the dependencies without any errors.
At the root of your project, create a new file named index.js that contains the following code.
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const typeDefs = gql` type Query { hello: String } `;
const resolvers = {
Query: {
hello: (a)= > 'Hello world! '}};const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000}, () = >console.log('🚀 Server ready at http://localhost:4000${server.graphqlPath}`));Copy the code
This is the starting point of our server file. At first we only needed the Express module. GQL is a template literal tag used to write GraphQL Schema as a type. Schema consists of type definitions and enforces the inclusion of a Query type for reading data. It can also contain fields and nested fields that represent other data fields. In our example above, we defined typeDefs to write graphQL’s schema.
Then the Resolvers came into view. The Resolver is used to return field data from the schema. In our example, we define a resolver that maps the function hello() to the implementation of our schema. Next, we create a server that uses the ApolloServer class to instantiate and start the server. Since we are using Express, we need to integrate the ApolloServer class. Add middleware to Apollo Server by passing it through applyMiddleware() as an app. The app here is an instance of Express and represents an existing application.
Finally, we use the app.listen() provided by the Express module to boot the server. To run the server, simply open Terminal and run the command node index.js. Now, from the browser window to access the url: http://localhost:4000/graphql to see the operation.
Apollo Server sets up GraphQL Playground for you to quickly start running Query and exploring schema, as shown below.
To run a Query, edit the left margin and type the following query. Then press the â–¶ (Play) button in the middle.
The schema card on the right describes the data type for which we are querying Hello. This comes directly from typeDefs defined in our server.
Look! You just created your first GraphQL server. Now let’s expand our understanding of the real world.
Build the API using GraphQL
So far we have sorted out all the necessary modules and the necessary terms that accompany them. In this section, we will use Apollo Server to create a small Star Wars API for our demo. You might have guessed that Apollo Server is a library that helps you connect GraphQL Schema to HTTP Server using Nodejs. It is not limited to a particular Node framework. For example, we used ExpressJS in the previous section. Apollo Server supports Koa, Restify, Hapi, and Lambda. For our API, we continue to use Express.
Compile using Babel
If you want to start at the beginning, please continue. From Hello World! The With GraphQL section installs all libraries. Here are all the dependencies we installed in the previous section:
"dependencies": {
"apollo-server-express": "^ 2.1.0." "."express": "^ 4.16.4"."graphql": "^ 14.0.2"
}
Copy the code
I’ll use the same project and the same file index.js to boot the server. But before we build our API, I want to show you how to use ES6 Modules in our demo project. They already support ES6 features for using front-end libraries like React and Angular. Statements such as import and export default. Nodejs version 8.x.x solves this problem. All we need is a transpiler to let us write JavaScript using ES6 features. You can definitely skip this step and use the old require() statement.
So what is a converter?
Converter (TranspilerAlso known as a source-to-source compiler, it reads source code written in one programming language and translates it into equivalent code in another language.
In the case of Nodejs, we won’t switch programming languages, but rather use new features of languages not supported by my current LTS version of Node. I will install the Babel compiler and enable it in our project through the following configuration process.
First, you need to install some dependencies, remember to use the -d argument. Because we only use these dependencies in our development environment.
npm install -D babel-cli babel-preset-env babel-watch
Copy the code
Once you have successfully installed them, add a.babelrc file to the root of your project and add the following configuration:
{
"presets": [env]
}
Copy the code
The last step in the configuration process is to add a dev script to package.json. Once changes are made, the Babel compiler runs automatically. This is done by Babel-Watch. It is also responsible for restarting the Nodejs web server.
"scripts": {
"dev": "babel-watch index.js"
}
Copy the code
To see it in action, add the following code to index.js to see if everything works.
import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Babel Working! '));
app.listen({ port: 4000}, () = >console.log('🚀 Server ready at http://localhost:4000));Copy the code
Type NPM run dev in the terminal and, unsurprisingly, you should see the following:
You can also visit http://localhost:4000/ in your browser to see how it works.
Add the Schema
We need a schema to launch our GraphQL API. Let’s create a new file named API /schema.js in the API directory. Add the following schema.
import { gql } from 'apollo-server-express';
const typeDefs = gql` type Person { id: Int name: String gender: String homeworld: String } type Query { allPeople: [Person] person(id: Int!) : Person } `;
export default typeDefs;
Copy the code
Our schema contains two queries in total. The first one is allPeople, which allows us to list all the people in the API. The second query person retrieves a person using their ID. Both types of queries rely on a custom type called the Person object, which contains four properties.
Add a Resolver
We’ve already seen the importance of resolver. It is based on a simple mechanism to disassociate schema and data. Resolver is the logic and function that contains query or mutation. They are then used to retrieve the data and return it on relevant requests.
If you built a server before using Express, you can think of resolver as a controller, where each controller is built for a specific route. Since we don’t use the database behind the server, we have to provide some virtual data to simulate our API.
Create a new file called resolvers.js and add the following files.
const defaultData = [
{
id: 1.name: 'Luke SkyWaler'.gender: 'male'.homeworld: 'Tattoine'
},
{
id: 2.name: 'C-3PO'.gender: 'bot'.homeworld: 'Tattoine'}];const resolvers = {
Query: {
allPeople: (a)= > {
return defaultData;
},
person: (root, { id }) = > {
return defaultData.filter(character= > {
return(character.id = id); }) [0]; }}};export default resolvers;
Copy the code
First, we define the defaultData array, which contains the details of the two characters in Star Wars. According to our schema, both objects in the array have four properties. Next up is our Resolvers object, which contains two functions. Here you can use allPeople() to retrieve all the data in the defaultData array. The person() arrow function uses the parameter ID to retrieve the Person object with the request ID. This is already defined in our query.
You must export resolver and Schema objects to use them with Apollo Server middleware.
Implementation server
Now that we’ve defined the schema and resolver, we’ll implement the server in the index.js file. First import Apollo-server from Apollo-server-Express. We also need to import our Schema and resolvers objects from the API/folder. The GraphQL API is then instantiated using the GraphQL middleware in the Apollo Server Express library.
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import typeDefs from './api/schema';
import resolvers from './api/resolvers';
const app = express();
const PORT = 4000;
const SERVER = new ApolloServer({
typeDefs,
resolvers
});
SERVER.applyMiddleware({ app });
app.listen(PORT, () =>
console.log('🚀 GraphQL playground is running at http://localhost:4000'));Copy the code
Finally, we use app.listen() to boot our Express server. You can now run the server by executing the command NPM run dev from the terminal. After the server node is started, a success message is displayed indicating that the server is started.
Now to test our GraphQL API, goto http://localhost:4000/graphql URL in the browser window and run the following query.
{
allPeople {
id
name
gender
homeworld
}
}
Copy the code
Click the Play button and you will see the familiar results in the right section, as shown below.
All is well, because our query type, allPeople, has custom business logic that retrieves all data using resolver (in our case, mock data that we provide as data in resolvers.js). To get a single person object, try running another query like this. Remember, you must provide an ID.
{
person(id: 1) {
name
homeworld
}
}
Copy the code
Run the query above, and in the result, you can get the value of each field/attribute you get for the query. Your result will look something like the following.
Perfect! I’m sure you know how to create a GraphQL Query and run it. The Apollo Server library is very powerful. It allows us to edit our playground. Suppose we wanted to edit the theme of our playground? All we need to do is provide an option when creating an instance of ApolloServer, in our case SERVER.
const SERVER = new ApolloServer({
typeDefs,
resolvers,
playground: {
settings: {
'editor.theme': 'light'}}});Copy the code
The playground property has many functions, such as defining the default endpoint for playground to change the theme. You can even enable playground in production mode. More configuration items can be found in the official Apollo Server documentation, here.
After changing the theme we get the following result.
conclusion
If you completed the tutorial step by step, congratulations! 🎉
You’ve learned how to configure the Express server using the Apollo library to set up your own GraphQL API. Apollo Server is an open source project that is one of the most stable solutions for creating the GraphQL API for full-stack applications. He also supports client-side React, Vue, Angular, Meteor, and Ember, as well as Native mobile development using Swift and Java, out of the box. More information on this can be found here.
See the full code for the tutorial in this Github repository at 👇
- amandeepmittal/apollo-express-demo: Apollo Server Express. Contribute to amandeepmittal/apollo-express-demo development by creating an account on Github.
Start a new Node.js project, or find a Node developer?
Crowdbotics helps companies build cool stuff with Node (among other things). If you have a Node project and you need other developer resources, please leave us a comment. Crowbotics can help you estimate build times for a given product’s functional specs and provide dedicated Node developers to suit your needs. If you’re building with Node, check out Crowdbotics.
Thanks to William Wickey for his editorial help.
If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.
The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.