What is GraphQL?
GraphQL is a query language for APIs that allows clients to request exactly the data they need, nothing more.
Basic Schema
graphql
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
users: [User!]!
posts: [Post!]!
}
type Mutation {
createUser(name: String!, email: String!): User!
createPost(title: String!, content: String!, authorId: ID!): Post!
}Setting Up with Apollo Server
javascript
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
const typeDefs = `#graphql
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User!]!
user(id: ID!): User
}
`;
const resolvers = {
Query: {
users: () => [],
user: (_, { id }) => findById(id)
}
};
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);Queries
Fetch Data
graphql
query {
users {
id
name
email
}
}
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}Mutations
Modify Data
graphql
mutation CreateUser($name: String!, $email: String!) {
createUser(name: $name, email: $email) {
id
name
email
}
}Best Practices
- 1Use specific types: Avoid overly generic types
- 2Handle errors gracefully: Return partial results when possible
- 3Use pagination: Implement cursor-based pagination
- 4Optimize resolvers: Use DataLoader to prevent N+1 queries
- 5Validate inputs: Use schema validation
Error Handling
javascript
const resolvers = {
Query: {
user: async (_, { id }, { dataSources }) => {
try {
return await dataSources.userAPI.getUserById(id);
} catch (error) {
throw new GraphQLError(error.message, {
extensions: {
code: 'USER_NOT_FOUND',
http: { status: 404 }
}
});
}
}
}
};Conclusion
GraphQL provides a flexible and efficient alternative to REST. Use it when you need complex data fetching and real-time updates.