GraphQL is a query language and runtime for APIs developed by Facebook. It provides a more efficient, powerful, and flexible alternative to REST by allowing clients to request exactly the data they need. This document explains how to build a GraphQL API, covering schema design, resolvers, queries, mutations, and tools using JavaScript (Node.js) as an example.
The most popular way to build a GraphQL API in Node.js is by using the Apollo Server library.
// Step 1: Install dependencies
npm install apollo-server graphql
// Step 2: Create a simple server
const { ApolloServer, gql } = require('apollo-server');
// Define the schema
const typeDefs = gql`
type Query {
hello: String
}
`;
// Define the resolver
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
};
// Create the server instance
const server = new ApolloServer({ typeDefs, resolvers });
// Start the server
server.listen().then(({ url }) => {
console.log(`π Server ready at ${url}`);
});
The schema defines the types and operations available in the API. It is strongly typed and follows the SDL (Schema Definition Language).
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
In this example, we define a Book type and a query called books that returns a list of Book objects.
Resolvers are functions that define how to fetch the data for each type and field in the schema.
const books = [
{ title: '1984', author: 'George Orwell' },
{ title: 'Brave New World', author: 'Aldous Huxley' },
];
const resolvers = {
Query: {
books: () => books,
},
};
GraphQL APIs are typically queried using a single endpoint (e.g., /graphql) and allow clients to specify the exact fields they need.
{
books {
title
author
}
}
{
"data": {
"books": [
{ "title": "1984", "author": "George Orwell" },
{ "title": "Brave New World", "author": "Aldous Huxley" }
]
}
}
Mutations allow clients to modify data (create, update, delete).
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: "The Hobbit", author: "J.R.R. Tolkien") {
title
author
}
}
For more complex data structures, use input types in mutations.
input BookInput {
title: String!
author: String!
}
type Mutation {
addBook(input: BookInput): Book
}
You can define nested types and handle relationships through resolvers.
type Author {
name: String
books: [Book]
}
type Book {
title: String
author: Author
}
Resolvers can then manage how relationships are resolved:
const resolvers = {
Book: {
author: (book) => authors.find(a => a.id === book.authorId),
},
};
Use middleware to check headers for a JWT or session token before passing context to resolvers.
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const token = req.headers.authorization || "";
const user = getUserFromToken(token);
return { user };
},
});
Check permissions inside resolvers:
Mutation: {
addBook: (parent, args, context) => {
if (!context.user) throw new Error("Not authorized");
// Proceed with adding book
}
}
GraphQL supports real-time communication via subscriptions and WebSockets.
type Subscription {
bookAdded: Book
}
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();
Mutation: {
addBook: (parent, args) => {
const newBook = { ...args };
books.push(newBook);
pubsub.publish('BOOK_ADDED', { bookAdded: newBook });
return newBook;
}
},
Subscription: {
bookAdded: {
subscribe: () => pubsub.asyncIterator(['BOOK_ADDED']),
},
}
| Aspect | GraphQL | REST |
|---|---|---|
| Endpoint | Single | Multiple |
| Data Fetching | Flexible, client-driven | Fixed, server-driven |
| Versioning | Not needed (schema evolves) | Required (v1, v2, etc.) |
| Real-time | Supported via subscriptions | Requires additional setup (e.g., WebSocket) |
GraphQL is a powerful and flexible API technology that empowers developers to design efficient, scalable, and strongly-typed data interactions. Whether you're building a monolith or microservices, GraphQL can significantly simplify client-server communication, reduce over-fetching, and support modern frontend demands. By understanding its core componentsβschemas, resolvers, queries, mutations, and subscriptionsβyou can effectively build robust APIs tailored to real-world applications.
A function passed as an argument and executed later.
Runs multiple instances to utilize multi-core systems.
Reusable blocks of code, exported and imported using require() or import.
nextTick() executes before setImmediate() in the event loop.
Starts a server and listens on specified port.
Node Package Manager β installs, manages, and shares JavaScript packages.
A minimal and flexible web application framework for Node.js.
A stream handles reading or writing data continuously.
It processes asynchronous callbacks and non-blocking I/O operations efficiently.
Node.js is a JavaScript runtime built on Chrome's V8 engine for server-side scripting.
An object representing the eventual completion or failure of an asynchronous operation.
require is CommonJS; import is ES6 syntax (requires transpilation or newer versions).
Use module.exports or exports.functionName.
Variables stored outside the code for configuration, accessed using process.env.
MongoDB, often used with Mongoose for schema management.
Describes project details and manages dependencies and scripts.
Synchronous blocks execution; asynchronous runs in background without blocking.
Allows or restricts resources shared between different origins.
Use try-catch, error events, or middleware for error handling.
Provides file system-related operations like read, write, delete.
Using event-driven architecture and non-blocking I/O.
Functions in Express that execute during request-response cycle.
A set of routes or endpoints to interact with server logic or databases.
Yes, it's single-threaded but handles concurrency using the event loop and asynchronous callbacks.
Middleware to parse incoming request bodies, like JSON or form data.
Copyrights © 2024 letsupdateskills All rights reserved