GraphQL
GraphQL best practice-ek
Séma tervezés, változók, nullability, pagination, limiting és éles környezetes beállítások.
Best practice-ek
1. Séma tervezés: gondolkodj a kliensek szemszögéből
A GraphQL séma ne az adatbázis struktúráját tükrözze, hanem azt, amire a klienseknek szükségük van. Az adatbázis implementációs részlet – a séma az üzleti domaint modellezi.
# ❌ Adatbázis-orientált séma
type User {
usr_id: Int!
usr_name_first: String
usr_name_last: String
usr_email: String
}
# ✅ Kliensorientált séma
type User {
id: ID!
fullName: String!
email: String!
}2. Mindig használj változókat
# ❌ String interpoláció – SOHA ne csináld ezt
query {
user(id: "123") { name }
}
# ✅ Változók – biztonságos és újrahasználható
query GetUser($id: ID!) {
user(id: $id) { name }
}3. Nullability körültekintő kezelése
A ! (non-null) jelölést csak ott használd, ahol valóban garantált, hogy az érték nem null. A túl sok ! töréspontokat okozhat a klienseken.
# Gondold végig: mikor lehet null egy mező?
type Post {
id: ID! # Mindig van ID
title: String! # Mindig van cím
publishedAt: String # Lehet null (vázlat állapotban)
author: User # Lehet null (törölt felhasználó)
}4. Pagination minden listánál
Ne adj vissza korlátlan listákat – mindig adj pagination lehetőséget:
type Query {
# ❌ Korlátlan lista
posts: [Post!]!
# ✅ Lapozható lista
posts(page: Int = 1, limit: Int = 20): PostConnection!
}5. Naming conventions
- Típusok:
PascalCase(User,BlogPost) - Mezők és argumentumok:
camelCase(firstName,publishedAt) - Enumok:
SCREAMING_SNAKE_CASE(ORDER_STATUS,USER_ROLE) - Queryök: főnév (
GetUser,ListPosts) - Mutationök: ige + főnév (
CreateUser,UpdatePost,DeleteComment)
6. Depth limiting (mélységkorlátozás)
Megakadályozza a szándékosan mélyre ágyazott, erőforrás-igényes lekérdezéseket:
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [depthLimit(5)],
});7. Query complexity limiting
const { createComplexityLimitRule } = require('graphql-validation-complexity');
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [
createComplexityLimitRule(1000, {
onCost: (cost) => console.log('Query cost:', cost),
}),
],
});8. Perzistált lekérdezések (Persisted Queries)
Éles frontend alkalmazásban a lekérdezéseket hash alapján cache-eld, hogy ne kelljen minden kérésnél elküldeni a teljes query szöveget:
import { createPersistedQueryLink } from '@apollo/client/link/persisted-queries';
import { sha256 } from 'crypto-hash';
const link = createPersistedQueryLink({ sha256 }).concat(httpLink);9. Introspection kikapcsolása éles környezetben
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
});Rövid összefoglaló
- A sémát a kliensek igényei köré tervezd, ne az adatbázis köré.
- Mindig változókat használj, soha ne égesd bele az értékeket a lekérdezésbe.
- Gondold végig a nullability-t: a
!jelölés töréspontokat okozhat. - Minden listás lekérdezésnél adj pagination lehetőséget.
- Kövesd a naming convention-eket:
PascalCasetípusokhoz,camelCasemezőkhöz. - Éles környezetben kapcsold ki az introspection-t, és vezess be mélységkorlátozást.