diff --git a/frontend/angular/readme.md b/frontend/angular/readme.md index a877b31..6d24780 100644 --- a/frontend/angular/readme.md +++ b/frontend/angular/readme.md @@ -39,6 +39,8 @@ title = input(''); #### 🚀 Solution Use Signal Inputs (`input()`). This allows Angular to precisely know *which* specific component requires an update, paving the way for Zoneless applications. +--- + ### 🚨 2. Using `@Output()` Decorator **Context:** Component Outputs #### ❌ Bad Practice @@ -54,6 +56,8 @@ save = output(); #### 🚀 Solution Use the `output()` function. It provides strict typing, better performance, and a unified API with Signal Inputs. +--- + ### 🚨 3. Two-Way Binding with `@Input()` and `@Output()` **Context:** Model Synchronization #### ❌ Bad Practice @@ -70,6 +74,8 @@ value = model(); #### 🚀 Solution Use `model()`. This creates a Signal that can be both read and written to, automatically synchronizing its state with the parent. +--- + ### 🚨 4. Structural Directives (`*ngIf`, `*ngFor`) **Context:** Template Control Flow #### ❌ Bad Practice @@ -93,6 +99,8 @@ Directives require importing `CommonModule` or `NgIf/NgFor`, increasing bundle s #### 🚀 Solution Use the built-in Control Flow (`@if`, `@for`). It is built into the compiler, requires no imports, supports improved type-narrowing, and runs faster. +--- + ### 🚨 5. Subscribing in Components (Logic in `ngOnInit`) **Context:** Data Fetching #### ❌ Bad Practice @@ -111,6 +119,8 @@ data = toSignal(this.service.getData()); #### 🚀 Solution Use `toSignal()` to convert an Observable into a Signal. This automatically manages the subscription and integrates the data stream into the reactivity system. +--- + ### 🚨 6. `BehaviorSubject` for Local State **Context:** Component State Management #### ❌ Bad Practice @@ -129,6 +139,8 @@ count = signal(0); #### 🚀 Solution Use `signal()` for local state. It is a primitive designed specifically for synchronizing UI and data. +--- + ### 🚨 7. Derived State with `ngOnChanges` **Context:** Reactivity #### ❌ Bad Practice @@ -148,6 +160,8 @@ fullName = computed(() => `${this.firstName()} ${this.lastName()}`); #### 🚀 Solution Use `computed()`. The signal is recalculated *only* when its dependencies change, and the result is memoized (cached). +--- + ### 🚨 8. Constructor Dependency Injection **Context:** DI Pattern #### ❌ Bad Practice @@ -164,6 +178,8 @@ private store = inject(Store); #### 🚀 Solution Use the `inject()` function. It operates in the initialization context (fields or constructor), is type-safe, and does not require `super()` during inheritance. +--- + ### 🚨 9. Modules (`NgModule`) **Context:** App Architecture #### ❌ Bad Practice @@ -186,6 +202,8 @@ Modules create an unnecessary level of indirection. Components become dependent #### 🚀 Solution Use Standalone Components. This is the Angular v14+ standard that makes components self-sufficient and tree-shakable. +--- + ### 🚨 10. String-based Route Loading **Context:** Lazy Loading Routing #### ❌ Bad Practice @@ -201,6 +219,8 @@ loadComponent: () => import('./user.component').then(c => c.UserComponent) #### 🚀 Solution Use `loadComponent` for routing to Standalone components. This ensures minimal chunk size. +--- + ### 🚨 11. Heavy Logic in Templates **Context:** Template Performance #### ❌ Bad Practice @@ -219,6 +239,8 @@ total = computed(() => this.calculateTotal(this.items())); #### 🚀 Solution Extract logic into `computed()` signals or Pure Pipes. They are only executed when input data changes. +--- + ### 🚨 12. Manual Subscription Management (`takeUntil`) **Context:** RxJS Memory Leaks #### ❌ Bad Practice @@ -236,6 +258,8 @@ stream$.pipe(takeUntilDestroyed()).subscribe(); #### 🚀 Solution Use the `takeUntilDestroyed()` operator. It automatically unsubscribes upon context destruction (component, directive, service). +--- + ### 🚨 13. Deeply Nested Components Passing Data **Context:** Prop Drilling #### ❌ Bad Practice @@ -257,6 +281,8 @@ theme = inject(ThemeService).theme; #### 🚀 Solution Use Signal Stores or services for state sharing, or the new `input()` API with context inheritance (in the future). +--- + ### 🚨 14. Accessing DOM directly (`ElementRef.nativeElement`) **Context:** Security & Abstraction #### ❌ Bad Practice @@ -273,6 +299,8 @@ Direct DOM access breaks abstraction (doesn't work in SSR/Web Workers) and opens #### 🚀 Solution Use style/class bindings or `Renderer2`. For direct manipulations, consider directives. +--- + ### 🚨 15. Zone.js overhead **Context:** Change Detection #### ❌ Bad Practice @@ -289,6 +317,7 @@ bootstrapApplication(App, { Migrate to Zoneless mode. Use Signals to notify Angular when a re-render is needed. --- +[⬆️ Back to Top](#) ## 📚 Specialized Topics @@ -296,5 +325,6 @@ For further reading, please refer to the following specialized guides: - [🏗 Architecture & Dependency Injection](./architecture.md) - [🚀 Advanced Performance](./advanced-performance.md) +- [📦 State Management](./state-management.md) - [📝 Data & Forms](./data-forms.md) - [🧠 Expert/Niche Topics](./expert-niche.md) diff --git a/frontend/angular/state-management.md b/frontend/angular/state-management.md new file mode 100644 index 0000000..73691cf --- /dev/null +++ b/frontend/angular/state-management.md @@ -0,0 +1,164 @@ +--- +description: Vibe coding guidelines and architectural constraints for Angular State Management, focusing on Zoneless reactivity, Signals, and modern functional APIs. +technology: Angular +domain: frontend +level: Senior/Architect +complexity: Advanced +topic: Angular State Management +vibe_coding_ready: true +last_evolution: 2026-03-28 +version: "20" +tags: [state-management, signals, zoneless, angular, best-practices, clean-code, scalable-code] +ai_role: Senior Angular State Management Expert +--- + +> 📦 [best-practise](../../README.md) / 🖥️ [frontend](../readme.md) / 🅰️ [angular](./readme.md) + +# 📦 Angular State Management: Zoneless Reactivity & Signals + +# 📖 Context & Scope +- **Primary Goal:** Enforce strictly functional state management patterns using Angular 20's Zoneless architecture. +- **Target Tooling:** Cursor, Windsurf, Antigravity. +- **Tech Stack Version:** Angular 20+ + +> [!IMPORTANT] +> **Strict Constraints for AI:** +> - Avoid RxJS `BehaviorSubject` for local and synchronous global component state. +> - Strictly use `signal()`, `computed()`, and `effect()` to manage all dynamic data states. +> - Never use the `@Input()` and `@Output()` decorators for sharing state across component trees; rely solely on functional `input()` and `output()`. + +--- + +## 🏗 Architecture & Data Flow + +State management in Angular 20 relies entirely on the granular reactivity provided by Signals. This architecture inherently supports Zoneless change detection by exactly tracking which views need updates without relying on `zone.js`. + +```mermaid +graph TD + Store[Signal Store / Global Service] -->|Signals| Comp1[Component A] + Store -->|Signals| Comp2[Component B] + Comp1 -->|input()| Child[Child Component] + Comp2 -->|model()| Child2[Two-Way Child] + + classDef default fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px,color:#000; + classDef component fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#000; + classDef layout fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px,color:#000; + + class Store layout; + class Comp1 component; + class Comp2 component; + class Child default; + class Child2 default; +``` + +--- + +## 🚀 I. Local State Management + +### 🚨 1. Managing Component State with Signals +**Context:** Synchronous local state. +#### ❌ Bad Practice +```typescript +isLoading: boolean = false; +data: any[] = []; + +fetchData() { + this.isLoading = true; + this.api.get().subscribe(res => { + this.data = res; + this.isLoading = false; + }); +} +``` +#### ⚠️ Problem +Relying on raw primitive properties means Angular relies on `zone.js` to run Change Detection globally whenever an event completes. +#### ✅ Best Practice +```typescript +isLoading = signal(false); +data = signal([]); + +fetchData() { + this.isLoading.set(true); + this.api.get().subscribe(res => { + this.data.set(res); + this.isLoading.set(false); + }); +} +``` +#### 🚀 Solution +Use `signal()`. It forces the developer to explicitly use `.set()` or `.update()`, signaling to the framework exactly when and where the change occurred. + +--- + +## ⚙️ II. Derived State + +### 🚨 2. Computing Values +**Context:** Creating derived state based on other state values. +#### ❌ Bad Practice +```typescript +items = signal([1, 2, 3]); +total = 0; + +updateTotal() { + this.total = this.items().reduce((a, b) => a + b, 0); +} +``` +#### ⚠️ Problem +Manually syncing state variables is error-prone. If you update `items` but forget to call `updateTotal()`, the state becomes inconsistent. +#### ✅ Best Practice +```typescript +items = signal([1, 2, 3]); +total = computed(() => this.items().reduce((a, b) => a + b, 0)); +``` +#### 🚀 Solution +Use `computed()`. The calculated value is memoized and only re-evaluates when its specific signal dependencies (in this case, `items`) change. + +--- + +## ⚡ III. Side Effects + +### 🚨 3. Handling Side Effects Safely +**Context:** Executing logic when a signal changes. +#### ❌ Bad Practice +Using getters or Angular lifecycle hooks like `ngDoCheck` to monitor value changes and trigger side effects like logging or generic HTTP calls. +#### ⚠️ Problem +This causes severe performance degradation as the logic is run on every change detection cycle, regardless of whether the specific state actually changed. +#### ✅ Best Practice +```typescript +constructor() { + effect(() => { + console.log(`Current items count: ${this.items().length}`); + // Effect will re-run automatically only when this.items() changes. + }); +} +``` +#### 🚀 Solution +Use `effect()`. Effects track dependencies automatically and ensure the side effect runs solely when required. Always define them within an injection context (like a constructor). + +--- + +## 🔗 IV. Component Communication + +### 🚨 4. Modern Data Passing +**Context:** Passing data between parent and child components. +#### ❌ Bad Practice +```typescript +@Input() user: User; +@Output() userUpdate = new EventEmitter(); +``` +#### ⚠️ Problem +Requires boilerplate, depends on decorators which are less ideal for dynamic composition, and heavily couples the components to legacy Zone-based tracking. +#### ✅ Best Practice +```typescript +// For one-way data flow +user = input.required(); + +// For two-way data binding synchronization +userProfile = model(); +``` +#### 🚀 Solution +Use the `input()` and `model()` functional APIs. They return signals that can be directly used in `computed()` properties within the child component. + +--- + +[⬆️ Back to Top](#) diff --git a/frontend/javascript/readme.md b/frontend/javascript/readme.md index d512c4e..30b7de5 100644 --- a/frontend/javascript/readme.md +++ b/frontend/javascript/readme.md @@ -16,7 +16,7 @@ last_updated: 2026-03-22 --- [⬆️ Back to Top](#) -## I. Fundamentals (The Basics) +## 🚀 I. Fundamentals (The Basics) ### 🚨 1. `var` vs `const/let` **Context:** Scoping and hoisting mechanisms in modern JavaScript. `var` is function-scoped and hoisted, leading to unpredictable behavior and accidental global leakage. @@ -41,6 +41,8 @@ console.log(price); // 100 #### 🚀 Solution Use `const` by default to ensure immutability of the reference. Use `let` only when reassigning a variable is strictly necessary. This enforces block-level scoping and prevents accidental overrides. +--- + ### 🚨 2. Loose equality `==` **Context:** JavaScript's type coercion rules are complex and often counter-intuitive. #### ❌ Bad Practice @@ -60,6 +62,8 @@ if (userCount === 0) { #### 🚀 Solution Always use strict equality `===` and inequality `!==`. This forces the developer to handle type conversions explicitly, making the code's intent clear and predictable. +--- + ### 🚨 3. Global Scope Pollution **Context:** The global namespace is shared. Overwriting global properties can break third-party libraries or browser APIs. #### ❌ Bad Practice @@ -83,6 +87,8 @@ export const config = { api: '/v1' }; #### 🚀 Solution Use ES Modules (`import/export`) to encapsulate code. Modules have their own scope and do not leak to the global object. +--- + ### 🚨 4. String concatenation vs Template Literals **Context:** Readability and handling of multi-line strings/expressions. #### ❌ Bad Practice @@ -100,6 +106,8 @@ Welcome to ${siteName}.`; #### 🚀 Solution Use Template Literals (backticks). They allow for embedded expressions, multi-line strings, and superior readability. +--- + ### 🚨 5. Magic Numbers **Context:** Numbers with no context make the codebase hard to maintain. #### ❌ Bad Practice @@ -121,6 +129,8 @@ if (user.age >= LEGAL_AGE) { #### 🚀 Solution Extract magic numbers into named constants. This provides semantic meaning and a single source of truth for configuration. +--- + ### 🚨 6. Boolean comparisons `(if x === true)` **Context:** Redundancy in conditional logic. #### ❌ Bad Practice @@ -137,6 +147,8 @@ if (!isPending) { /* ... */ } #### 🚀 Solution Leverage JavaScript's truthiness/falsiness or direct boolean evaluation. It makes the code more concise and idiomatic. +--- + ### 🚨 7. Array/Object literal vs `new` constructor **Context:** Object and Array instantiation. #### ❌ Bad Practice @@ -154,6 +166,8 @@ const map = {}; #### 🚀 Solution Use literals `[]` and `{}`. They are visually cleaner and perform slightly better as they don't involve a function call. +--- + ### 🚨 8. Function length/complexity **Context:** The Single Responsibility Principle (SRP). #### ❌ Bad Practice @@ -179,6 +193,8 @@ function processOrder(order) { #### 🚀 Solution Break functions into smaller, pure components. Aim for functions under 20 lines that do exactly one thing. +--- + ### 🚨 9. Deeply nested `if/else` (Arrow code) **Context:** Cognitive load and code readability. #### ❌ Bad Practice @@ -207,6 +223,8 @@ function getData(user) { #### 🚀 Solution Use "Guard Clauses" to return early. This flattens the structure and handles edge cases first, leaving the happy path at the lowest nesting level. +--- + ### 🚨 10. Improper naming (Single letters) **Context:** Self-documenting code. #### ❌ Bad Practice diff --git a/frontend/typescript/readme.md b/frontend/typescript/readme.md index 510f1aa..25c0946 100644 --- a/frontend/typescript/readme.md +++ b/frontend/typescript/readme.md @@ -13,9 +13,9 @@ last_updated: 2026-03-22 ![TypeScript Logo](https://img.icons8.com/?size=100&id=uJM6fQYqDaZK&format=png&color=000000) -## I. Fundamentals (1-10) +## 🚀 I. Fundamentals (1-10) -## 1. `any` vs `unknown` +## ⚡ 1. `any` vs `unknown` **Context:** Handling data of an uncertain type. `any` disables all type-checking, while `unknown` forces safety. ### ❌ Bad Practice ```typescript @@ -36,7 +36,9 @@ function process(data: unknown) { ### 🚀 Solution Use `unknown` for values whose type is not yet determined. It requires a type check or assertion before usage, ensuring the developer acknowledges the data's structure. -## 2. `null` vs `undefined` in APIs +--- + +## ⚡ 2. `null` vs `undefined` in APIs **Context:** Distinguishing between "value not provided" and "value is empty." ### ❌ Bad Practice ```typescript @@ -55,7 +57,9 @@ interface UserResponse { ### 🚀 Solution Standardize: use `undefined` (optional properties) for missing keys and `null` for intentional absence of value. Avoid using both for the same field unless strictly required by a legacy API. -## 3. `Array` vs `T[]` +--- + +## ⚡ 3. `Array` vs `T[]` **Context:** Visual consistency in array declarations. ### ❌ Bad Practice ```typescript @@ -72,7 +76,9 @@ const complex: (string | number)[] = []; ### 🚀 Solution Prefer the shorthand `T[]`. It is idiomatic, more readable, and clearly distinguishes arrays from other generic containers like `Record` or `Promise`. -## 4. `interface` vs `type` +--- + +## ⚡ 4. `interface` vs `type` **Context:** Defining object structures and aliases. ### ❌ Bad Practice ```typescript @@ -90,7 +96,9 @@ type Union = 'A' | 'B'; ### 🚀 Solution Use `type` for almost everything (unions, primitives, intersections). Use `interface` only when you specifically need declaration merging or for public library APIs where consumers might need to extend types. -## 5. Function Overloads vs Union Types +--- + +## ⚡ 5. Function Overloads vs Union Types **Context:** Handling functions with different input/output combinations. ### ❌ Bad Practice ```typescript @@ -111,7 +119,9 @@ function format(input: string | number): string { ### 🚀 Solution Prefer Union types when the implementation logic is identical for all types. Reserve overloads only for cases where the return type strictly depends on the input type and cannot be expressed via generics. -## 6. Global Scope Pollution (Legacy Namespaces) +--- + +## 🎯 6. Global Scope Pollution (Legacy Namespaces) **Context:** Organizing code in the ES Module era. ### ❌ Bad Practice ```typescript @@ -129,7 +139,9 @@ export const log = (msg: string) => console.log(msg); ### 🚀 Solution Use ES Modules (`export`/`import`). They are the industry standard, supported by all modern environments, and allow for better static analysis. -## 7. `enum` vs `const object` +--- + +## ⚡ 7. `enum` vs `const object` **Context:** Grouping related constants. ### ❌ Bad Practice ```typescript @@ -152,7 +164,9 @@ type Status = typeof STATUS[keyof typeof STATUS]; ### 🚀 Solution Use `const` objects with `as const` and a derived union type. This is more predictable, emits cleaner code, and is easier to iterate over. -## 8. Explicit `any` in Parameters +--- + +## ⚡ 8. Explicit `any` in Parameters **Context:** Enforcing strict type safety. ### ❌ Bad Practice ```typescript @@ -171,7 +185,9 @@ function save(data: UserData) { ### 🚀 Solution Enable `noImplicitAny: true` in `tsconfig.json`. Always define specific types or use `unknown` if the type is truly dynamic. -## 9. Manual Type Guards vs Type Predicates +--- + +## ⚡ 9. Manual Type Guards vs Type Predicates **Context:** Narrowing types inside conditional blocks. ### ❌ Bad Practice ```typescript @@ -194,7 +210,9 @@ if (isAdmin(input)) { ### 🚀 Solution Use Type Predicates (`arg is Type`) to create reusable, safe narrowing functions. -## 10. Triple-Slash Directives +--- + +## ⚡ 10. Triple-Slash Directives **Context:** Referencing types or files. ### ❌ Bad Practice ```typescript @@ -212,6 +230,9 @@ Use standard ES `import` statements. Manage global types via `tsconfig.json` `ty --- +--- +[⬆️ Back to Top](#) + ## 📚 Specialized Topics For further reading, please refer to the following specialized guides: