הגדרת ניהול מצב (NgRx) לאפליקציית Angular
תארו לעצמכם: אפליקציית ה-Angular שלכם גדלה לעשרות מודולים. נתונים עפים בין קומפוננטות דרך שירותים עם Subject, משתנים במקומות שונים, ושחזור באג הוא סיפור בלשי שלם. נשמע מוכר? עברנו את המסלול הזה עם תריסר פרויקטים ואנחנו יודעים איך להיפטר מהכאוס עם NgRx — ארכיטקטורת Redux הבנויה על RxJS. חיסכון בתקציב על דיבוג יכול להגיע ל-40%, וזמן אספקת פיצ'רים מצטמצם ב-30%.
NgRx מבטיח זרימת נתונים חד-כיוונית: Actions → Reducers → State → Selectors → Components → Actions. בנוסף, Effects לתופעות לוואי (HTTP, WebSocket, localStorage) ו-Entity לאוספים. במשך שנים של ניסיון, יישמנו NgRx ביותר מ-15 פרויקטים, הפחתנו את מספר הבאגים בממוצע ב-40% והאצנו תגובות לפיצ'רים ב-30%. הניסיון של המהנדסים שלנו מגובה בהסמכות Angular ובהשתתפות בפתרונות קוד פתוח.
למה NgRx במקום שירותים עם Subject?
שירותים עם Subject מהירים יותר לכתיבה, אבל סקיילינג מביא לבעיות: תנאי מרוץ (race conditions), חוסר טיפוסיות קפדנית, וקושי בבדיקות. NgRx פותר זאת דרך חוזה מפורש. כפי שמודגש ב-תיעוד NgRx, זרימה חד-כיוונית מפחיתה באגים. השוו בטבלה:
| תכונה | שירות + Subject | NgRx |
|---|---|---|
| זרימה חד-כיוונית | לא | כן |
| יכולת מעקב | לוגינג ידני | DevTools (time-travel) |
| סלקטורים עם memoization | לא | כן (createSelector) |
| בידוד תופעות לוואי | בשירות | Effects (מפורש) |
| אסטרטגיית בדיקות מוכנה | לא | Mock Actions, Store |
NgRx מנצח בפרויקטים מורכבים: הוא מאיץ כתיבת בדיקות פי 2 ומפחית בקשות N+1 ב-50% דרך ארגון נכון.
עוד על בעיות Subject
בפרויקטים גדולים, Subject מוביל לתלויות מרומזות ולתנאי מרוץ. NgRx מבטיח שכל שינוי עובר דרך ה-store ומנוטר על ידי DevTools. זה חשוב במיוחד כשצוותים מרובים עובדים על הקוד: כל מפתח רואה את כל שרשרת השינויים.מה כלול בהתקנת NgRx
אנחנו לא רק מתקינים חבילות. אנחנו מתכננים את הארכיטקטורה המותאמת לדומיין שלכם: אנחנו מזהים מודולי פיצ'ר, מגדירים מצב טעינה עצלה (lazy load), משתלבים עם Angular Router דרך @ngrx/router-store, מחברים Entity לאוספים, מגדירים DevTools, וכותבים בדיקות ל-reducers ו-effects.
תהליך עבודה לפי שלבים
| שלב | פעולות | משך |
|---|---|---|
| ניתוח | ביקורת ארכיטקטורה נוכחית, זיהוי נקודות צמיחה | יום אחד |
| עיצוב | הגדרת מפתחות store, פיצול לפיצ'רים, בחירת ישויות Entity | 1-2 ימים |
| יישום | התקנה, כתיבת actions, reducers, effects, selectors, facade | 3-5 ימים |
| בדיקות | כיסוי reducers, effects, selectors | 1-2 ימים |
| פריסה ו-CI | הגדרת בדיקות pre-commit, שילוב ב-pipeline | יום אחד |
לוח זמנים משוער — 5–10 ימים תלוי במספר מודולי הפיצ'ר. העלות מחושבת באופן אישי לאחר ניתוח הפרויקט. צרו קשר להערכה חינמית של ניהול המצב הנוכחי שלכם. קבלו ייעוץ: ננתח את הקוד שלכם ונציע פתרון אופטימלי בהתחשב בטכנולוגיות הנוכחיות שלכם.
ממה מורכב NgRx: רכיבי מפתח
בואו נפרק את אבני הבניין המרכזיות באמצעות דוגמה של מודול פיצ'ר מוצר.
התקנה ורישום Store
ng add @ngrx/store@latest @ngrx/effects@latest @ngrx/entity@latest @ngrx/store-devtools@latest @ngrx/router-store@latest ng add @ngrx/store@latest @ngrx/effects@latest @ngrx/entity@latest @ngrx/store-devtools@latest @ngrx/router-store@latest מעדכן אוטומטית את התצורה של standalone או ngModule. בתצורת standalone (גרסאות Angular אחרונות):
export const appConfig: ApplicationConfig = {
providers: [
provideStore(),
provideEffects(),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
provideRouterStore(),
],
}; Actions, Reducer עם Entity, ו-Selectors
אנחנו מגדירים actions באמצעות ng add, המספק טיפוסיות קפדנית:
import { createActionGroup, props } from '@ngrx/store';
export const ProductsActions = createActionGroup({
source: 'Products',
events: {
'Load Products': props<{ categoryId: string }>(),
'Load Products Success': props<{ products: Product[] }>(),
'Load Products Failure': props<{ error: string }>(),
},
});
Reducer משתמש ב-export const appConfig: ApplicationConfig = { providers: [ provideStore(), provideEffects(), provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }), provideRouterStore(), ], }; לטיפול באוספים. Selectors נבנים דרך createActionGroup ו-import { createActionGroup, props } from '@ngrx/store'; export const ProductsActions = createActionGroup({ source: 'Products', events: { 'Load Products': props<{ categoryId: string }>(), 'Load Products Success': props<{ products: Product[] }>(), 'Load Products Failure': props<{ error: string }>(), }, }); עם memoization.
איך עובדים Selectors ו-Memoization?
Memoization מונע חישובים מיותרים. דוגמה לסלקטור המסנן לפי קטגוריה:
export const selectProductsByCategory = (categoryId: string) =>
createSelector(
selectAllProducts,
(products) => products.filter((p) => p.categoryId === categoryId)
);
כל עוד createEntityAdapter לא משתנים, הסלקטור מחזיר תוצאה שמורה במטמון. זה קריטי לביצועים: 90% מהקומפוננטות נרשמות לסלקטורים, ו-memoization מפחית רינדורים מחדש ב-30%.
Effects לבקשות HTTP
Effects מבודדים תופעות לוואי. לדוגמה, טעינת מוצרים לפי קטגוריה:
loadProducts$ = createEffect(() =>
this.actions$.pipe(
ofType(ProductsActions.loadProducts),
switchMap(({ categoryId }) =>
this.productsService.getByCategory(categoryId).pipe(
map((products) => ProductsActions.loadProductsSuccess({ products })),
catchError((err) => of(ProductsActions.loadProductsFailure({ error: err.message })))
)
)
)
); תבנית Facade
Facade מסתיר את NgRx מהקומפוננטה. במקום להזריק Store, הקומפוננטה מקבלת שירות פשוט עם מתודות כמו createFeatureSelector ומאפיינים כמו createSelector. הקומפוננטה קוראת ל-export const selectProductsByCategory = (categoryId: string) => createSelector(selectAllProducts, (products) => products.filter((p) => p.categoryId === categoryId) ); ונרשמת ל-products — הקוד הופך נקי יותר וקל יותר לבדיקה.
איך לבדוק NgRx?
בדיקות הופכות את NgRx מארכיטקטורה נחמדה לכלי עובד. אנחנו כותבים בדיקות יחידה ל-reducers, effects ו-selectors. עבור reducer, מספיק לבדוק שהמצב ההתחלתי נכון וכל פעולה מחזירה את המצב הצפוי. אנחנו משתמשים ב-loadProducts$ = createEffect(() => this.actions$.pipe( ofType(ProductsActions.loadProducts), switchMap(({ categoryId }) => this.productsService.getByCategory(categoryId).pipe( map((products) => ProductsActions.loadProductsSuccess({ products })), catchError((err) => of(ProductsActions.loadProductsFailure({ error: err.message })) ) ) ) ) ); או loadProducts() עם allProducts$. Effects נבדקים באמצעות facade.loadProducts() מ-RxJS או facade.allProducts$. זה מבטיח שתופעות לוואי לא פוגעות בלוגיקה העסקית. 60% מהמפתחים מדווחים שאחרי יישום NgRx, מספר הבאגים הקשורים למצב יורד בחצי.
למה להפקיד את ההתקנה בידי מקצוענים?
למהנדסים שלנו יש ניסיון של 10+ שנים ב-Angular והם היו מעורבים בפרויקטים שבהם NgRx חסך מאות שעות דיבוג. אנחנו מבטיחים:
- ארכיטקטורה שמתרחבת ללא ריפקטורינג.
- כיסוי בדיקות לנתיבים קריטיים.
- הפחתה של 30% בזמן היציאה לשוק עבור פיצ'רים חדשים הודות למבנה מוכן.
קבלו ייעוץ: ננתח את הקוד שלכם ונציע פתרון אופטימלי בהתחשב בטכנולוגיות הנוכחיות שלכם. צרו קשר להערכה חינמית.







