אינטגרציה של KeystoneJS עם הפרונטאנד דרך GraphQL API
בעיה: KeystoneJS מייצר GraphQL API, אבל אינטגרציה עם הפרונטאנד מובילה לעיתים קרובות לאי-התאמת טיפוסים — הפרונטאנד משתמש בשדות שלא קיימים בסכמה או עושה טעויות במוטציות. פגינציה באמצעות take/skip ללא קאשינג מתאים גורמת לרשומות כפולות, ואימות דורש הגדרת מידלוור זהירה. אנחנו, צוות עם ניסיון של למעלה מ-5 שנים עם KeystoneJS, הקמנו את הסטאק הזה עבור 30+ פרויקטים, צמצמנו באגים ב-90% והאצנו שחרורים פי שניים. אינטגרציה טיפוסית על Next.js + Apollo Client עם codegen אורכת 3–5 ימים במפתח מלא. קבלו אודיט של סכמת KeystoneJS שלכם — נמצא צווארי בקבוק ונציע תוכנית אינטגרציה.
מה KeystoneJS מייצר
עבור כל רשימה (List), לדוגמה Post, נוצרות שאילתות ומוטציות סטנדרטיות (תיעוד GraphQL API של KeystoneJS):
-
post(where: PostWhereUniqueInput!): Post -
posts(where: PostWhereInput, orderBy: [...], take: Int, skip: Int): [Post!] -
postsCount(where: PostWhereInput): Int -
createPost(data: PostCreateInput!): Post -
createPosts(data: [PostCreateInput!]!): [Post] -
updatePost(where: PostWhereUniqueInput!, data: PostUpdateInput!): Post -
deletePost(where: PostWhereUniqueInput!): Post
זה מבטל קידוד חוזר. עם זאת, ללא codegen, קל לטעות בשם שדה או לשכוח לבחור קשרים מקוננים (בעיית N+1), מה שמגדיל את עלות הפיתוח ב-30-50%.
איך להגדיר Apollo Client עבור KeystoneJS
Apollo Client הוא לקוח ה-GraphQL הפופולרי ביותר עבור React. ההתקנה כוללת קישור HTTP לנקודת הקצה, מידלוור אימות וטיפול בשגיאות. הנה דוגמה עבור Next.js עם סשנים מבוססי עוגיות (תיעוד Apollo Client):
// lib/apollo.ts
import { ApolloClient, InMemoryCache, createHttpLink, from } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error';
const httpLink = createHttpLink({
uri: process.env.NEXT_PUBLIC_KEYSTONE_URL + '/api/graphql',
credentials: 'include',
});
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
authorization: getToken() ? `Bearer ${getToken()}` : '',
},
}));
const errorLink = onError(({ graphQLErrors }) => {
if (graphQLErrors?.some(e => e.extensions?.code === 'UNAUTHENTICATED')) {
window.location.href = '/login';
}
});
export const apolloClient = new ApolloClient({
link: from([errorLink, authLink, httpLink]),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
posts: {
keyArgs: ['where', 'orderBy'],
merge: (existing = [], incoming) => [...existing, ...incoming],
},
},
},
},
}),
});
הבלוק הזה משלב אימות ופגינציה. בהשוואה ל-fetch ישיר, Apollo Client מספק קאשינג אוטומטי, פסילה והוקים נוחים — מצמצם קוד ב-40%.
למה Codegen מאיץ פיתוח פי 3
GraphQL Code Generator יוצר טיפוסי TypeScript והוקים מהסכמה שלכם. ההגדרה פשוטה:
---
# codegen.yml
schema: http://localhost:3000/api/graphql
documents: "src/**/*.graphql"
generates:
src/generated/graphql.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-apollo
דוגמת שאילתה:
# src/queries/posts.graphql
query GetPosts($where: PostWhereInput, $take: Int, $skip: Int) {
posts(where: $where, take: $take, skip: $skip, orderBy: [{ publishedAt: desc }]) {
id
title
slug
publishedAt
status
author {
id
name
}
tags {
id
name
}
}
postsCount(where: $where)
}לאחר היצירה, מקבלים הוקים מוכנים לשימוש עם השלמה אוטומטית. זה מבטל לחלוטין שגיאות בשמות שדות ובשאילתות, וחוסך עד 60% מזמן הדיבאג.
איך להשתמש ב-Next.js Server Components
ב-Server Components, שאילתות מבוצעות בצד השרת. אנחנו משתמשים בלקוח Apollo לשרת:
// app/blog/page.tsx
import { getClient } from '@/lib/apollo-server';
import { GetPostsDocument } from '@/generated/graphql';
export default async function BlogPage({ searchParams }) {
const page = Number(searchParams.page) || 1;
const { data } = await getClient().query({
query: GetPostsDocument,
variables: {
where: { status: { equals: 'published' } },
take: 10,
skip: (page - 1) * 10
},
});
return <PostGrid posts={data.posts} total={data.postsCount} page={page} />;
} מוטציות ב-Client Components
לפעולות כתיבה, אנחנו משתמשים ברכיבי לקוח:
'use client';
import { useMutation } from '@apollo/client';
import { CreatePostDocument } from '@/generated/graphql';
export function NewPostForm() {
const [createPost, { loading, error }] = useMutation(CreatePostDocument, {
update(cache, { data }) {
cache.evict({ fieldName: 'posts' });
},
});
const handleSubmit = async (formData) => {
const { data } = await createPost({
variables: {
data: {
title: formData.title,
slug: formData.slug,
content: { document: formData.content },
author: { connect: { id: currentUserId } },
status: 'draft',
},
},
});
router.push(`/admin/posts/${data?.createPost?.id}`);
};
} השוואה: Apollo Client מול fetch
| קריטריון | Apollo Client | fetch + קאשינג ידני |
|---|---|---|
| קאשינג | אוטומטי (InMemoryCache) | ידני (React Query/SWR) |
| טיפוסים | אינטגרציה עם codegen | טיפוסים נפרדים |
| אימות | מידלוור | קוד נוסף |
| פגינציה | keyArgs, merge | לוגיקה ידנית |
| גודל באנדל | ~30 kB | ~0 kB (אבל + React Query ~11 kB) |
שימוש ב-Apollo Client מקצר את זמן הפיתוח ב-2–3 ימים בהשוואה ל-fetch גולמי, וחוסך משמעותית בתקציב הפרויקט.
איך להימנע מטעויות אינטגרציה נפוצות
| טעות | השלכה | פתרון |
|---|---|---|
| ללא codegen | שגיאות בשמות שדות, דיבאג ארוך | הגדרת codegen בתחילת הפרויקט |
| הגדרת קאש שגויה | רשומות כפולות בפגינציה | הגדרת מדיניות merge באמצעות keyArgs |
| התעלמות מאימות | בקשות לא מורשות, דליפות מידע | הוספת מידלוור עם בדיקת טוקן |
| שימוש ב-Client Components לכל השאילתות | באנדל גדול יותר, טעינה איטית | העברת שאילתות קריאה ל-Server Components |
| מפתח קאש שגוי לפגינציה | נתונים נמחקים עם מיון שונה | שימוש ב-keyArgs עם where ו-orderBy |
תוכנית אינטגרציה שלב אחר שלב
- ניתוח סכמת KeystoneJS — בדיקת רשימות, קשרים, הרשאות והוקים.
- הגדרת Apollo Client — יצירת מופעי שרת ולקוח עם מידלוור.
- הגדרת codegen — יצירת טיפוסי TypeScript והוקים.
- יישום שאילתות — רשימה נבחרת, פגינציה, מיון.
- יישום מוטציות — CRUD לממשקי ניהול.
- אימות — סשן או JWT, אבטחת נתיבים.
- בדיקות — בדיקות יחידה עם Apollo MockedProvider.
מה כולל שירות האינטגרציה
- אודיט של הגדרות KeystoneJS הקיימות.
- הגדרת Apollo Client עם אופטימיזציית קאש.
- יצירת קוד באמצעות GraphQL Code Generator.
- יישום שאילתות ומוטציות עבור רשימות קריטיות.
- אינטגרציית אימות (סשן/JWT).
- תיעוד על שימוש בהוקים שנוצרו.
- שבועיים של תמיכה לאחר המסירה.
אנחנו מבטיחים שכל השאילתות עוברות בדיקת קוד ובדיקות. צרו קשר לייעוץ כדי שנוכל לנתח את הסכמה הנוכחית שלכם ולהציע את תוכנית האינטגרציה הטובה ביותר.
הניסיון של הצוות שלנו
אנחנו עובדים עם KeystoneJS ו-GraphQL למעלה מ-5 שנים. בתקופה זו השלמנו 30+ פרויקטים, כולל אינטגרציה עם חנויות מסחר אלקטרוני, פלטפורמות SaaS ופורטלים ארגוניים. NPS ממוצע — 9.2. חיסכון בתקציב הלקוח הגיע עד 50% בהשוואה לפתרונות חלופיים. פנו אלינו כדי לדון בפרויקט שלכם.







