0

Tại sao mình chuyển từ REST sang GraphQL (và khi nào không nên)

Mình dùng REST 5 năm trước khi thử GraphQL. Đây là những gì mình học được — cả ưu và nhược.

Vấn đề với REST

Over-fetching

GET /api/users/123
→ Trả về 30 fields, frontend chỉ cần name + avatar

Under-fetching

GET /api/posts/456        → Lấy bài viết
GET /api/users/123        → Lấy tác giả
GET /api/posts/456/comments → Lấy comments
→ 3 requests cho 1 trang

Version hell

/api/v1/users
/api/v2/users  (thêm field mới)
/api/v3/users  (đổi format)

GraphQL giải quyết thế nào

query {
    post(id: "456") {
            title
                    content
                            author {
                                        name
                                                    avatar
                                                            }
                                                                    comments(first: 10) {
                                                                                text
                                                                                            createdAt
                                                                                                    }
                                                                                                        }
                                                                                                        }
                                                                                                        ```
                                                                                                        
                                                                                                        1 request, ly đúng data cn. Không over-fetch, không under-fetch.
                                                                                                        
                                                                                                        ## Setup (Node.js + Apollo)
                                                                                                        
                                                                                                        ```javascript
                                                                                                        const { ApolloServer } = require('@apollo/server');
                                                                                                        
                                                                                                        const typeDefs = `
                                                                                                            type User {
                                                                                                                    id: ID!
                                                                                                                            name: String!
                                                                                                                                    email: String!
                                                                                                                                            posts: [Post!]!
                                                                                                                                                }
                                                                                                                                                
                                                                                                                                                    type Post {
                                                                                                                                                            id: ID!
                                                                                                                                                                    title: String!
                                                                                                                                                                            author: User!
                                                                                                                                                                                }
                                                                                                                                                                                
                                                                                                                                                                                    type Query {
                                                                                                                                                                                            user(id: ID!): User
                                                                                                                                                                                                    posts(limit: Int): [Post!]!
                                                                                                                                                                                                        }
                                                                                                                                                                                                        
                                                                                                                                                                                                            type Mutation {
                                                                                                                                                                                                                    createPost(title: String!, content: String!): Post!
                                                                                                                                                                                                                        }
                                                                                                                                                                                                                        `;
                                                                                                                                                                                                                        
                                                                                                                                                                                                                        const resolvers = {
                                                                                                                                                                                                                            Query: {
                                                                                                                                                                                                                                    user: (_, { id }) => getUserById(id),
                                                                                                                                                                                                                                            posts: (_, { limit }) => getPosts(limit),
                                                                                                                                                                                                                                                },
                                                                                                                                                                                                                                                    User: {
                                                                                                                                                                                                                                                            posts: (user) => getPostsByUserId(user.id),
                                                                                                                                                                                                                                                                },
                                                                                                                                                                                                                                                                };
                                                                                                                                                                                                                                                                ```
                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                ## Khi nào GraphQL tốt hơn REST?
                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                ✅ **Dùng GraphQL khi:**
                                                                                                                                                                                                                                                                - Frontend cn flexibility (mobile vs web cn data khác nhau)
                                                                                                                                                                                                                                                                - Quan hdata phc tp (social network, e-commerce)
                                                                                                                                                                                                                                                                - Nhiu team cùng dùng API
                                                                                                                                                                                                                                                                - Tránh over-fetching quan trng (mobile, bandwidth thp)
                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                ❌ **GiREST khi:**
                                                                                                                                                                                                                                                                - API đơn gin, ít endpoints
                                                                                                                                                                                                                                                                - File upload (GraphQL htrnhưng phc tp)
                                                                                                                                                                                                                                                                - Caching đơn gin (REST dùng HTTP cache, GraphQL phi dùng client cache)
                                                                                                                                                                                                                                                                - Team nh, product đơn gin
                                                                                                                                                                                                                                                                - Microservices giao tiếp ni b## Nhược điểm GraphQL (thật sự)
                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                ### 1. N+1 Query Problem
                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                ```graphql
                                                                                                                                                                                                                                                                query {
                                                                                                                                                                                                                                                                    posts {      # 1 query
                                                                                                                                                                                                                                                                            author { # N queries (mỗi post 1 query lấy author)
                                                                                                                                                                                                                                                                                        name
                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                    ```
                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                    Fix: DataLoader
                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                    ```javascript
                                                                                                                                                                                                                                                                                                    const DataLoader = require('dataloader');
                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                    const userLoader = new DataLoader(async (ids) => {
                                                                                                                                                                                                                                                                                                        const users = await User.findAll({ where: { id: ids } });
                                                                                                                                                                                                                                                                                                            return ids.map(id => users.find(u => u.id === id));
                                                                                                                                                                                                                                                                                                            });
                                                                                                                                                                                                                                                                                                            ```
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            ### 2. Caching khó hơn
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            REST: `GET /users/123` → HTTP cache tnhiên.
                                                                                                                                                                                                                                                                                                            GraphQL: Mi request đều POSTphi dùng client-side cache (Apollo Client).
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            ### 3. Error handling phức tạp
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            REST: HTTP status code nói rõ li gì.
                                                                                                                                                                                                                                                                                                            GraphQL: Luôn tr200, li nm trong `errors` array.
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            ## Kết luận
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            GraphQL không thay thế REST. Nó gii quyết problems khác. Chn tool phù hp vi problem ca bn.
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            ---
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            Bn dùng REST hay GraphQL? Hay chai?

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí