Introduction to GraphQL and Its Advantages
\n\nGraphQL is a query language and runtime for APIs, developed by Facebook. Unlike REST, where you receive fixed data structures, GraphQL allows the client to request only what it needs. This makes APIs more flexible and efficient.
\n\nIn this step-by-step tutorial, we will create a full-fledged GraphQL API with JavaScript using Node.js. You will learn how to set up a server, define schemas, and handle queries and mutations. By the end of the article, you will have a working API ready for integration into any project.
\n\n1. Project Setup and Dependency Installation
\n\nFirst, let's create a new Node.js project and install the necessary packages. We will use apollo-server — a popular library for building GraphQL servers.
Step 1: Project Initialization
\nmkdir graphql-tutorial\ncd graphql-tutorial\nnpm init -y\n\nStep 2: Installing Apollo Server and GraphQL
\nnpm install apollo-server graphql\n\nAfter installation, create the main file index.js, where our server will reside.
2. Creating a Basic GraphQL Server
\n\nNow let's write a minimal server that will accept requests and return responses. To do this, we will define a schema and resolvers.
\n\nStep 1: Defining the Data Type
\nLet's create a simple Book type with fields id, title, and author.
const { ApolloServer, gql } = require('apollo-server');\n\n// GraphQL Schema\nconst typeDefs = gql`\n type Book {\n id: ID!\n title: String!\n author: String!\n }\n\n type Query {\n books: [Book]\n book(id: ID!): Book\n }\n`;\n\n// Sample data (in a real project — a database)\nconst books = [\n { id: '1', title: 'War and Peace', author: 'Leo Tolstoy' },\n { id: '2', title: 'Crime and Punishment', author: 'Fyodor Dostoevsky' },\n { id: '3', title: 'The Master and Margarita', author: 'Mikhail Bulgakov' }\n];\n\n// Resolvers — functions that return data\nconst resolvers = {\n Query: {\n books: () => books,\n book: (parent, args) => books.find(book => book.id === args.id)\n }\n};\n\n// Creating the server\nconst server = new ApolloServer({ typeDefs, resolvers });\n\n// Starting the server\nserver.listen().then(({ url }) => {\n console.log(`🚀 Server ready at: ${url}`);\n});\n\nStep 2: Running and Testing
\nRun the command node index.js and open http://localhost:4000 in your browser. You will see the GraphQL Playground — a tool for testing queries.
Try executing a simple query:
\n{\n books {\n title\n author\n }\n}\n\nThe response should contain a list of books with the specified fields.
\n\n3. Adding Mutations and Extending the Schema
\n\nNow let's add the ability to modify data through mutations. This will allow creating, updating, and deleting records.
\n\nStep 1: Defining Mutations in the Schema
\nconst typeDefs = gql`\n type Book {\n id: ID!\n title: String!\n author: String!\n }\n\n input BookInput {\n title: String!\n author: String!\n }\n\n type Query {\n books: [Book]\n book(id: ID!): Book\n }\n\n type Mutation {\n addBook(input: BookInput!): Book\n deleteBook(id: ID!): Book\n }\n`;\n\nStep 2: Implementing Resolvers for Mutations
\nconst resolvers = {\n Query: {\n books: () => books,\n book: (parent, args) => books.find(book => book.id === args.id)\n },\n Mutation: {\n addBook: (parent, args) => {\n const newBook = {\n id: String(books.length + 1),\n title: args.input.title,\n author: args.input.author\n };\n books.push(newBook);\n return newBook;\n },\n deleteBook: (parent, args) => {\n const index = books.findIndex(book => book.id