GraphQL is a powerful query language for APIs and a runtime for executing those queries with your existing data. It allows clients to request exactly the data they need, making APIs more flexible and efficient. Apollo Server is a popular, open-source implementation of GraphQL that integrates seamlessly with Express.js.In this chapter, we will explore how to build GraphQL APIs using Apollo Server and Express.js. Starting from the basics of GraphQL and Apollo, we will dive deep into advanced features such as query handling, mutations, subscriptions, and error handling. Every section will include easy-to-understand explanations and detailed examples to ensure complete comprehension.
GraphQL is a query language developed by Facebook that offers the following benefits:
/graphql
endpoint.Feature | GraphQL | REST |
---|---|---|
Data Fetching | Flexible queries | Fixed endpoints |
Overfetching | Avoided, as clients specify data | May fetch unnecessary data |
Schema | Strongly typed | No built-in schema |
npm init -y
npm install express graphql apollo-server-express
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const app = express();
// Placeholder middleware
app.get('/', (req, res) => {
res.send('Welcome to Express.js with Apollo Server!');
});
app.listen(4000, () => {
console.log('Server running on http://localhost:4000');
});
const { gql } = require('apollo-server-express');
// Define the schema
const typeDefs = gql`
type Query {
hello: String
}
`;
// Define the resolver
const resolvers = {
Query: {
hello: () => 'Hello, GraphQL!',
},
};
// Set up Apollo Server
const server = new ApolloServer({ typeDefs, resolvers });
server.start().then(() => {
server.applyMiddleware({ app });
app.listen(4000, () => {
console.log(`Server running at http://localhost:4000${server.graphqlPath}`);
});
});
typeDefs
defines the structure of the data.Modify the schema to fetch a list of books:
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const resolvers = {
Query: {
books: () => [
{ title: 'The Alchemist', author: 'Paulo Coelho' },
{ title: '1984', author: 'George Orwell' },
],
},
};
query {
books {
title
author
}
}
{
"data": {
"books": [
{ "title": "The Alchemist", "author": "Paulo Coelho" },
{ "title": "1984", "author": "George Orwell" }
]
}
}
Update schema with a mutation:
const books = [];
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
type Mutation {
addBook(title: String, author: String): Book
}
`;
const resolvers = {
Query: {
books: () => books,
},
Mutation: {
addBook: (_, { title, author }) => {
const newBook = { title, author };
books.push(newBook);
return newBook;
},
},
};
mutation {
addBook(title: "Sapiens", author: "Yuval Noah Harari") {
title
author
}
}
{
"data": {
"addBook": {
"title": "Sapiens",
"author": "Yuval Noah Harari"
}
}
}
const resolvers = {
Query: {
hello: () => {
throw new Error('Custom error message');
},
},
};
{
"errors": [
{
"message": "Custom error message"
}
]
}
Use Apollo’s formatError
to customize error responses:
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (err) => ({
message: err.message,
status: err.extensions.code || 500,
}),
});
npm install mongoose
Update resolvers to fetch data from MongoDB:
const mongoose = require('mongoose');
const Book = mongoose.model('Book', { title: String, author: String });
mongoose.connect('mongodb://localhost:27017/graphql_books', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const resolvers = {
Query: {
books: async () => await Book.find(),
},
Mutation: {
addBook: async (_, { title, author }) => {
const newBook = new Book({ title, author });
await newBook.save();
return newBook;
},
},
};
Apollo Server includes a GraphQL Playground at /graphql
for testing queries and mutations.
Use jest
or mocha
to write tests for your GraphQL resolvers:
test('fetches books', async () => {
const response = await query({ query: gql`{ books { title author } }` });
expect(response.data.books).toEqual(expect.any(Array));
});
Building GraphQL APIs with Apollo Server and Express.js simplifies the process of creating efficient, scalable, and flexible APIs. Setting up Apollo Server with Express.js. Handling queries, mutations, and subscriptions. Integrating a database and managing errors. By following these concepts, you can build modern APIs that meet the demands of complex applications while ensuring an exceptional developer and user experience. Happy coding !❤️