From 5b23686941840c9c0af42a662e9632e3cead2e35 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 17:21:23 +0000 Subject: [PATCH] refactor(frontend): optimize Angular snippets and initialize structured docs for SolidJS and Qwik Co-authored-by: beginwebdev2002 <102213457+beginwebdev2002@users.noreply.github.com> --- frontend/angular/advanced-performance.md | 130 ++++++++++++++++++----- frontend/qwik/performance.md | 44 ++++++++ frontend/qwik/readme.md | 7 ++ frontend/qwik/state-management.md | 61 +++++++++++ frontend/solidjs/performance.md | 54 ++++++++++ frontend/solidjs/readme.md | 7 ++ frontend/solidjs/state-management.md | 58 ++++++++++ 7 files changed, 333 insertions(+), 28 deletions(-) create mode 100644 frontend/qwik/performance.md create mode 100644 frontend/qwik/state-management.md create mode 100644 frontend/solidjs/performance.md create mode 100644 frontend/solidjs/state-management.md diff --git a/frontend/angular/advanced-performance.md b/frontend/angular/advanced-performance.md index baa45b8..d6b21fe 100644 --- a/frontend/angular/advanced-performance.md +++ b/frontend/angular/advanced-performance.md @@ -117,15 +117,37 @@ Always use a unique key in `track`. This allows Angular to move DOM nodes instea > [!NOTE] > **Context:** Tree Rendering ### ❌ Bad Practice -Recursive component call without `OnPush` and memoization. +```html + + {{ node.name }} + + + + + +``` ### ⚠️ Problem -Exponential growth in change detection checks. +Recursive component calls without `OnPush` or memoization cause exponential growth in change detection checks, blocking the main thread during deep tree rendering. ### ✅ Best Practice -Using the `Memoization` pattern or `computed()` to prepare the tree data structure. - - +```typescript +@Component({ + selector: 'app-tree-node', + standalone: true, + imports: [CommonModule], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + {{ node().name }} + @for (child of node().children; track child.id) { + + } + ` +}) +export class TreeNodeComponent { + node = input.required(); +} +``` ### 🚀 Solution -This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries. +Use standalone components with `ChangeDetectionStrategy.OnPush` and modern `@for` control flow for recursive structures. This ensures change detection only runs when inputs change, drastically improving performance for deeply nested trees. ## ⚡ 38. Global Styles Leakage > [!NOTE] > **Context:** CSS Encapsulation @@ -181,54 +203,106 @@ Pay attention to template determinism with SSR. > [!NOTE] > **Context:** DI Performance ### ❌ Bad Practice -Calling `inject()` inside a function that loops. +```typescript +processItems(items: Item[]) { + items.forEach(item => { + const logger = inject(LoggerService); + logger.log(item.name); + }); +} +``` ### ⚠️ Problem -Although `inject` is fast, in hot paths these are unnecessary DI tree lookups. +Although `inject()` is fast, calling it inside hot paths (loops) triggers unnecessary Dependency Injection tree lookups on every iteration, which degrades performance. ### ✅ Best Practice -Inject dependency once at the class/file constant level. - +```typescript +export class ItemProcessor { + private logger = inject(LoggerService); + processItems(items: Item[]) { + items.forEach(item => { + this.logger.log(item.name); + }); + } +} +``` ### 🚀 Solution -This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries. +Inject dependencies exactly once at the class or property level. This caches the reference to the service, bypassing redundant DI resolution and keeping hot paths efficient. ## ⚡ 43. Unused Signal Dependencies > [!NOTE] > **Context:** Signal Graph ### ❌ Bad Practice -Reading a signal inside `computed` whose value doesn't affect the result (an unexecuted logical branch). +```typescript +effect(() => { + console.log('Value changed:', this.value()); + this.analytics.track('Change', this.user()?.id); +}); +``` ### ⚠️ Problem -Angular dynamically builds the dependency graph. If you accidentally read a signal, it becomes a dependency. +Angular dynamically builds the signal graph. If you read a signal like `this.user()` inside an effect just for analytics, any change to `user()` will unexpectedly re-trigger the effect, leading to redundant executions. ### ✅ Best Practice -Use `untracked()` to read signals whose changes should not trigger a recalculation. - - +```typescript +effect(() => { + const currentVal = this.value(); + untracked(() => { + this.analytics.track('Change', this.user()?.id); + }); + console.log('Value changed:', currentVal); +}); +``` ### 🚀 Solution -This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries. +Use `untracked()` to read signals that should not register as dependencies. This prevents unintended re-evaluations and ensures effects only run when their primary state changes. ## ⚡ 44. Excessive Wrappers (`div` soup) > [!NOTE] > **Context:** DOM Size ### ❌ Bad Practice ```html -
+
+
+ +
+
``` ### ⚠️ Problem -Increases DOM tree depth, slowing down Style Recalculation and Layout. +Unnecessary wrapper `
` elements deeply nest the DOM tree ("div soup"). This exponentially slows down CSS Style Recalculation, Layout (Reflow), and Paint. ### ✅ Best Practice -Use `` to group elements without creating extra DOM nodes. - - +```html +@if (isLoggedIn()) { + + + +} +``` ### 🚀 Solution -This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries. +Utilize `` to apply structural logic or apply classes directly to component hosts. `` is rendered as an invisible comment, keeping the DOM tree shallow and performant. ## ⚡ 45. Neglecting `runOutsideAngular` for Events > [!NOTE] > **Context:** High-frequency events ### ❌ Bad Practice -`@HostListener('window:scroll')` +```typescript +@HostListener('window:scroll', ['$event']) +onScroll() { + this.scrollPosition.set(window.scrollY); +} +``` ### ⚠️ Problem -Every scroll event triggers Change Detection. +Every scroll, mousemove, or drag event triggers a full Angular Change Detection cycle. High-frequency events will cause immediate UI lag and frame drops. ### ✅ Best Practice -Subscribe manually in `runOutsideAngular` and update the signal only when necessary. - +```typescript +export class ScrollTracker { + private zone = inject(NgZone); + scrollPosition = signal(0); + constructor() { + this.zone.runOutsideAngular(() => { + window.addEventListener('scroll', () => { + if (Math.abs(window.scrollY - this.scrollPosition()) > 50) { + this.zone.run(() => this.scrollPosition.set(window.scrollY)); + } + }); + }); + } +} +``` ### 🚀 Solution -This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries. +Bind high-frequency events outside the Angular Zone using `NgZone.runOutsideAngular()`. Only re-enter the Angular Zone (`zone.run()`) when a threshold is met and a UI update is strictly required. --- diff --git a/frontend/qwik/performance.md b/frontend/qwik/performance.md new file mode 100644 index 0000000..0edda2a --- /dev/null +++ b/frontend/qwik/performance.md @@ -0,0 +1,44 @@ +--- +technology: Qwik +domain: frontend +level: Senior/Architect +version: "1.x" +tags: [performance, advanced, qwik, best-practices, clean-code, scalable-code] +ai_role: Senior Qwik Performance Expert +last_updated: 2026-03-22 +--- + +# 🚀 Qwik Advanced Performance Best Practices + +[⬆️ Back to Top](#) +# 📖 Context & Scope +- **Primary Goal:** Enforce strict adherence to advanced performance best practices in Qwik. +- **Target Tooling:** Cursor, Windsurf, Antigravity. +- **Tech Stack Version:** Qwik 1.x + +## ⚡ II. Advanced Performance + +## ⚡ 1. Synchronous Closures +> [!NOTE] +> **Context:** Component Event Handlers +### ❌ Bad Practice +```tsx +const Component = component$(() => { + const handleClick = () => console.log('clicked'); + return ; +}); +``` +### ⚠️ Problem +If you define synchronous functions and bind them to events, Qwik must bundle all that javascript code eagerly, undermining resumability and slowing down the initial page load time. +### ✅ Best Practice +```tsx +import { component$, $ } from '@builder.io/qwik'; + +const Component = component$(() => { + const handleClick = $(() => console.log('clicked')); + return ; +}); +``` +### 🚀 Solution +Ensure all event handlers use the `$` suffix (like `onClick$`) and their corresponding logic is wrapped in `$()`. This explicit syntax breaks the application into tiny resumable closures that Qwik can fetch only when the user interacts with them. +--- diff --git a/frontend/qwik/readme.md b/frontend/qwik/readme.md index 99f2ea5..cde5b3f 100644 --- a/frontend/qwik/readme.md +++ b/frontend/qwik/readme.md @@ -43,3 +43,10 @@ const Component = component$(({ onClick$ }: { onClick$: PropFunction<() => void> ``` ### 🚀 Solution Use the `$` suffix (`onClick$`) to mark the prop as a `PropFunction`, allowing Qwik to serialize the closure and load it lazily. + +## 📚 Specialized Topics + +For further reading, please refer to the following specialized guides: + +- [🚀 Advanced Performance](./performance.md) +- [📦 State Management](./state-management.md) diff --git a/frontend/qwik/state-management.md b/frontend/qwik/state-management.md new file mode 100644 index 0000000..79b00f9 --- /dev/null +++ b/frontend/qwik/state-management.md @@ -0,0 +1,61 @@ +--- +technology: Qwik +domain: frontend +level: Senior/Architect +version: "1.x" +tags: [state-management, advanced, qwik, best-practices, clean-code, scalable-code] +ai_role: Senior Qwik State Management Expert +last_updated: 2026-03-22 +--- + +# 🔄 Qwik State Management Best Practices + +[⬆️ Back to Top](#) +# 📖 Context & Scope +- **Primary Goal:** Enforce strict adherence to state management best practices in Qwik. +- **Target Tooling:** Cursor, Windsurf, Antigravity. +- **Tech Stack Version:** Qwik 1.x + +## ⚡ II. State Management + +## ⚡ 1. Storing Unserializable Data +> [!NOTE] +> **Context:** Reactive Stores and State Object +### ❌ Bad Practice +```tsx +import { component$, useStore, useTask$ } from '@builder.io/qwik'; + +export const MyComponent = component$(() => { + const store = useStore({ + ws: null, + }); + + useTask$(() => { + store.ws = new WebSocket('ws://localhost:8080'); // Throws Serialization Error + }); + + return
Connecting...
; +}); +``` +### ⚠️ Problem +Objects like WebSockets, DOM elements, Timeouts, or native Maps/Sets cannot be JSON serialized. Putting them into `useStore` breaks Qwik's core serialization engine, causing fatal errors when the server attempts to transmit state to the client for resumability. +### ✅ Best Practice +```tsx +import { component$, useSignal, useTask$, useVisibleTask$ } from '@builder.io/qwik'; + +export const MyComponent = component$(() => { + // Use useSignal initialized with undefined on server + const ws = useSignal(); + + // Only run in browser (where websocket lives) + useVisibleTask$(() => { + ws.value = new WebSocket('ws://localhost:8080'); + return () => ws.value?.close(); + }); + + return
Connecting...
; +}); +``` +### 🚀 Solution +Do not put instances like WebSockets or DOM references into `useStore`. Use `useSignal()` when you need isolated references that initialize lazily on the client using `useVisibleTask$()`, or handle them outside the reactive serialization boundaries. +--- diff --git a/frontend/solidjs/performance.md b/frontend/solidjs/performance.md new file mode 100644 index 0000000..8d5f2f3 --- /dev/null +++ b/frontend/solidjs/performance.md @@ -0,0 +1,54 @@ +--- +technology: SolidJS +domain: frontend +level: Senior/Architect +version: "1.8+" +tags: [performance, advanced, solidjs, best-practices, clean-code, scalable-code] +ai_role: Senior SolidJS Performance Expert +last_updated: 2026-03-22 +--- + +# 🚀 SolidJS Advanced Performance Best Practices + +[⬆️ Back to Top](#) +# 📖 Context & Scope +- **Primary Goal:** Enforce strict adherence to advanced performance best practices in SolidJS. +- **Target Tooling:** Cursor, Windsurf, Antigravity. +- **Tech Stack Version:** SolidJS 1.8+ + +## ⚡ II. Advanced Performance + +## ⚡ 1. Suboptimal List Rendering +> [!NOTE] +> **Context:** Rendering large lists in the DOM. +### ❌ Bad Practice +```tsx +function List(props) { + return ( +
    + {props.items.map(item => ( +
  • {item.name}
  • + ))} +
+ ); +} +``` +### ⚠️ Problem +Using standard `.map()` for array rendering creates new DOM nodes for every element when the array changes, even if only one item is added or modified. This causes high CPU overhead and negates SolidJS's fine-grained reactivity. +### ✅ Best Practice +```tsx +import { For } from 'solid-js'; + +function List(props) { + return ( +
    + + {(item) =>
  • {item.name}
  • } +
    +
+ ); +} +``` +### 🚀 Solution +Always utilize the built-in `` component. It caches DOM elements and handles granular updates when the array changes, reusing nodes instead of discarding and recreating them. +--- diff --git a/frontend/solidjs/readme.md b/frontend/solidjs/readme.md index 89af51e..1584b51 100644 --- a/frontend/solidjs/readme.md +++ b/frontend/solidjs/readme.md @@ -41,3 +41,10 @@ return
    {item =>
  • {item.name}
  • }
; ``` ### 🚀 Solution Use the `` component. It caches DOM elements and handles granular updates when the array changes. + +## 📚 Specialized Topics + +For further reading, please refer to the following specialized guides: + +- [🚀 Advanced Performance](./performance.md) +- [📦 State Management](./state-management.md) diff --git a/frontend/solidjs/state-management.md b/frontend/solidjs/state-management.md new file mode 100644 index 0000000..8ce0ffb --- /dev/null +++ b/frontend/solidjs/state-management.md @@ -0,0 +1,58 @@ +--- +technology: SolidJS +domain: frontend +level: Senior/Architect +version: "1.8+" +tags: [state-management, advanced, solidjs, best-practices, clean-code, scalable-code] +ai_role: Senior SolidJS State Management Expert +last_updated: 2026-03-22 +--- + +# 🔄 SolidJS State Management Best Practices + +[⬆️ Back to Top](#) +# 📖 Context & Scope +- **Primary Goal:** Enforce strict adherence to state management best practices in SolidJS. +- **Target Tooling:** Cursor, Windsurf, Antigravity. +- **Tech Stack Version:** SolidJS 1.8+ + +## ⚡ II. State Management + +## ⚡ 1. Direct Prop Destructuring +> [!NOTE] +> **Context:** Receiving props in functional components. +### ❌ Bad Practice +```tsx +function Profile({ user, settings }) { + return ( +
+

{user.name}

+

{settings.theme}

+
+ ); +} +``` +### ⚠️ Problem +SolidJS tracks reactivity via getters. If you destructure props (e.g., `{ user }`), the component loses reactivity because the destructured variable evaluates to a static reference at the time of component execution. When the parent updates the prop, the child component will not react. +### ✅ Best Practice +```tsx +import { splitProps } from 'solid-js'; + +function Profile(props) { + // Option 1: Access directly (preferred) + // return

{props.user.name}

+ + // Option 2: Split props if needed for spreading + const [local, others] = splitProps(props, ['user', 'settings']); + + return ( +
+

{local.user.name}

+

{local.settings.theme}

+
+ ); +} +``` +### 🚀 Solution +Never destructure props directly. Access props dynamically via `props.propertyName` or use `splitProps()` / `mergeProps()` utilities if you need to separate internal from forwarded properties while preserving reactive getters. +---