GraphQL
Gyakori hibák
Tipikus GraphQL csapdák teljesítményben, biztonságban és karbantarthatóságban.
Gyakori hibák
1. N+1 lekérdezési probléma figyelmen kívül hagyása
A leggyakoribb teljesítményprobléma. Mindig használj DataLoadert a kapcsolódó objektumok batch-elésére.
// ❌ Minden Post resolverje külön DB-lekérdezést indít
Post: {
author: (parent, _, { db }) => db.users.findById(parent.authorId),
}
// ✅ DataLoaderrel batch-elt lekérdezés
Post: {
author: (parent, _, { loaders }) => loaders.user.load(parent.authorId),
}2. A context nem kerül felhasználásra
A context a megosztott erőforrások átadásának helyes módja – ne hozz létre új DB-kapcsolatot minden resolverben.
// ❌ Új kapcsolat minden resolverben
Query: {
user: async (_, { id }) => {
const db = new Database();
return db.users.findById(id);
},
}
// ✅ Context-ből kapott kapcsolat
Query: {
user: async (_, { id }, { db }) => {
return db.users.findById(id);
},
}3. Érzékeny adatok expozálása
# ❌ Jelszó hash a sémában
type User {
id: ID!
passwordHash: String! # SOHA ne tedd elérhetővé!
}
# ✅ Csak szükséges mezők
type User {
id: ID!
name: String!
email: String!
}4. Túl nagy, monolitikus séma
Érdemes a sémát modulokra bontani és összefűzni:
// ❌ Egy hatalmas sémafájl
const typeDefs = `
# 1000 sor...
`;
// ✅ Moduláris séma
const { mergeTypeDefs, mergeResolvers } = require('@graphql-tools/merge');
const typeDefs = mergeTypeDefs([userTypeDefs, postTypeDefs, commentTypeDefs]);
const resolvers = mergeResolvers([userResolvers, postResolvers, commentResolvers]);5. Cache stratégia hiánya
A GraphQL egyetlen végpontot használ, ezért a HTTP-szintű cache nem működik úgy, mint REST-nél. Explicit cache stratégiát kell tervezni.
// Apollo Client cache stratégia beállítása
const client = new ApolloClient({
cache: new InMemoryCache({
typePolicies: {
User: {
keyFields: ['id'], // Cache kulcs
},
Post: {
keyFields: ['id'],
fields: {
comments: {
merge(existing = [], incoming) {
return [...existing, ...incoming];
},
},
},
},
},
}),
});6. Subscription memóriaszivárgás
Mindig iratkozz le a subscriptionről, ha a komponens unmountolódik:
// ❌ Nem iratkozik le
useEffect(() => {
const sub = subscribeToMore({ ... });
}, []);
// ✅ Cleanup függvénnyel
useEffect(() => {
const unsubscribe = subscribeToMore({ ... });
return () => unsubscribe();
}, []);Rövid összefoglaló
- Az N+1 probléma a leggyakoribb teljesítményprobléma – DataLoaderrel oldható meg.
- A context a helyes módja a megosztott erőforrások átadásának.
- Soha ne tedd elérhetővé az érzékeny adatokat (jelszó hash, belső ID-k) a sémában.
- Nagy projekteknél a sémát modulokra bontva kezeld.
- Tervezz explicit cache stratégiát – a HTTP cache nem működik GraphQL-nél.
- Subscription esetén mindig iratkozz le, amikor a komponens eltűnik.