agentic-team-templates 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +280 -0
- package/bin/cli.js +5 -0
- package/package.json +47 -0
- package/src/index.js +521 -0
- package/templates/_shared/code-quality.md +162 -0
- package/templates/_shared/communication.md +114 -0
- package/templates/_shared/core-principles.md +62 -0
- package/templates/_shared/git-workflow.md +165 -0
- package/templates/_shared/security-fundamentals.md +173 -0
- package/templates/blockchain/.cursorrules/defi-patterns.md +520 -0
- package/templates/blockchain/.cursorrules/gas-optimization.md +339 -0
- package/templates/blockchain/.cursorrules/overview.md +130 -0
- package/templates/blockchain/.cursorrules/security.md +318 -0
- package/templates/blockchain/.cursorrules/smart-contracts.md +364 -0
- package/templates/blockchain/.cursorrules/testing.md +415 -0
- package/templates/blockchain/.cursorrules/web3-integration.md +538 -0
- package/templates/blockchain/CLAUDE.md +389 -0
- package/templates/cli-tools/.cursorrules/architecture.md +412 -0
- package/templates/cli-tools/.cursorrules/arguments.md +406 -0
- package/templates/cli-tools/.cursorrules/distribution.md +546 -0
- package/templates/cli-tools/.cursorrules/error-handling.md +455 -0
- package/templates/cli-tools/.cursorrules/overview.md +136 -0
- package/templates/cli-tools/.cursorrules/testing.md +537 -0
- package/templates/cli-tools/.cursorrules/user-experience.md +545 -0
- package/templates/cli-tools/CLAUDE.md +356 -0
- package/templates/data-engineering/.cursorrules/data-modeling.md +367 -0
- package/templates/data-engineering/.cursorrules/data-quality.md +455 -0
- package/templates/data-engineering/.cursorrules/overview.md +85 -0
- package/templates/data-engineering/.cursorrules/performance.md +339 -0
- package/templates/data-engineering/.cursorrules/pipeline-design.md +280 -0
- package/templates/data-engineering/.cursorrules/security.md +460 -0
- package/templates/data-engineering/.cursorrules/testing.md +452 -0
- package/templates/data-engineering/CLAUDE.md +974 -0
- package/templates/devops-sre/.cursorrules/capacity-planning.md +653 -0
- package/templates/devops-sre/.cursorrules/change-management.md +584 -0
- package/templates/devops-sre/.cursorrules/chaos-engineering.md +651 -0
- package/templates/devops-sre/.cursorrules/disaster-recovery.md +641 -0
- package/templates/devops-sre/.cursorrules/incident-management.md +565 -0
- package/templates/devops-sre/.cursorrules/observability.md +714 -0
- package/templates/devops-sre/.cursorrules/overview.md +230 -0
- package/templates/devops-sre/.cursorrules/postmortems.md +588 -0
- package/templates/devops-sre/.cursorrules/runbooks.md +760 -0
- package/templates/devops-sre/.cursorrules/slo-sli.md +617 -0
- package/templates/devops-sre/.cursorrules/toil-reduction.md +567 -0
- package/templates/devops-sre/CLAUDE.md +1007 -0
- package/templates/documentation/.cursorrules/adr.md +277 -0
- package/templates/documentation/.cursorrules/api-documentation.md +411 -0
- package/templates/documentation/.cursorrules/code-comments.md +253 -0
- package/templates/documentation/.cursorrules/maintenance.md +260 -0
- package/templates/documentation/.cursorrules/overview.md +82 -0
- package/templates/documentation/.cursorrules/readme-standards.md +306 -0
- package/templates/documentation/CLAUDE.md +120 -0
- package/templates/fullstack/.cursorrules/api-contracts.md +331 -0
- package/templates/fullstack/.cursorrules/architecture.md +298 -0
- package/templates/fullstack/.cursorrules/overview.md +109 -0
- package/templates/fullstack/.cursorrules/shared-types.md +348 -0
- package/templates/fullstack/.cursorrules/testing.md +386 -0
- package/templates/fullstack/CLAUDE.md +349 -0
- package/templates/ml-ai/.cursorrules/data-engineering.md +483 -0
- package/templates/ml-ai/.cursorrules/deployment.md +601 -0
- package/templates/ml-ai/.cursorrules/model-development.md +538 -0
- package/templates/ml-ai/.cursorrules/monitoring.md +658 -0
- package/templates/ml-ai/.cursorrules/overview.md +131 -0
- package/templates/ml-ai/.cursorrules/security.md +637 -0
- package/templates/ml-ai/.cursorrules/testing.md +678 -0
- package/templates/ml-ai/CLAUDE.md +1136 -0
- package/templates/mobile/.cursorrules/navigation.md +246 -0
- package/templates/mobile/.cursorrules/offline-first.md +302 -0
- package/templates/mobile/.cursorrules/overview.md +71 -0
- package/templates/mobile/.cursorrules/performance.md +345 -0
- package/templates/mobile/.cursorrules/testing.md +339 -0
- package/templates/mobile/CLAUDE.md +233 -0
- package/templates/platform-engineering/.cursorrules/ci-cd.md +778 -0
- package/templates/platform-engineering/.cursorrules/developer-experience.md +632 -0
- package/templates/platform-engineering/.cursorrules/infrastructure-as-code.md +600 -0
- package/templates/platform-engineering/.cursorrules/kubernetes.md +710 -0
- package/templates/platform-engineering/.cursorrules/observability.md +747 -0
- package/templates/platform-engineering/.cursorrules/overview.md +215 -0
- package/templates/platform-engineering/.cursorrules/security.md +855 -0
- package/templates/platform-engineering/.cursorrules/testing.md +878 -0
- package/templates/platform-engineering/CLAUDE.md +850 -0
- package/templates/utility-agent/.cursorrules/action-control.md +284 -0
- package/templates/utility-agent/.cursorrules/context-management.md +186 -0
- package/templates/utility-agent/.cursorrules/hallucination-prevention.md +253 -0
- package/templates/utility-agent/.cursorrules/overview.md +78 -0
- package/templates/utility-agent/.cursorrules/token-optimization.md +369 -0
- package/templates/utility-agent/CLAUDE.md +513 -0
- package/templates/web-backend/.cursorrules/api-design.md +255 -0
- package/templates/web-backend/.cursorrules/authentication.md +309 -0
- package/templates/web-backend/.cursorrules/database-patterns.md +298 -0
- package/templates/web-backend/.cursorrules/error-handling.md +366 -0
- package/templates/web-backend/.cursorrules/overview.md +69 -0
- package/templates/web-backend/.cursorrules/security.md +358 -0
- package/templates/web-backend/.cursorrules/testing.md +395 -0
- package/templates/web-backend/CLAUDE.md +366 -0
- package/templates/web-frontend/.cursorrules/accessibility.md +296 -0
- package/templates/web-frontend/.cursorrules/component-patterns.md +204 -0
- package/templates/web-frontend/.cursorrules/overview.md +72 -0
- package/templates/web-frontend/.cursorrules/performance.md +325 -0
- package/templates/web-frontend/.cursorrules/state-management.md +227 -0
- package/templates/web-frontend/.cursorrules/styling.md +271 -0
- package/templates/web-frontend/.cursorrules/testing.md +311 -0
- package/templates/web-frontend/CLAUDE.md +399 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Component Patterns
|
|
2
|
+
|
|
3
|
+
Best practices for building frontend components.
|
|
4
|
+
|
|
5
|
+
## Composition Over Inheritance
|
|
6
|
+
|
|
7
|
+
Build complex UIs by composing small components, not extending base classes.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
// Good: Composition
|
|
11
|
+
const UserCard = ({ user }: { user: User }) => (
|
|
12
|
+
<Card>
|
|
13
|
+
<Avatar src={user.avatar} />
|
|
14
|
+
<CardContent>
|
|
15
|
+
<UserName name={user.name} />
|
|
16
|
+
<UserBio bio={user.bio} />
|
|
17
|
+
</CardContent>
|
|
18
|
+
</Card>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// Bad: Inheritance
|
|
22
|
+
class UserCard extends BaseCard {
|
|
23
|
+
renderContent() { ... }
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Pure Components
|
|
28
|
+
|
|
29
|
+
Components should be predictable: same props = same output.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
// Good: Pure component
|
|
33
|
+
const Greeting = ({ name }: { name: string }) => (
|
|
34
|
+
<h1>Hello, {name}!</h1>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// Bad: Side effects in render
|
|
38
|
+
const Greeting = ({ name }: { name: string }) => {
|
|
39
|
+
document.title = name; // Side effect!
|
|
40
|
+
return <h1>Hello, {name}!</h1>;
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Single Responsibility
|
|
45
|
+
|
|
46
|
+
Each component should do one thing well.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
// Good: Focused components
|
|
50
|
+
const UserAvatar = ({ src, alt }: AvatarProps) => (
|
|
51
|
+
<img src={src} alt={alt} className="avatar" />
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const UserName = ({ name }: { name: string }) => (
|
|
55
|
+
<span className="user-name">{name}</span>
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Bad: Component doing too much
|
|
59
|
+
const UserDisplay = ({ user }: { user: User }) => {
|
|
60
|
+
// Fetching, formatting, displaying, handling clicks...
|
|
61
|
+
// This should be split up
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Props Interface
|
|
66
|
+
|
|
67
|
+
Define clear, typed interfaces for component props.
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
// Good: Explicit props interface
|
|
71
|
+
interface ButtonProps {
|
|
72
|
+
variant: 'primary' | 'secondary' | 'danger';
|
|
73
|
+
size?: 'sm' | 'md' | 'lg';
|
|
74
|
+
disabled?: boolean;
|
|
75
|
+
onClick: () => void;
|
|
76
|
+
children: React.ReactNode;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const Button = ({ variant, size = 'md', disabled, onClick, children }: ButtonProps) => (
|
|
80
|
+
// ...
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Bad: Implicit or any props
|
|
84
|
+
const Button = (props: any) => ( ... );
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Controlled vs Uncontrolled
|
|
88
|
+
|
|
89
|
+
Prefer controlled components for form inputs.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// Good: Controlled input
|
|
93
|
+
const SearchInput = ({ value, onChange }: SearchInputProps) => (
|
|
94
|
+
<input
|
|
95
|
+
type="text"
|
|
96
|
+
value={value}
|
|
97
|
+
onChange={(e) => onChange(e.target.value)}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Acceptable for simple cases: Uncontrolled with ref
|
|
102
|
+
const FileInput = ({ onFile }: FileInputProps) => {
|
|
103
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
104
|
+
return <input type="file" ref={ref} onChange={...} />;
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Conditional Rendering
|
|
109
|
+
|
|
110
|
+
Use clear patterns for conditional UI.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
// Good: Early return for guards
|
|
114
|
+
const UserProfile = ({ user }: { user: User | null }) => {
|
|
115
|
+
if (!user) return <NotLoggedIn />;
|
|
116
|
+
return <Profile user={user} />;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Good: Ternary for simple conditions
|
|
120
|
+
const Status = ({ isActive }: { isActive: boolean }) => (
|
|
121
|
+
<span>{isActive ? 'Active' : 'Inactive'}</span>
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Good: && for optional rendering
|
|
125
|
+
const Notification = ({ message }: { message?: string }) => (
|
|
126
|
+
<div>
|
|
127
|
+
{message && <Alert>{message}</Alert>}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Handling Events
|
|
133
|
+
|
|
134
|
+
Keep event handlers clean and focused.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
// Good: Handler defined separately
|
|
138
|
+
const Form = () => {
|
|
139
|
+
const handleSubmit = (e: FormEvent) => {
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
// Submit logic
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return <form onSubmit={handleSubmit}>...</form>;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Avoid: Complex inline handlers
|
|
148
|
+
const Form = () => (
|
|
149
|
+
<form onSubmit={(e) => {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
// Lots of logic here...
|
|
152
|
+
}}>
|
|
153
|
+
...
|
|
154
|
+
</form>
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Children Patterns
|
|
159
|
+
|
|
160
|
+
Use children effectively for composition.
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
// Good: Children for content injection
|
|
164
|
+
const Card = ({ title, children }: CardProps) => (
|
|
165
|
+
<div className="card">
|
|
166
|
+
<h2>{title}</h2>
|
|
167
|
+
<div className="card-content">{children}</div>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Usage
|
|
172
|
+
<Card title="Settings">
|
|
173
|
+
<SettingsForm />
|
|
174
|
+
</Card>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Render Props & Compound Components
|
|
178
|
+
|
|
179
|
+
For complex reusable patterns.
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
// Compound components pattern
|
|
183
|
+
const Tabs = ({ children }: TabsProps) => {
|
|
184
|
+
const [active, setActive] = useState(0);
|
|
185
|
+
return (
|
|
186
|
+
<TabsContext.Provider value={{ active, setActive }}>
|
|
187
|
+
{children}
|
|
188
|
+
</TabsContext.Provider>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
Tabs.List = TabsList;
|
|
193
|
+
Tabs.Panel = TabsPanel;
|
|
194
|
+
|
|
195
|
+
// Usage
|
|
196
|
+
<Tabs>
|
|
197
|
+
<Tabs.List>
|
|
198
|
+
<Tabs.Tab>One</Tabs.Tab>
|
|
199
|
+
<Tabs.Tab>Two</Tabs.Tab>
|
|
200
|
+
</Tabs.List>
|
|
201
|
+
<Tabs.Panel>Content One</Tabs.Panel>
|
|
202
|
+
<Tabs.Panel>Content Two</Tabs.Panel>
|
|
203
|
+
</Tabs>
|
|
204
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Web Frontend Development
|
|
2
|
+
|
|
3
|
+
Guidelines for building modern web frontend applications.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
This ruleset applies to:
|
|
8
|
+
- Single-page applications (SPAs)
|
|
9
|
+
- Server-rendered web applications
|
|
10
|
+
- Static sites with dynamic components
|
|
11
|
+
- Progressive web applications (PWAs)
|
|
12
|
+
|
|
13
|
+
## Core Technologies
|
|
14
|
+
|
|
15
|
+
Frontend development typically involves:
|
|
16
|
+
- JavaScript/TypeScript
|
|
17
|
+
- Component frameworks (React, Vue, Angular, Svelte, etc.)
|
|
18
|
+
- CSS/Styling solutions (CSS Modules, Tailwind, Styled Components, etc.)
|
|
19
|
+
- Build tools (Vite, webpack, esbuild, etc.)
|
|
20
|
+
- Testing frameworks (Jest, Vitest, Testing Library, Playwright, etc.)
|
|
21
|
+
|
|
22
|
+
## Key Principles
|
|
23
|
+
|
|
24
|
+
### 1. User Experience First
|
|
25
|
+
- Fast initial load
|
|
26
|
+
- Responsive to user input
|
|
27
|
+
- Works across devices and browsers
|
|
28
|
+
- Accessible to all users
|
|
29
|
+
|
|
30
|
+
### 2. Component-Based Architecture
|
|
31
|
+
- Small, focused components
|
|
32
|
+
- Reusable and composable
|
|
33
|
+
- Clear data flow
|
|
34
|
+
- Separation of concerns
|
|
35
|
+
|
|
36
|
+
### 3. Type Safety
|
|
37
|
+
- Use TypeScript for all new code
|
|
38
|
+
- Define explicit types for props and state
|
|
39
|
+
- Avoid `any` type
|
|
40
|
+
- Let types document your code
|
|
41
|
+
|
|
42
|
+
### 4. Progressive Enhancement
|
|
43
|
+
- Core functionality works without JavaScript where possible
|
|
44
|
+
- Enhanced experience with JavaScript
|
|
45
|
+
- Graceful degradation for older browsers
|
|
46
|
+
|
|
47
|
+
## Project Structure
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
src/
|
|
51
|
+
├── components/ # Reusable UI components
|
|
52
|
+
│ ├── ui/ # Primitive components (Button, Input, Card)
|
|
53
|
+
│ └── features/ # Feature-specific components
|
|
54
|
+
├── pages/ # Page/route components
|
|
55
|
+
├── hooks/ # Custom React hooks (or equivalent)
|
|
56
|
+
├── lib/ # Business logic, utilities
|
|
57
|
+
├── types/ # TypeScript type definitions
|
|
58
|
+
├── styles/ # Global styles, theme
|
|
59
|
+
└── assets/ # Static assets (images, fonts)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Definition of Done
|
|
63
|
+
|
|
64
|
+
A frontend feature is complete when:
|
|
65
|
+
- [ ] Component renders correctly
|
|
66
|
+
- [ ] Responsive across breakpoints
|
|
67
|
+
- [ ] Keyboard navigable
|
|
68
|
+
- [ ] Screen reader accessible
|
|
69
|
+
- [ ] Loading and error states handled
|
|
70
|
+
- [ ] Tests written and passing
|
|
71
|
+
- [ ] No TypeScript errors
|
|
72
|
+
- [ ] Meets performance budgets
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# Frontend Performance
|
|
2
|
+
|
|
3
|
+
Guidelines for building fast, responsive web applications.
|
|
4
|
+
|
|
5
|
+
## Core Web Vitals
|
|
6
|
+
|
|
7
|
+
### Largest Contentful Paint (LCP)
|
|
8
|
+
Measures loading performance. Target: < 2.5 seconds.
|
|
9
|
+
|
|
10
|
+
**Optimize by:**
|
|
11
|
+
- Optimize critical rendering path
|
|
12
|
+
- Preload critical resources
|
|
13
|
+
- Use efficient image formats (WebP, AVIF)
|
|
14
|
+
- Implement proper caching
|
|
15
|
+
|
|
16
|
+
### First Input Delay (FID) / Interaction to Next Paint (INP)
|
|
17
|
+
Measures interactivity. Target: < 100ms / < 200ms.
|
|
18
|
+
|
|
19
|
+
**Optimize by:**
|
|
20
|
+
- Break up long tasks
|
|
21
|
+
- Minimize main thread work
|
|
22
|
+
- Use web workers for heavy computation
|
|
23
|
+
- Defer non-critical JavaScript
|
|
24
|
+
|
|
25
|
+
### Cumulative Layout Shift (CLS)
|
|
26
|
+
Measures visual stability. Target: < 0.1.
|
|
27
|
+
|
|
28
|
+
**Optimize by:**
|
|
29
|
+
- Always include size attributes on images/video
|
|
30
|
+
- Reserve space for dynamic content
|
|
31
|
+
- Avoid inserting content above existing content
|
|
32
|
+
- Use CSS containment
|
|
33
|
+
|
|
34
|
+
## JavaScript Performance
|
|
35
|
+
|
|
36
|
+
### Code Splitting
|
|
37
|
+
|
|
38
|
+
Load code only when needed.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// Route-based splitting
|
|
42
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
43
|
+
const Settings = lazy(() => import('./pages/Settings'));
|
|
44
|
+
|
|
45
|
+
function App() {
|
|
46
|
+
return (
|
|
47
|
+
<Suspense fallback={<Loading />}>
|
|
48
|
+
<Routes>
|
|
49
|
+
<Route path="/dashboard" element={<Dashboard />} />
|
|
50
|
+
<Route path="/settings" element={<Settings />} />
|
|
51
|
+
</Routes>
|
|
52
|
+
</Suspense>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Component-based splitting
|
|
57
|
+
const HeavyChart = lazy(() => import('./components/HeavyChart'));
|
|
58
|
+
|
|
59
|
+
function Dashboard() {
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<Suspense fallback={<ChartSkeleton />}>
|
|
63
|
+
<HeavyChart data={data} />
|
|
64
|
+
</Suspense>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Minimize Bundle Size
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// Bad: Import entire library
|
|
74
|
+
import _ from 'lodash';
|
|
75
|
+
_.debounce(fn, 300);
|
|
76
|
+
|
|
77
|
+
// Good: Import only what you need
|
|
78
|
+
import debounce from 'lodash/debounce';
|
|
79
|
+
debounce(fn, 300);
|
|
80
|
+
|
|
81
|
+
// Better: Use native or smaller alternatives
|
|
82
|
+
function debounce(fn, ms) {
|
|
83
|
+
let timeoutId;
|
|
84
|
+
return (...args) => {
|
|
85
|
+
clearTimeout(timeoutId);
|
|
86
|
+
timeoutId = setTimeout(() => fn(...args), ms);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Avoid Memory Leaks
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
|
|
97
|
+
fetchData({ signal: controller.signal })
|
|
98
|
+
.then(setData)
|
|
99
|
+
.catch(err => {
|
|
100
|
+
if (err.name !== 'AbortError') throw err;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Cleanup on unmount
|
|
104
|
+
return () => controller.abort();
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
const handler = () => { ... };
|
|
109
|
+
window.addEventListener('resize', handler);
|
|
110
|
+
|
|
111
|
+
// Remove listener on cleanup
|
|
112
|
+
return () => window.removeEventListener('resize', handler);
|
|
113
|
+
}, []);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## React-Specific Optimizations
|
|
117
|
+
|
|
118
|
+
### Prevent Unnecessary Re-renders
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
// Memoize expensive components
|
|
122
|
+
const ExpensiveList = memo(({ items }: Props) => {
|
|
123
|
+
return items.map(item => <ExpensiveItem key={item.id} {...item} />);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Memoize expensive calculations
|
|
127
|
+
const sortedItems = useMemo(
|
|
128
|
+
() => items.slice().sort((a, b) => a.name.localeCompare(b.name)),
|
|
129
|
+
[items]
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Memoize callbacks passed to children
|
|
133
|
+
const handleClick = useCallback((id: string) => {
|
|
134
|
+
setSelected(id);
|
|
135
|
+
}, []);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Virtualize Long Lists
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
142
|
+
|
|
143
|
+
function VirtualList({ items }) {
|
|
144
|
+
const parentRef = useRef(null);
|
|
145
|
+
|
|
146
|
+
const virtualizer = useVirtualizer({
|
|
147
|
+
count: items.length,
|
|
148
|
+
getScrollElement: () => parentRef.current,
|
|
149
|
+
estimateSize: () => 50,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
|
|
154
|
+
<div style={{ height: virtualizer.getTotalSize() }}>
|
|
155
|
+
{virtualizer.getVirtualItems().map((virtualItem) => (
|
|
156
|
+
<div
|
|
157
|
+
key={virtualItem.key}
|
|
158
|
+
style={{
|
|
159
|
+
position: 'absolute',
|
|
160
|
+
top: virtualItem.start,
|
|
161
|
+
height: virtualItem.size,
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
164
|
+
{items[virtualItem.index].name}
|
|
165
|
+
</div>
|
|
166
|
+
))}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Defer Non-Critical Updates
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
// Use startTransition for non-urgent updates
|
|
177
|
+
import { startTransition } from 'react';
|
|
178
|
+
|
|
179
|
+
function SearchPage() {
|
|
180
|
+
const [query, setQuery] = useState('');
|
|
181
|
+
const [results, setResults] = useState([]);
|
|
182
|
+
|
|
183
|
+
const handleChange = (e) => {
|
|
184
|
+
// Urgent: Update input immediately
|
|
185
|
+
setQuery(e.target.value);
|
|
186
|
+
|
|
187
|
+
// Non-urgent: Can be interrupted
|
|
188
|
+
startTransition(() => {
|
|
189
|
+
setResults(filterResults(e.target.value));
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Image Optimization
|
|
196
|
+
|
|
197
|
+
### Use Modern Formats
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<picture>
|
|
201
|
+
<source srcset="image.avif" type="image/avif" />
|
|
202
|
+
<source srcset="image.webp" type="image/webp" />
|
|
203
|
+
<img src="image.jpg" alt="Description" />
|
|
204
|
+
</picture>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Lazy Load Images
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
// Native lazy loading
|
|
211
|
+
<img src="image.jpg" loading="lazy" alt="Description" />
|
|
212
|
+
|
|
213
|
+
// With blur placeholder
|
|
214
|
+
<Image
|
|
215
|
+
src="/image.jpg"
|
|
216
|
+
alt="Description"
|
|
217
|
+
placeholder="blur"
|
|
218
|
+
blurDataURL={blurHash}
|
|
219
|
+
/>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Proper Sizing
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
// Always specify dimensions
|
|
226
|
+
<img
|
|
227
|
+
src="image.jpg"
|
|
228
|
+
width={800}
|
|
229
|
+
height={600}
|
|
230
|
+
alt="Description"
|
|
231
|
+
/>
|
|
232
|
+
|
|
233
|
+
// Responsive images
|
|
234
|
+
<img
|
|
235
|
+
src="image-800.jpg"
|
|
236
|
+
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
|
|
237
|
+
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
|
|
238
|
+
alt="Description"
|
|
239
|
+
/>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Network Optimization
|
|
243
|
+
|
|
244
|
+
### Preload Critical Resources
|
|
245
|
+
|
|
246
|
+
```html
|
|
247
|
+
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin />
|
|
248
|
+
<link rel="preload" href="/hero.jpg" as="image" />
|
|
249
|
+
<link rel="preconnect" href="https://api.example.com" />
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Cache Effectively
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
// Service worker caching
|
|
256
|
+
// Cache static assets aggressively
|
|
257
|
+
// Network-first for API calls
|
|
258
|
+
// Stale-while-revalidate for semi-static content
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Compress Assets
|
|
262
|
+
|
|
263
|
+
- Enable gzip/brotli compression on server
|
|
264
|
+
- Minify JS, CSS, HTML
|
|
265
|
+
- Optimize SVGs
|
|
266
|
+
|
|
267
|
+
## Monitoring
|
|
268
|
+
|
|
269
|
+
### Performance Metrics
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
// Web Vitals library
|
|
273
|
+
import { onCLS, onFID, onLCP } from 'web-vitals';
|
|
274
|
+
|
|
275
|
+
onCLS(console.log);
|
|
276
|
+
onFID(console.log);
|
|
277
|
+
onLCP(console.log);
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Performance Budgets
|
|
281
|
+
|
|
282
|
+
Set limits and alert on regression:
|
|
283
|
+
- JavaScript bundle: < 200KB (gzipped)
|
|
284
|
+
- CSS: < 50KB (gzipped)
|
|
285
|
+
- LCP: < 2.5s
|
|
286
|
+
- TTI: < 5s
|
|
287
|
+
|
|
288
|
+
## Anti-Patterns
|
|
289
|
+
|
|
290
|
+
### Blocking the Main Thread
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
// Bad: Synchronous heavy computation
|
|
294
|
+
const sorted = hugeArray.sort((a, b) => complexComparison(a, b));
|
|
295
|
+
|
|
296
|
+
// Good: Use web worker or break into chunks
|
|
297
|
+
const worker = new Worker('sort-worker.js');
|
|
298
|
+
worker.postMessage(hugeArray);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Layout Thrashing
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
// Bad: Read/write in loop
|
|
305
|
+
items.forEach(item => {
|
|
306
|
+
const height = item.offsetHeight; // Read
|
|
307
|
+
item.style.height = height + 10; // Write
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Good: Batch reads then writes
|
|
311
|
+
const heights = items.map(item => item.offsetHeight);
|
|
312
|
+
items.forEach((item, i) => {
|
|
313
|
+
item.style.height = heights[i] + 10;
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Importing Everything
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
// Bad
|
|
321
|
+
import * as utils from './utils';
|
|
322
|
+
|
|
323
|
+
// Good
|
|
324
|
+
import { specificUtil } from './utils';
|
|
325
|
+
```
|