@zmice/zc 0.2.4 → 0.2.6
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 +89 -9
- package/dist/cli/__tests__/platform.test.js +169 -2
- package/dist/cli/__tests__/platform.test.js.map +1 -1
- package/dist/cli/__tests__/surface.test.js +52 -0
- package/dist/cli/__tests__/surface.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.d.ts +2 -0
- package/dist/cli/__tests__/team.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team.test.js +29 -0
- package/dist/cli/__tests__/team.test.js.map +1 -0
- package/dist/cli/__tests__/upstream.test.js +4 -0
- package/dist/cli/__tests__/upstream.test.js.map +1 -1
- package/dist/cli/platform.d.ts +11 -3
- package/dist/cli/platform.d.ts.map +1 -1
- package/dist/cli/platform.js +186 -49
- package/dist/cli/platform.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +114 -4
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/upstream.d.ts +1 -0
- package/dist/cli/upstream.d.ts.map +1 -1
- package/dist/cli/upstream.js +84 -5
- package/dist/cli/upstream.js.map +1 -1
- package/dist/node_modules/@zmice/platform-core/dist/index.d.ts +37 -3
- package/dist/node_modules/@zmice/platform-core/dist/index.d.ts.map +1 -1
- package/dist/node_modules/@zmice/platform-core/dist/index.js +68 -0
- package/dist/node_modules/@zmice/platform-core/dist/index.js.map +1 -1
- package/dist/node_modules/@zmice/platform-core/dist/index.test.js +44 -1
- package/dist/node_modules/@zmice/platform-core/dist/index.test.js.map +1 -1
- package/dist/runtime/__tests__/worktree-manager.test.js +63 -1
- package/dist/runtime/__tests__/worktree-manager.test.js.map +1 -1
- package/dist/runtime/worktree-manager.d.ts +26 -1
- package/dist/runtime/worktree-manager.d.ts.map +1 -1
- package/dist/runtime/worktree-manager.js +126 -12
- package/dist/runtime/worktree-manager.js.map +1 -1
- package/dist/team/__tests__/orchestrator.test.js +40 -0
- package/dist/team/__tests__/orchestrator.test.js.map +1 -1
- package/dist/team/__tests__/planner.test.d.ts +2 -0
- package/dist/team/__tests__/planner.test.d.ts.map +1 -0
- package/dist/team/__tests__/planner.test.js +43 -0
- package/dist/team/__tests__/planner.test.js.map +1 -0
- package/dist/team/__tests__/task-queue.test.js +18 -0
- package/dist/team/__tests__/task-queue.test.js.map +1 -1
- package/dist/team/orchestrator.d.ts +2 -1
- package/dist/team/orchestrator.d.ts.map +1 -1
- package/dist/team/orchestrator.js +29 -10
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/planner.d.ts +27 -0
- package/dist/team/planner.d.ts.map +1 -0
- package/dist/team/planner.js +120 -0
- package/dist/team/planner.js.map +1 -0
- package/dist/team/task-queue.d.ts +3 -0
- package/dist/team/task-queue.d.ts.map +1 -1
- package/dist/team/task-queue.js +11 -2
- package/dist/team/task-queue.js.map +1 -1
- package/dist/utils/qwen-extension-cli.d.ts.map +1 -1
- package/dist/utils/qwen-extension-cli.js +23 -0
- package/dist/utils/qwen-extension-cli.js.map +1 -1
- package/dist/utils/qwen-extension-cli.test.js +40 -0
- package/dist/utils/qwen-extension-cli.test.js.map +1 -1
- package/package.json +3 -3
- package/vendor/node_modules/@zmice/platform-core/dist/index.d.ts +37 -3
- package/vendor/node_modules/@zmice/platform-core/dist/index.d.ts.map +1 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.js +68 -0
- package/vendor/node_modules/@zmice/platform-core/dist/index.js.map +1 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.test.js +44 -1
- package/vendor/node_modules/@zmice/platform-core/dist/index.test.js.map +1 -1
- package/vendor/packages/platform-claude/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-claude/dist/index.js +12 -70
- package/vendor/packages/platform-claude/dist/index.js.map +1 -1
- package/vendor/packages/platform-codex/dist/generate.d.ts +1 -1
- package/vendor/packages/platform-codex/dist/generate.d.ts.map +1 -1
- package/vendor/packages/platform-codex/dist/generate.js +1 -1
- package/vendor/packages/platform-codex/dist/generate.js.map +1 -1
- package/vendor/packages/platform-codex/dist/index.d.ts +16 -1
- package/vendor/packages/platform-codex/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-codex/dist/index.js +268 -67
- package/vendor/packages/platform-codex/dist/index.js.map +1 -1
- package/vendor/packages/platform-codex/dist/index.test.js +102 -7
- package/vendor/packages/platform-codex/dist/index.test.js.map +1 -1
- package/vendor/packages/platform-opencode/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-opencode/dist/index.js +15 -81
- package/vendor/packages/platform-opencode/dist/index.js.map +1 -1
- package/vendor/packages/platform-qwen/dist/index.d.ts.map +1 -1
- package/vendor/packages/platform-qwen/dist/index.js +28 -84
- package/vendor/packages/platform-qwen/dist/index.js.map +1 -1
- package/vendor/packages/toolkit/src/content/agents/architect/body.md +8 -0
- package/vendor/packages/toolkit/src/content/agents/code-reviewer/body.md +10 -0
- package/vendor/packages/toolkit/src/content/agents/product-owner/body.md +8 -0
- package/vendor/packages/toolkit/src/content/commands/plan-review/body.md +3 -1
- package/vendor/packages/toolkit/src/content/commands/start/body.md +51 -2
- package/vendor/packages/toolkit/src/content/commands/start/meta.yaml +2 -2
- package/vendor/packages/toolkit/src/content/skills/branch-finish-and-cleanup/body.md +17 -0
- package/vendor/packages/toolkit/src/content/skills/browser-qa-testing/body.md +77 -520
- package/vendor/packages/toolkit/src/content/skills/ci-cd-and-automation/body.md +56 -387
- package/vendor/packages/toolkit/src/content/skills/code-review-and-quality/body.md +10 -0
- package/vendor/packages/toolkit/src/content/skills/code-simplification/body.md +55 -301
- package/vendor/packages/toolkit/src/content/skills/context-engineering/body.md +10 -0
- package/vendor/packages/toolkit/src/content/skills/continuous-learning/body.md +66 -331
- package/vendor/packages/toolkit/src/content/skills/multi-perspective-review/body.md +30 -1
- package/vendor/packages/toolkit/src/content/skills/parallel-agent-dispatch/body.md +79 -317
- package/vendor/packages/toolkit/src/content/skills/performance-optimization/body.md +60 -330
- package/vendor/packages/toolkit/src/content/skills/planning-and-task-breakdown/body.md +35 -0
- package/vendor/packages/toolkit/src/content/skills/sdd-tdd-workflow/body.md +66 -342
- package/vendor/packages/toolkit/src/content/skills/sprint-retrospective/body.md +66 -303
- package/vendor/packages/toolkit/src/content/skills/team-orchestration/body.md +81 -327
- package/vendor/packages/toolkit/src/content/skills/test-driven-development/body.md +50 -346
- package/vendor/packages/toolkit/src/content/skills/using-agent-skills/body.md +26 -2
- package/vendor/references/upstreams.yaml +5 -0
- package/dist/cli/setup.d.ts +0 -3
- package/dist/cli/setup.d.ts.map +0 -1
- package/dist/cli/setup.js +0 -41
- package/dist/cli/setup.js.map +0 -1
|
@@ -1,345 +1,75 @@
|
|
|
1
1
|
# Performance Optimization
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 角色定位
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
性能优化必须从测量开始。这个 skill 用于定位真实瓶颈、做最小修复、再次测量,并补回归保护;不用于凭感觉提前复杂化实现。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 何时使用
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- Core Web Vitals
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- 规格里有明确性能目标或预算。
|
|
10
|
+
- 用户、监控或日志报告慢。
|
|
11
|
+
- Core Web Vitals、接口延迟、吞吐、内存或 CPU 有异常。
|
|
12
|
+
- 怀疑一次变更造成性能回归。
|
|
13
|
+
- 功能会处理大数据量、高并发或关键首屏路径。
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
不适用:没有性能证据,只是担心未来可能慢。
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 快速路径
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
1. 写清性能症状和目标指标。
|
|
20
|
+
2. 建立 baseline:真实数据或可复现 synthetic 测量。
|
|
21
|
+
3. 定位瓶颈:前端、后端、数据库、网络、渲染、内存或外部依赖。
|
|
22
|
+
4. 只修当前证据指向的瓶颈。
|
|
23
|
+
5. 再次测量,确认指标改善。
|
|
24
|
+
6. 评估复杂度代价,避免为了小收益引入长期维护成本。
|
|
25
|
+
7. 加 guard:监控、benchmark、预算或回归测试。
|
|
24
26
|
|
|
25
|
-
##
|
|
27
|
+
## 指标选择
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.timeEnd('db-query');
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Where to Start Measuring
|
|
69
|
-
|
|
70
|
-
Use the symptom to decide what to measure first:
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
What is slow?
|
|
74
|
-
├── First page load
|
|
75
|
-
│ ├── Large bundle? --> Measure bundle size, check code splitting
|
|
76
|
-
│ ├── Slow server response? --> Measure TTFB in DevTools Network waterfall
|
|
77
|
-
│ │ ├── DNS long? --> Add dns-prefetch / preconnect for known origins
|
|
78
|
-
│ │ ├── TCP/TLS long? --> Enable HTTP/2, check edge deployment, keep-alive
|
|
79
|
-
│ │ └── Waiting (server) long? --> Profile backend, check queries and caching
|
|
80
|
-
│ └── Render-blocking resources? --> Check network waterfall for CSS/JS blocking
|
|
81
|
-
├── Interaction feels sluggish
|
|
82
|
-
│ ├── UI freezes on click? --> Profile main thread, look for long tasks (>50ms)
|
|
83
|
-
│ ├── Form input lag? --> Check re-renders, controlled component overhead
|
|
84
|
-
│ └── Animation jank? --> Check layout thrashing, forced reflows
|
|
85
|
-
├── Page after navigation
|
|
86
|
-
│ ├── Data loading? --> Measure API response times, check for waterfalls
|
|
87
|
-
│ └── Client rendering? --> Profile component render time, check for N+1 fetches
|
|
88
|
-
└── Backend / API
|
|
89
|
-
├── Single endpoint slow? --> Profile database queries, check indexes
|
|
90
|
-
├── All endpoints slow? --> Check connection pool, memory, CPU
|
|
91
|
-
└── Intermittent slowness? --> Check for lock contention, GC pauses, external deps
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Step 2: Identify the Bottleneck
|
|
95
|
-
|
|
96
|
-
Common bottlenecks by category:
|
|
97
|
-
|
|
98
|
-
**Frontend:**
|
|
99
|
-
|
|
100
|
-
| Symptom | Likely Cause | Investigation |
|
|
101
|
-
|---------|-------------|---------------|
|
|
102
|
-
| Slow LCP | Large images, render-blocking resources, slow server | Check network waterfall, image sizes |
|
|
103
|
-
| High CLS | Images without dimensions, late-loading content, font shifts | Check layout shift attribution |
|
|
104
|
-
| Poor INP | Heavy JavaScript on main thread, large DOM updates | Check long tasks in Performance trace |
|
|
105
|
-
| Slow initial load | Large bundle, many network requests | Check bundle size, code splitting |
|
|
106
|
-
|
|
107
|
-
**Backend:**
|
|
108
|
-
|
|
109
|
-
| Symptom | Likely Cause | Investigation |
|
|
110
|
-
|---------|-------------|---------------|
|
|
111
|
-
| Slow API responses | N+1 queries, missing indexes, unoptimized queries | Check database query log |
|
|
112
|
-
| Memory growth | Leaked references, unbounded caches, large payloads | Heap snapshot analysis |
|
|
113
|
-
| CPU spikes | Synchronous heavy computation, regex backtracking | CPU profiling |
|
|
114
|
-
| High latency | Missing caching, redundant computation, network hops | Trace requests through the stack |
|
|
115
|
-
|
|
116
|
-
### Step 3: Fix Common Anti-Patterns
|
|
117
|
-
|
|
118
|
-
#### N+1 Queries (Backend)
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
// BAD: N+1 — one query per task for the owner
|
|
122
|
-
const tasks = await db.tasks.findMany();
|
|
123
|
-
for (const task of tasks) {
|
|
124
|
-
task.owner = await db.users.findUnique({ where: { id: task.ownerId } });
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// GOOD: Single query with join/include
|
|
128
|
-
const tasks = await db.tasks.findMany({
|
|
129
|
-
include: { owner: true },
|
|
130
|
-
});
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
#### Unbounded Data Fetching
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
// BAD: Fetching all records
|
|
137
|
-
const allTasks = await db.tasks.findMany();
|
|
138
|
-
|
|
139
|
-
// GOOD: Paginated with limits
|
|
140
|
-
const tasks = await db.tasks.findMany({
|
|
141
|
-
take: 20,
|
|
142
|
-
skip: (page - 1) * 20,
|
|
143
|
-
orderBy: { createdAt: 'desc' },
|
|
144
|
-
});
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
#### Missing Image Optimization (Frontend)
|
|
148
|
-
|
|
149
|
-
```html
|
|
150
|
-
<!-- BAD: No dimensions, no format optimization -->
|
|
151
|
-
<img src="/hero.jpg" />
|
|
152
|
-
|
|
153
|
-
<!-- GOOD: Hero / LCP image — art direction + resolution switching, high priority -->
|
|
154
|
-
<!--
|
|
155
|
-
Two techniques combined:
|
|
156
|
-
- Art direction (media): different crop/composition per breakpoint
|
|
157
|
-
- Resolution switching (srcset + sizes): right file size per screen density
|
|
158
|
-
-->
|
|
159
|
-
<picture>
|
|
160
|
-
<!-- Mobile: portrait crop (8:10) -->
|
|
161
|
-
<source
|
|
162
|
-
media="(max-width: 767px)"
|
|
163
|
-
srcset="/hero-mobile-400.avif 400w, /hero-mobile-800.avif 800w"
|
|
164
|
-
sizes="100vw"
|
|
165
|
-
width="800"
|
|
166
|
-
height="1000"
|
|
167
|
-
type="image/avif"
|
|
168
|
-
/>
|
|
169
|
-
<source
|
|
170
|
-
media="(max-width: 767px)"
|
|
171
|
-
srcset="/hero-mobile-400.webp 400w, /hero-mobile-800.webp 800w"
|
|
172
|
-
sizes="100vw"
|
|
173
|
-
width="800"
|
|
174
|
-
height="1000"
|
|
175
|
-
type="image/webp"
|
|
176
|
-
/>
|
|
177
|
-
<!-- Desktop: landscape crop (2:1) -->
|
|
178
|
-
<source
|
|
179
|
-
srcset="/hero-800.avif 800w, /hero-1200.avif 1200w, /hero-1600.avif 1600w"
|
|
180
|
-
sizes="(max-width: 1200px) 100vw, 1200px"
|
|
181
|
-
width="1200"
|
|
182
|
-
height="600"
|
|
183
|
-
type="image/avif"
|
|
184
|
-
/>
|
|
185
|
-
<source
|
|
186
|
-
srcset="/hero-800.webp 800w, /hero-1200.webp 1200w, /hero-1600.webp 1600w"
|
|
187
|
-
sizes="(max-width: 1200px) 100vw, 1200px"
|
|
188
|
-
width="1200"
|
|
189
|
-
height="600"
|
|
190
|
-
type="image/webp"
|
|
191
|
-
/>
|
|
192
|
-
<img
|
|
193
|
-
src="/hero-desktop.jpg"
|
|
194
|
-
width="1200"
|
|
195
|
-
height="600"
|
|
196
|
-
fetchpriority="high"
|
|
197
|
-
alt="Hero image description"
|
|
198
|
-
/>
|
|
199
|
-
</picture>
|
|
200
|
-
|
|
201
|
-
<!-- GOOD: Below-the-fold image — lazy loaded + async decoding -->
|
|
202
|
-
<img
|
|
203
|
-
src="/content.webp"
|
|
204
|
-
width="800"
|
|
205
|
-
height="400"
|
|
206
|
-
loading="lazy"
|
|
207
|
-
decoding="async"
|
|
208
|
-
alt="Content image description"
|
|
209
|
-
/>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
#### Unnecessary Re-renders (React)
|
|
213
|
-
|
|
214
|
-
```tsx
|
|
215
|
-
// BAD: Creates new object on every render, causing children to re-render
|
|
216
|
-
function TaskList() {
|
|
217
|
-
return <TaskFilters options={{ sortBy: 'date', order: 'desc' }} />;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// GOOD: Stable reference
|
|
221
|
-
const DEFAULT_OPTIONS = { sortBy: 'date', order: 'desc' } as const;
|
|
222
|
-
function TaskList() {
|
|
223
|
-
return <TaskFilters options={DEFAULT_OPTIONS} />;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Use React.memo for expensive components
|
|
227
|
-
const TaskItem = React.memo(function TaskItem({ task }: Props) {
|
|
228
|
-
return <div>{/* expensive render */}</div>;
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
// Use useMemo for expensive computations
|
|
232
|
-
function TaskStats({ tasks }: Props) {
|
|
233
|
-
const stats = useMemo(() => calculateStats(tasks), [tasks]);
|
|
234
|
-
return <div>{stats.completed} / {stats.total}</div>;
|
|
235
|
-
}
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
#### Large Bundle Size
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
// Modern bundlers (Vite, webpack 5+) handle named imports with tree-shaking automatically,
|
|
242
|
-
// provided the dependency ships ESM and is marked `sideEffects: false` in package.json.
|
|
243
|
-
// Profile before changing import styles — the real gains come from splitting and lazy loading.
|
|
244
|
-
|
|
245
|
-
// GOOD: Dynamic import for heavy, rarely-used features
|
|
246
|
-
const ChartLibrary = lazy(() => import('./ChartLibrary'));
|
|
247
|
-
|
|
248
|
-
// GOOD: Route-level code splitting wrapped in Suspense
|
|
249
|
-
const SettingsPage = lazy(() => import('./pages/Settings'));
|
|
250
|
-
|
|
251
|
-
function App() {
|
|
252
|
-
return (
|
|
253
|
-
<Suspense fallback={<Spinner />}>
|
|
254
|
-
<SettingsPage />
|
|
255
|
-
</Suspense>
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
#### Missing Caching (Backend)
|
|
261
|
-
|
|
262
|
-
```typescript
|
|
263
|
-
// Cache frequently-read, rarely-changed data
|
|
264
|
-
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
265
|
-
let cachedConfig: AppConfig | null = null;
|
|
266
|
-
let cacheExpiry = 0;
|
|
267
|
-
|
|
268
|
-
async function getAppConfig(): Promise<AppConfig> {
|
|
269
|
-
if (cachedConfig && Date.now() < cacheExpiry) {
|
|
270
|
-
return cachedConfig;
|
|
271
|
-
}
|
|
272
|
-
cachedConfig = await db.config.findFirst();
|
|
273
|
-
cacheExpiry = Date.now() + CACHE_TTL;
|
|
274
|
-
return cachedConfig;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// HTTP caching headers for static assets
|
|
278
|
-
app.use('/static', express.static('public', {
|
|
279
|
-
maxAge: '1y', // Cache for 1 year
|
|
280
|
-
immutable: true, // Never revalidate (use content hashing in filenames)
|
|
281
|
-
}));
|
|
282
|
-
|
|
283
|
-
// Cache-Control for API responses
|
|
284
|
-
res.set('Cache-Control', 'public, max-age=300'); // 5 minutes
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
## Performance Budget
|
|
288
|
-
|
|
289
|
-
Set budgets and enforce them:
|
|
290
|
-
|
|
291
|
-
```
|
|
292
|
-
JavaScript bundle: < 200KB gzipped (initial load)
|
|
293
|
-
CSS: < 50KB gzipped
|
|
294
|
-
Images: < 200KB per image (above the fold)
|
|
295
|
-
Fonts: < 100KB total
|
|
296
|
-
API response time: < 200ms (p95)
|
|
297
|
-
Time to Interactive: < 3.5s on 4G
|
|
298
|
-
Lighthouse Performance score: ≥ 90
|
|
29
|
+
| 场景 | 优先指标 |
|
|
30
|
+
|---|---|
|
|
31
|
+
| 首屏慢 | LCP、TTFB、bundle size、network waterfall |
|
|
32
|
+
| 交互卡顿 | INP、long task、render count、main thread profile |
|
|
33
|
+
| 布局跳动 | CLS、图片尺寸、字体加载、late content |
|
|
34
|
+
| API 慢 | p95/p99 latency、query time、cache hit、payload size |
|
|
35
|
+
| 资源异常 | CPU、memory、GC、connection pool、queue depth |
|
|
36
|
+
|
|
37
|
+
默认使用能复现症状的最小指标。不要同时优化所有指标。
|
|
38
|
+
|
|
39
|
+
## 常见定位方向
|
|
40
|
+
|
|
41
|
+
- 前端首屏:大图片、render-blocking CSS/JS、bundle 过大、慢 TTFB。
|
|
42
|
+
- 前端交互:长任务、重复渲染、过大 DOM、同步计算。
|
|
43
|
+
- 数据加载:瀑布请求、N+1、过大 payload、缺少分页。
|
|
44
|
+
- 后端接口:缺索引、锁等待、连接池耗尽、重复计算。
|
|
45
|
+
- 内存/CPU:无界缓存、泄漏、正则回溯、同步重计算。
|
|
46
|
+
|
|
47
|
+
## 修复纪律
|
|
48
|
+
|
|
49
|
+
- 先证明瓶颈,再改代码。
|
|
50
|
+
- 一次只优化一个瓶颈。
|
|
51
|
+
- 保留 before / after 数字。
|
|
52
|
+
- 小收益大复杂度的优化要默认拒绝。
|
|
53
|
+
- 性能关键路径改动要补 benchmark、监控或预算门禁。
|
|
54
|
+
|
|
55
|
+
## 输出契约
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Performance evidence:
|
|
59
|
+
- Symptom:
|
|
60
|
+
- Target:
|
|
61
|
+
- Baseline:
|
|
62
|
+
- Bottleneck:
|
|
63
|
+
- Change:
|
|
64
|
+
- After:
|
|
65
|
+
- Regression guard:
|
|
66
|
+
- Trade-off:
|
|
299
67
|
```
|
|
300
68
|
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
# Bundle size check
|
|
304
|
-
npx bundlesize --config bundlesize.config.json
|
|
69
|
+
推荐结论:
|
|
305
70
|
|
|
306
|
-
|
|
307
|
-
|
|
71
|
+
```text
|
|
72
|
+
Recommendation: <optimize / monitor / defer / revert> because <baseline, measured impact, complexity cost, and rejected alternative>.
|
|
308
73
|
```
|
|
309
74
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
For detailed performance checklists, optimization commands, and anti-pattern reference, see `references/performance-checklist.md`.
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
## Common Rationalizations
|
|
316
|
-
|
|
317
|
-
| Rationalization | Reality |
|
|
318
|
-
|---|---|
|
|
319
|
-
| "We'll optimize later" | Performance debt compounds. Fix obvious anti-patterns now, defer micro-optimizations. |
|
|
320
|
-
| "It's fast on my machine" | Your machine isn't the user's. Profile on representative hardware and networks. |
|
|
321
|
-
| "This optimization is obvious" | If you didn't measure, you don't know. Profile first. |
|
|
322
|
-
| "Users won't notice 100ms" | Research shows 100ms delays impact conversion rates. Users notice more than you think. |
|
|
323
|
-
| "The framework handles performance" | Frameworks prevent some issues but can't fix N+1 queries or oversized bundles. |
|
|
324
|
-
|
|
325
|
-
## Red Flags
|
|
326
|
-
|
|
327
|
-
- Optimization without profiling data to justify it
|
|
328
|
-
- N+1 query patterns in data fetching
|
|
329
|
-
- List endpoints without pagination
|
|
330
|
-
- Images without dimensions, lazy loading, or responsive sizes
|
|
331
|
-
- Bundle size growing without review
|
|
332
|
-
- No performance monitoring in production
|
|
333
|
-
- `React.memo` and `useMemo` everywhere (overusing is as bad as underusing)
|
|
334
|
-
|
|
335
|
-
## Verification
|
|
336
|
-
|
|
337
|
-
After any performance-related change:
|
|
338
|
-
|
|
339
|
-
- [ ] Before and after measurements exist (specific numbers)
|
|
340
|
-
- [ ] The specific bottleneck is identified and addressed
|
|
341
|
-
- [ ] Core Web Vitals are within "Good" thresholds
|
|
342
|
-
- [ ] Bundle size hasn't increased significantly
|
|
343
|
-
- [ ] No N+1 queries in new data fetching code
|
|
344
|
-
- [ ] Performance budget passes in CI (if configured)
|
|
345
|
-
- [ ] Existing tests still pass (optimization didn't break behavior)
|
|
75
|
+
没有 baseline 和 after 数据,不要声明性能优化成立。
|
|
@@ -28,18 +28,53 @@
|
|
|
28
28
|
- Files likely touched
|
|
29
29
|
5. 排出顺序,并设置阶段性检查点
|
|
30
30
|
|
|
31
|
+
## 提问纪律
|
|
32
|
+
|
|
33
|
+
- 能从规格、代码、配置、测试或用户原话判断的,不问。
|
|
34
|
+
- 只有缺失信息会改变架构、数据模型、任务顺序、破坏性操作或并行边界时才问。
|
|
35
|
+
- 一轮最多问 1-3 个关键问题,问题要说明选择会避免什么风险或解锁什么能力。
|
|
36
|
+
- 用户已经给出偏好时,把它写进计划假设;不要把偏好扩展成长期配置或跨会话记忆授权。
|
|
37
|
+
|
|
38
|
+
## 计划产物要求
|
|
39
|
+
|
|
40
|
+
计划不是任务名列表,至少要包含:
|
|
41
|
+
|
|
42
|
+
- `decision log`:关键取舍和采用原因
|
|
43
|
+
- `evidence`:读取过的规格、代码、配置、测试或上游证据
|
|
44
|
+
- `open risks`:尚未证明的风险和验证方式
|
|
45
|
+
- `fan-out eligibility`:是否能并行、按哪些文件或模块拆、是否需要 `zc team plan`
|
|
46
|
+
- `fan-in gate`:实现后如何合流、审查、验证和清理
|
|
47
|
+
|
|
48
|
+
## 决策日志格式
|
|
49
|
+
|
|
50
|
+
每个关键取舍都要写成可审查的推荐,而不是只写“建议这样做”:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
Recommendation: <chosen action> because <evidence and trade-off>.
|
|
54
|
+
- Chosen:
|
|
55
|
+
- Rejected alternative:
|
|
56
|
+
- Evidence:
|
|
57
|
+
- Cost / risk:
|
|
58
|
+
- Verification gate:
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
理由必须说明被放弃的替代方案,以及当前选择为什么更适合本任务。不能只写“更稳”“更简单”“更符合最佳实践”。
|
|
62
|
+
|
|
31
63
|
## 成功标准
|
|
32
64
|
|
|
33
65
|
- 每个任务都能独立实现、测试和验证
|
|
34
66
|
- 任务粒度足够小,不会一次触碰过多文件
|
|
35
67
|
- 依赖顺序和可并行项是显式的
|
|
36
68
|
- 人类看完计划后能明确判断“方案对不对”
|
|
69
|
+
- 计划中的问题和风险都能落到后续验证命令或审查项
|
|
70
|
+
- 并行任务必须有明确文件所有权或隔离理由
|
|
37
71
|
|
|
38
72
|
## 相关原则
|
|
39
73
|
|
|
40
74
|
- 计划服务实现,不是形式化文档
|
|
41
75
|
- 先控制复杂度,再讨论并行度
|
|
42
76
|
- 任务必须能验证,不能只写动作名
|
|
77
|
+
- 计划阶段发现的问题要进入计划本身,不能只留在聊天里
|
|
43
78
|
|
|
44
79
|
## 与其他技能的衔接
|
|
45
80
|
|