ccgx-workflow 1.0.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/LICENSE +22 -0
- package/README.md +469 -0
- package/README.zh-CN.md +466 -0
- package/bin/ccg.mjs +2 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +173 -0
- package/dist/index.d.mts +1774 -0
- package/dist/index.d.ts +1774 -0
- package/dist/index.mjs +2029 -0
- package/dist/shared/ccgx-workflow.WgUzkiC3.mjs +5248 -0
- package/package.json +129 -0
- package/templates/commands/agents/assumptions-analyzer.md +129 -0
- package/templates/commands/agents/code-fixer.md +292 -0
- package/templates/commands/agents/codebase-mapper.md +152 -0
- package/templates/commands/agents/debug-session-manager.md +247 -0
- package/templates/commands/agents/debugger.md +111 -0
- package/templates/commands/agents/eval-auditor.md +171 -0
- package/templates/commands/agents/framework-selector.md +152 -0
- package/templates/commands/agents/get-current-datetime.md +29 -0
- package/templates/commands/agents/init-architect.md +114 -0
- package/templates/commands/agents/integration-checker.md +163 -0
- package/templates/commands/agents/interface-auditor.md +170 -0
- package/templates/commands/agents/nyquist-auditor.md +131 -0
- package/templates/commands/agents/pattern-mapper.md +111 -0
- package/templates/commands/agents/phase-runner.md +321 -0
- package/templates/commands/agents/plan-checker.md +255 -0
- package/templates/commands/agents/planner.md +320 -0
- package/templates/commands/agents/team-architect.md +186 -0
- package/templates/commands/agents/team-qa.md +121 -0
- package/templates/commands/agents/team-reviewer.md +157 -0
- package/templates/commands/agents/ui-ux-designer.md +573 -0
- package/templates/commands/agents/verifier.md +274 -0
- package/templates/commands/analyze.md +210 -0
- package/templates/commands/autonomous.md +792 -0
- package/templates/commands/cancel.md +132 -0
- package/templates/commands/clean-branches.md +117 -0
- package/templates/commands/codex-exec.md +404 -0
- package/templates/commands/commit.md +151 -0
- package/templates/commands/context.md +332 -0
- package/templates/commands/debate.md +165 -0
- package/templates/commands/debug.md +226 -0
- package/templates/commands/enhance.md +64 -0
- package/templates/commands/execute.md +380 -0
- package/templates/commands/init.md +123 -0
- package/templates/commands/optimize.md +217 -0
- package/templates/commands/plan.md +373 -0
- package/templates/commands/result.md +106 -0
- package/templates/commands/review.md +338 -0
- package/templates/commands/rollback.md +116 -0
- package/templates/commands/spec-impl.md +139 -0
- package/templates/commands/spec-init.md +101 -0
- package/templates/commands/spec-plan.md +210 -0
- package/templates/commands/spec-research.md +152 -0
- package/templates/commands/spec-review.md +120 -0
- package/templates/commands/status.md +206 -0
- package/templates/commands/team-exec.md +265 -0
- package/templates/commands/test.md +236 -0
- package/templates/commands/verify-work.md +338 -0
- package/templates/commands/verify.md +66 -0
- package/templates/commands/workflow.md +190 -0
- package/templates/commands/worktree.md +128 -0
- package/templates/hooks/ccg-context-monitor.js +159 -0
- package/templates/hooks/ccg-session-state.cjs +510 -0
- package/templates/hooks/ccg-statusline.js +142 -0
- package/templates/output-styles/abyss-command.md +56 -0
- package/templates/output-styles/abyss-concise.md +89 -0
- package/templates/output-styles/abyss-cultivator.md +302 -0
- package/templates/output-styles/abyss-ritual.md +70 -0
- package/templates/output-styles/engineer-professional.md +89 -0
- package/templates/output-styles/laowang-engineer.md +127 -0
- package/templates/output-styles/nekomata-engineer.md +120 -0
- package/templates/output-styles/ojousama-engineer.md +121 -0
- package/templates/prompts/claude/analyzer.md +59 -0
- package/templates/prompts/claude/architect.md +54 -0
- package/templates/prompts/claude/debugger.md +71 -0
- package/templates/prompts/claude/optimizer.md +73 -0
- package/templates/prompts/claude/reviewer.md +63 -0
- package/templates/prompts/claude/tester.md +69 -0
- package/templates/prompts/codex/analyzer.md +58 -0
- package/templates/prompts/codex/architect.md +54 -0
- package/templates/prompts/codex/debugger.md +74 -0
- package/templates/prompts/codex/optimizer.md +81 -0
- package/templates/prompts/codex/reviewer.md +73 -0
- package/templates/prompts/codex/tester.md +62 -0
- package/templates/prompts/gemini/analyzer.md +61 -0
- package/templates/prompts/gemini/architect.md +55 -0
- package/templates/prompts/gemini/debugger.md +78 -0
- package/templates/prompts/gemini/frontend.md +64 -0
- package/templates/prompts/gemini/optimizer.md +84 -0
- package/templates/prompts/gemini/reviewer.md +80 -0
- package/templates/prompts/gemini/tester.md +68 -0
- package/templates/rules/ccg-skill-routing.md +83 -0
- package/templates/rules/ccg-skills.md +71 -0
- package/templates/scripts/ccg-phase-runner-launcher.mjs +467 -0
- package/templates/scripts/invoke-model.mjs +949 -0
- package/templates/scripts/repatch-gemini-plugin.mjs +194 -0
- package/templates/skills/SKILL.md +92 -0
- package/templates/skills/domains/ai/SKILL.md +35 -0
- package/templates/skills/domains/ai/agent-dev.md +242 -0
- package/templates/skills/domains/ai/llm-security.md +288 -0
- package/templates/skills/domains/ai/prompt-and-eval.md +279 -0
- package/templates/skills/domains/ai/rag-system.md +542 -0
- package/templates/skills/domains/architecture/SKILL.md +43 -0
- package/templates/skills/domains/architecture/api-design.md +225 -0
- package/templates/skills/domains/architecture/caching.md +299 -0
- package/templates/skills/domains/architecture/cloud-native.md +285 -0
- package/templates/skills/domains/architecture/message-queue.md +329 -0
- package/templates/skills/domains/architecture/security-arch.md +297 -0
- package/templates/skills/domains/data-engineering/SKILL.md +208 -0
- package/templates/skills/domains/development/SKILL.md +47 -0
- package/templates/skills/domains/development/cpp.md +246 -0
- package/templates/skills/domains/development/go.md +323 -0
- package/templates/skills/domains/development/java.md +277 -0
- package/templates/skills/domains/development/python.md +288 -0
- package/templates/skills/domains/development/rust.md +313 -0
- package/templates/skills/domains/development/shell.md +313 -0
- package/templates/skills/domains/development/typescript.md +277 -0
- package/templates/skills/domains/devops/SKILL.md +40 -0
- package/templates/skills/domains/devops/cost-optimization.md +272 -0
- package/templates/skills/domains/devops/database.md +217 -0
- package/templates/skills/domains/devops/devsecops.md +198 -0
- package/templates/skills/domains/devops/git-workflow.md +181 -0
- package/templates/skills/domains/devops/observability.md +280 -0
- package/templates/skills/domains/devops/performance.md +336 -0
- package/templates/skills/domains/devops/testing.md +283 -0
- package/templates/skills/domains/frontend-design/SKILL.md +244 -0
- package/templates/skills/domains/frontend-design/agents/openai.yaml +4 -0
- package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +121 -0
- package/templates/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
- package/templates/skills/domains/frontend-design/component-patterns.md +202 -0
- package/templates/skills/domains/frontend-design/engineering.md +287 -0
- package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +142 -0
- package/templates/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
- package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +139 -0
- package/templates/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
- package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +145 -0
- package/templates/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
- package/templates/skills/domains/frontend-design/reference/color-and-contrast.md +132 -0
- package/templates/skills/domains/frontend-design/reference/interaction-design.md +195 -0
- package/templates/skills/domains/frontend-design/reference/motion-design.md +99 -0
- package/templates/skills/domains/frontend-design/reference/responsive-design.md +114 -0
- package/templates/skills/domains/frontend-design/reference/spatial-design.md +100 -0
- package/templates/skills/domains/frontend-design/reference/typography.md +133 -0
- package/templates/skills/domains/frontend-design/reference/ux-writing.md +107 -0
- package/templates/skills/domains/frontend-design/state-management.md +680 -0
- package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -0
- package/templates/skills/domains/frontend-design/ux-principles.md +156 -0
- package/templates/skills/domains/infrastructure/SKILL.md +201 -0
- package/templates/skills/domains/mobile/SKILL.md +225 -0
- package/templates/skills/domains/orchestration/SKILL.md +30 -0
- package/templates/skills/domains/orchestration/multi-agent.md +263 -0
- package/templates/skills/domains/security/SKILL.md +73 -0
- package/templates/skills/domains/security/blue-team.md +436 -0
- package/templates/skills/domains/security/code-audit.md +265 -0
- package/templates/skills/domains/security/pentest.md +226 -0
- package/templates/skills/domains/security/red-team.md +374 -0
- package/templates/skills/domains/security/threat-intel.md +372 -0
- package/templates/skills/domains/security/vuln-research.md +369 -0
- package/templates/skills/impeccable/adapt/SKILL.md +201 -0
- package/templates/skills/impeccable/animate/SKILL.md +176 -0
- package/templates/skills/impeccable/arrange/SKILL.md +126 -0
- package/templates/skills/impeccable/audit/SKILL.md +149 -0
- package/templates/skills/impeccable/bolder/SKILL.md +118 -0
- package/templates/skills/impeccable/clarify/SKILL.md +185 -0
- package/templates/skills/impeccable/colorize/SKILL.md +144 -0
- package/templates/skills/impeccable/critique/SKILL.md +203 -0
- package/templates/skills/impeccable/critique/reference/cognitive-load.md +106 -0
- package/templates/skills/impeccable/critique/reference/heuristics-scoring.md +234 -0
- package/templates/skills/impeccable/critique/reference/personas.md +178 -0
- package/templates/skills/impeccable/delight/SKILL.md +305 -0
- package/templates/skills/impeccable/distill/SKILL.md +123 -0
- package/templates/skills/impeccable/extract/SKILL.md +94 -0
- package/templates/skills/impeccable/harden/SKILL.md +357 -0
- package/templates/skills/impeccable/normalize/SKILL.md +72 -0
- package/templates/skills/impeccable/onboard/SKILL.md +248 -0
- package/templates/skills/impeccable/optimize/SKILL.md +268 -0
- package/templates/skills/impeccable/overdrive/SKILL.md +143 -0
- package/templates/skills/impeccable/polish/SKILL.md +205 -0
- package/templates/skills/impeccable/quieter/SKILL.md +104 -0
- package/templates/skills/impeccable/teach-impeccable/SKILL.md +72 -0
- package/templates/skills/impeccable/typeset/SKILL.md +117 -0
- package/templates/skills/orchestration/multi-agent/SKILL.md +533 -0
- package/templates/skills/run_skill.js +129 -0
- package/templates/skills/scrapling/SKILL.md +98 -0
- package/templates/skills/scrapling/references/api-quick-ref.md +127 -0
- package/templates/skills/scrapling/references/cookie-vault.md +56 -0
- package/templates/skills/scrapling/references/maintenance.md +79 -0
- package/templates/skills/scrapling/references/site-patterns.md +86 -0
- package/templates/skills/scrapling/references/troubleshooting.md +95 -0
- package/templates/skills/scrapling/templates/basic_fetch.py +19 -0
- package/templates/skills/scrapling/templates/parse_only.py +15 -0
- package/templates/skills/scrapling/templates/session_login.py +19 -0
- package/templates/skills/scrapling/templates/stealth_cloudflare.py +28 -0
- package/templates/skills/tools/extract-learnings/SKILL.md +77 -0
- package/templates/skills/tools/forensics/SKILL.md +89 -0
- package/templates/skills/tools/gen-docs/SKILL.md +116 -0
- package/templates/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
- package/templates/skills/tools/health/SKILL.md +121 -0
- package/templates/skills/tools/lib/shared.js +98 -0
- package/templates/skills/tools/map-codebase/SKILL.md +118 -0
- package/templates/skills/tools/override-refusal/SKILL.md +53 -0
- package/templates/skills/tools/override-refusal/agents/openai.yaml +4 -0
- package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -0
- package/templates/skills/tools/verify-change/SKILL.md +143 -0
- package/templates/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
- package/templates/skills/tools/verify-module/SKILL.md +130 -0
- package/templates/skills/tools/verify-module/scripts/module_scanner.js +171 -0
- package/templates/skills/tools/verify-quality/SKILL.md +163 -0
- package/templates/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
- package/templates/skills/tools/verify-security/SKILL.md +146 -0
- package/templates/skills/tools/verify-security/scripts/security_scanner.js +283 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# 组件模式
|
|
2
|
+
|
|
3
|
+
## 布局模板
|
|
4
|
+
|
|
5
|
+
### 经典布局模式
|
|
6
|
+
圣杯布局(header/nav/main/aside/footer)、卡片网格、侧边栏、仪表盘。优先使用Grid,Flexbox做一维布局。
|
|
7
|
+
|
|
8
|
+
```css
|
|
9
|
+
.layout {
|
|
10
|
+
display: grid;
|
|
11
|
+
grid-template:
|
|
12
|
+
"header header" auto
|
|
13
|
+
"nav main" 1fr
|
|
14
|
+
"nav aside" auto
|
|
15
|
+
"footer footer" auto
|
|
16
|
+
/ 200px 1fr;
|
|
17
|
+
gap: 1rem;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
}
|
|
20
|
+
@media (max-width: 768px) {
|
|
21
|
+
.layout {
|
|
22
|
+
grid-template: "header" "nav" "main" "aside" "footer" / 1fr;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Flexbox卡片网格
|
|
28
|
+
```css
|
|
29
|
+
.card-grid {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
gap: 1.5rem;
|
|
33
|
+
}
|
|
34
|
+
.card {
|
|
35
|
+
flex: 1 1 300px;
|
|
36
|
+
max-width: 400px;
|
|
37
|
+
padding: 1.5rem;
|
|
38
|
+
border-radius: 8px;
|
|
39
|
+
box-shadow: var(--shadow-2);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 响应式设计
|
|
44
|
+
|
|
45
|
+
### 响应式断点策略
|
|
46
|
+
移动优先:320px基准→640px(sm)→768px(md)→1024px(lg)→1280px(xl)。使用em单位断点(除以16)。优先容器查询。
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
.card-container {
|
|
50
|
+
container-type: inline-size;
|
|
51
|
+
}
|
|
52
|
+
.card {
|
|
53
|
+
padding: 1rem;
|
|
54
|
+
}
|
|
55
|
+
@container (min-width: 400px) {
|
|
56
|
+
.card {
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-columns: 150px 1fr;
|
|
59
|
+
gap: 1rem;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 交互模式
|
|
65
|
+
|
|
66
|
+
### 微交互设计原则
|
|
67
|
+
反馈即时(<100ms)、过渡流畅(200-300ms)、状态清晰(hover/active/focus)、减少认知负担。
|
|
68
|
+
|
|
69
|
+
```css
|
|
70
|
+
.btn {
|
|
71
|
+
transition: all 0.2s ease;
|
|
72
|
+
}
|
|
73
|
+
.btn:hover {
|
|
74
|
+
transform: translateY(-2px);
|
|
75
|
+
box-shadow: var(--shadow-3);
|
|
76
|
+
}
|
|
77
|
+
.btn:active {
|
|
78
|
+
transform: translateY(0);
|
|
79
|
+
}
|
|
80
|
+
.btn:focus-visible {
|
|
81
|
+
outline: 2px solid var(--primary);
|
|
82
|
+
outline-offset: 2px;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 动画
|
|
87
|
+
|
|
88
|
+
### CSS关键帧动画
|
|
89
|
+
```css
|
|
90
|
+
@keyframes fadeInUp {
|
|
91
|
+
from {
|
|
92
|
+
opacity: 0;
|
|
93
|
+
transform: translateY(20px);
|
|
94
|
+
}
|
|
95
|
+
to {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
transform: translateY(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
.animate-in {
|
|
101
|
+
animation: fadeInUp 0.4s ease-out;
|
|
102
|
+
}
|
|
103
|
+
@media (prefers-reduced-motion: reduce) {
|
|
104
|
+
.animate-in {
|
|
105
|
+
animation: none;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Framer Motion模板
|
|
111
|
+
```javascript
|
|
112
|
+
const fadeInUp = {
|
|
113
|
+
initial: { opacity: 0, y: 20 },
|
|
114
|
+
animate: { opacity: 1, y: 0 },
|
|
115
|
+
transition: { duration: 0.4, ease: "easeOut" }
|
|
116
|
+
};
|
|
117
|
+
const stagger = {
|
|
118
|
+
animate: { transition: { staggerChildren: 0.1 } }
|
|
119
|
+
};
|
|
120
|
+
<motion.div variants={stagger}>
|
|
121
|
+
<motion.div variants={fadeInUp} />
|
|
122
|
+
</motion.div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 表单设计
|
|
126
|
+
|
|
127
|
+
### 表单UX模式
|
|
128
|
+
标签上置、内联验证、清晰错误提示、禁用状态明显、必填标记、合理分组、自动聚焦首字段。
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
.form-field {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
gap: 0.5rem;
|
|
135
|
+
}
|
|
136
|
+
.input {
|
|
137
|
+
padding: 0.75rem;
|
|
138
|
+
border: 1px solid #d1d5db;
|
|
139
|
+
border-radius: 6px;
|
|
140
|
+
font-size: 1rem;
|
|
141
|
+
transition: border-color 0.2s;
|
|
142
|
+
}
|
|
143
|
+
.input:focus {
|
|
144
|
+
outline: none;
|
|
145
|
+
border-color: var(--primary);
|
|
146
|
+
box-shadow: 0 0 0 3px rgba(59,130,246,0.1);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 卡片组件
|
|
151
|
+
|
|
152
|
+
### 玻璃拟态卡片
|
|
153
|
+
```css
|
|
154
|
+
.glass-card {
|
|
155
|
+
background: rgba(255, 255, 255, 0.1);
|
|
156
|
+
backdrop-filter: blur(10px);
|
|
157
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
158
|
+
border-radius: 12px;
|
|
159
|
+
padding: 1.5rem;
|
|
160
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 导航模式
|
|
165
|
+
|
|
166
|
+
### 响应式导航栏
|
|
167
|
+
```css
|
|
168
|
+
.nav {
|
|
169
|
+
display: flex;
|
|
170
|
+
justify-content: space-between;
|
|
171
|
+
align-items: center;
|
|
172
|
+
padding: 1rem;
|
|
173
|
+
}
|
|
174
|
+
.nav-links {
|
|
175
|
+
display: flex;
|
|
176
|
+
gap: 2rem;
|
|
177
|
+
}
|
|
178
|
+
@media (max-width: 768px) {
|
|
179
|
+
.nav-links {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
.nav-links.open {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
position: absolute;
|
|
186
|
+
top: 100%;
|
|
187
|
+
left: 0;
|
|
188
|
+
right: 0;
|
|
189
|
+
background: white;
|
|
190
|
+
padding: 1rem;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 审查清单
|
|
196
|
+
|
|
197
|
+
- [ ] 响应式适配
|
|
198
|
+
- [ ] 交互状态完整
|
|
199
|
+
- [ ] 无障碍支持
|
|
200
|
+
- [ ] 性能优化
|
|
201
|
+
- [ ] 浏览器兼容
|
|
202
|
+
- [ ] 动画流畅
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-engineering
|
|
3
|
+
description: 前端工程化。性能优化(Web Vitals、懒加载、虚拟滚动)、测试(Vitest、Playwright、MSW)、构建工具(Vite、Webpack、esbuild)。当用户提到性能优化、前端测试、构建工具、代码分割时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 前端工程化 · Frontend Engineering
|
|
7
|
+
|
|
8
|
+
## 一、性能优化
|
|
9
|
+
|
|
10
|
+
### Core Web Vitals
|
|
11
|
+
|
|
12
|
+
| 指标 | 含义 | 目标值 |
|
|
13
|
+
|------|------|--------|
|
|
14
|
+
| LCP | Largest Contentful Paint | < 2.5s |
|
|
15
|
+
| FID | First Input Delay | < 100ms |
|
|
16
|
+
| CLS | Cumulative Layout Shift | < 0.1 |
|
|
17
|
+
| FCP | First Contentful Paint | < 1.8s |
|
|
18
|
+
| TTI | Time to Interactive | < 3.8s |
|
|
19
|
+
|
|
20
|
+
### 性能决策树
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
加载慢 → Bundle 大?代码分割 + Tree Shaking | 资源多?懒加载 + 预加载 | 网络慢?CDN + 压缩
|
|
24
|
+
渲染慢 → 列表长?虚拟滚动 | 重渲染?React.memo + useMemo | 布局抖动?固定尺寸
|
|
25
|
+
交互慢 → JS 阻塞?Web Worker + startTransition | 动画卡顿?CSS 动画 + rAF
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 代码分割
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// 路由级别 — React.lazy + Suspense
|
|
32
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'))
|
|
33
|
+
|
|
34
|
+
// 组件级别 — 按需加载重量级组件
|
|
35
|
+
const HeavyChart = lazy(() => import('./components/HeavyChart'))
|
|
36
|
+
|
|
37
|
+
// Vite manualChunks
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
build: {
|
|
40
|
+
rollupOptions: {
|
|
41
|
+
output: {
|
|
42
|
+
manualChunks: {
|
|
43
|
+
'react-vendor': ['react', 'react-dom'],
|
|
44
|
+
'ui': ['@mui/material'],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 虚拟滚动
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { FixedSizeList } from 'react-window'
|
|
56
|
+
|
|
57
|
+
function VirtualList({ items }: { items: Item[] }) {
|
|
58
|
+
return (
|
|
59
|
+
<FixedSizeList height={600} itemCount={items.length} itemSize={50} width="100%">
|
|
60
|
+
{({ index, style }) => <div style={style}>{items[index].name}</div>}
|
|
61
|
+
</FixedSizeList>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### React 性能要点
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// memo 避免重渲染
|
|
70
|
+
const Row = memo(function Row({ item, onClick }: Props) {
|
|
71
|
+
return <div onClick={() => onClick(item.id)}>{item.name}</div>
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// useMemo 缓存计算 + useCallback 缓存回调
|
|
75
|
+
const filtered = useMemo(() => data.filter(x => x.name.includes(q)), [data, q])
|
|
76
|
+
const handleClick = useCallback((id: string) => select(id), [])
|
|
77
|
+
|
|
78
|
+
// startTransition 低优先级更新
|
|
79
|
+
startTransition(() => setResults(heavySearch(query)))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 资源优化 Checklist
|
|
83
|
+
|
|
84
|
+
- 图片:WebP 格式 + `loading="lazy"` + 响应式 `<picture>`
|
|
85
|
+
- 字体:`font-display: swap` + `preload` woff2
|
|
86
|
+
- 预加载:`dns-prefetch` → `preconnect` → `preload` → `prefetch`
|
|
87
|
+
- 压缩:Gzip/Brotli + HTTP/2
|
|
88
|
+
|
|
89
|
+
### 性能监控
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { onCLS, onFID, onLCP } from 'web-vitals'
|
|
93
|
+
onCLS(sendToAnalytics)
|
|
94
|
+
onFID(sendToAnalytics)
|
|
95
|
+
onLCP(sendToAnalytics)
|
|
96
|
+
|
|
97
|
+
// 自定义指标
|
|
98
|
+
performance.mark('start')
|
|
99
|
+
doWork()
|
|
100
|
+
performance.mark('end')
|
|
101
|
+
performance.measure('work', 'start', 'end')
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 二、测试
|
|
105
|
+
|
|
106
|
+
### 测试金字塔
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
/\ E2E (10%) — Playwright
|
|
110
|
+
/--\ 集成 (20%) — Testing Library + MSW
|
|
111
|
+
/----\ 单元 (70%) — Vitest
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Vitest 配置
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// vitest.config.ts
|
|
118
|
+
export default defineConfig({
|
|
119
|
+
test: {
|
|
120
|
+
globals: true,
|
|
121
|
+
environment: 'jsdom',
|
|
122
|
+
setupFiles: './src/test/setup.ts',
|
|
123
|
+
coverage: {
|
|
124
|
+
provider: 'v8',
|
|
125
|
+
thresholds: { lines: 80, functions: 80, branches: 75 },
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 单元测试
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
describe('formatCurrency', () => {
|
|
135
|
+
it('formats number', () => expect(formatCurrency(1234.56)).toBe('$1,234.56'))
|
|
136
|
+
it('handles zero', () => expect(formatCurrency(0)).toBe('$0.00'))
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 组件测试
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
144
|
+
|
|
145
|
+
it('calls onClick', () => {
|
|
146
|
+
const fn = vi.fn()
|
|
147
|
+
render(<Button onClick={fn}>Click</Button>)
|
|
148
|
+
fireEvent.click(screen.getByText('Click'))
|
|
149
|
+
expect(fn).toHaveBeenCalledTimes(1)
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### MSW Mock
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { http, HttpResponse } from 'msw'
|
|
157
|
+
import { setupServer } from 'msw/node'
|
|
158
|
+
|
|
159
|
+
const server = setupServer(
|
|
160
|
+
http.get('/api/users/:id', ({ params }) =>
|
|
161
|
+
HttpResponse.json({ id: params.id, name: 'John' })
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
beforeAll(() => server.listen())
|
|
165
|
+
afterEach(() => server.resetHandlers())
|
|
166
|
+
afterAll(() => server.close())
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Playwright E2E
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// playwright.config.ts 核心
|
|
173
|
+
export default defineConfig({
|
|
174
|
+
testDir: './e2e',
|
|
175
|
+
use: { baseURL: 'http://localhost:3000', trace: 'on-first-retry' },
|
|
176
|
+
webServer: { command: 'npm run dev', url: 'http://localhost:3000' },
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// Page Object 模式
|
|
180
|
+
class LoginPage {
|
|
181
|
+
constructor(private page: Page) {}
|
|
182
|
+
async login(email: string, password: string) {
|
|
183
|
+
await this.page.fill('[name="email"]', email)
|
|
184
|
+
await this.page.fill('[name="password"]', password)
|
|
185
|
+
await this.page.click('[type="submit"]')
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 测试 Checklist
|
|
191
|
+
|
|
192
|
+
- 遵循 AAA 模式(Arrange / Act / Assert)
|
|
193
|
+
- 测试行为而非实现
|
|
194
|
+
- Mock 外部依赖(API、时间)
|
|
195
|
+
- 测试边界条件和错误路径
|
|
196
|
+
- CI 中自动运行 + 覆盖率门禁 80%+
|
|
197
|
+
|
|
198
|
+
## 三、构建工具
|
|
199
|
+
|
|
200
|
+
### 选型决策
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
新项目 React/Vue → Vite | Next.js → Turbopack | 零配置 → Parcel
|
|
204
|
+
库开发 → Rollup / esbuild
|
|
205
|
+
老项目复杂配置 → 保持 Webpack | 可迁移 → Vite
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 工具对比
|
|
209
|
+
|
|
210
|
+
| 工具 | 冷启动 | HMR | 生产构建 | 生态 |
|
|
211
|
+
|------|--------|-----|----------|------|
|
|
212
|
+
| Vite | < 1s | < 100ms | 10-30s | 成熟 |
|
|
213
|
+
| Webpack | 10-30s | 1-3s | 30-60s | 最丰富 |
|
|
214
|
+
| Turbopack | < 1s | < 100ms | 10-20s | 新兴 |
|
|
215
|
+
| esbuild | < 1s | N/A | 5-10s | 基础 |
|
|
216
|
+
|
|
217
|
+
### Vite 核心配置
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
export default defineConfig({
|
|
221
|
+
plugins: [react()],
|
|
222
|
+
resolve: { alias: { '@': path.resolve(__dirname, './src') } },
|
|
223
|
+
server: {
|
|
224
|
+
port: 3000,
|
|
225
|
+
proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } },
|
|
226
|
+
},
|
|
227
|
+
build: {
|
|
228
|
+
minify: 'terser',
|
|
229
|
+
terserOptions: { compress: { drop_console: true } },
|
|
230
|
+
rollupOptions: {
|
|
231
|
+
output: {
|
|
232
|
+
manualChunks: { 'react-vendor': ['react', 'react-dom'] },
|
|
233
|
+
entryFileNames: 'assets/[name].[hash].js',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
optimizeDeps: { include: ['react', 'react-dom'] },
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Webpack 生产优化要点
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
optimization: {
|
|
245
|
+
minimize: true,
|
|
246
|
+
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
|
|
247
|
+
splitChunks: {
|
|
248
|
+
chunks: 'all',
|
|
249
|
+
cacheGroups: {
|
|
250
|
+
react: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, priority: 20 },
|
|
251
|
+
vendor: { test: /[\\/]node_modules[\\/]/, priority: 10 },
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
runtimeChunk: 'single',
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Webpack → Vite 迁移要点
|
|
259
|
+
|
|
260
|
+
1. `npm install -D vite @vitejs/plugin-react`
|
|
261
|
+
2. `index.html` 移到根目录,加 `<script type="module" src="/src/main.tsx">`
|
|
262
|
+
3. `REACT_APP_*` → `VITE_*`,`process.env` → `import.meta.env`
|
|
263
|
+
4. `require()` → `import`
|
|
264
|
+
|
|
265
|
+
### 构建 Checklist
|
|
266
|
+
|
|
267
|
+
- 合理代码分割(路由级 + 第三方库分组)
|
|
268
|
+
- Tree Shaking + 压缩(terser / esbuild)
|
|
269
|
+
- 文件名哈希实现长期缓存
|
|
270
|
+
- Source map 仅 dev 或 hidden
|
|
271
|
+
- 定期 `webpack-bundle-analyzer` / `rollup-plugin-visualizer` 审计
|
|
272
|
+
- CI 缓存 `node_modules` + 构建产物
|
|
273
|
+
|
|
274
|
+
## 工具速查
|
|
275
|
+
|
|
276
|
+
| 类别 | 推荐工具 |
|
|
277
|
+
|------|----------|
|
|
278
|
+
| 构建 | Vite (新项目) / Webpack (复杂项目) |
|
|
279
|
+
| 单元测试 | Vitest |
|
|
280
|
+
| 组件测试 | Testing Library |
|
|
281
|
+
| E2E | Playwright |
|
|
282
|
+
| API Mock | MSW |
|
|
283
|
+
| 性能监控 | web-vitals + Lighthouse |
|
|
284
|
+
| Bundle 分析 | webpack-bundle-analyzer / rollup-plugin-visualizer |
|
|
285
|
+
| 视觉回归 | Playwright screenshots / Chromatic |
|
|
286
|
+
|
|
287
|
+
---
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: glassmorphism
|
|
3
|
+
description: Glassmorphism 玻璃态设计(毛玻璃、透明度、模糊、分层深度)。
|
|
4
|
+
license: MIT
|
|
5
|
+
user-invocable: false
|
|
6
|
+
disable-model-invocation: false
|
|
7
|
+
context: fork
|
|
8
|
+
paths: "*.tsx,*.jsx,*.vue,*.svelte,*.css,*.scss"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Glassmorphism Design Spec
|
|
12
|
+
|
|
13
|
+
## 4 Core Elements
|
|
14
|
+
|
|
15
|
+
1. **Transparency** — Semi-transparent backgrounds using `rgba()` or `hsla()` with alpha `0.05–0.4`
|
|
16
|
+
2. **Blur** — `backdrop-filter: blur()` ranging 8–40px for frosted-glass effect
|
|
17
|
+
3. **Border** — Subtle semi-transparent borders (`1px solid rgba(255,255,255,0.18)`) to define edges
|
|
18
|
+
4. **Shadow** — Soft layered `box-shadow` for depth separation from background
|
|
19
|
+
|
|
20
|
+
## CSS Tokens
|
|
21
|
+
|
|
22
|
+
Reference: [references/tokens.css](references/tokens.css)
|
|
23
|
+
|
|
24
|
+
Use CSS custom properties from `tokens.css` for consistent theming:
|
|
25
|
+
|
|
26
|
+
```css
|
|
27
|
+
@import 'references/tokens.css';
|
|
28
|
+
|
|
29
|
+
.glass-card {
|
|
30
|
+
background: var(--glass-bg);
|
|
31
|
+
backdrop-filter: var(--glass-blur);
|
|
32
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
33
|
+
border: var(--glass-border);
|
|
34
|
+
border-radius: var(--glass-radius);
|
|
35
|
+
box-shadow: var(--glass-shadow);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Component Examples
|
|
40
|
+
|
|
41
|
+
### Card
|
|
42
|
+
```css
|
|
43
|
+
.glass-card {
|
|
44
|
+
background: var(--glass-bg);
|
|
45
|
+
backdrop-filter: var(--glass-blur);
|
|
46
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
47
|
+
border: var(--glass-border);
|
|
48
|
+
border-radius: var(--glass-radius);
|
|
49
|
+
box-shadow: var(--glass-shadow);
|
|
50
|
+
padding: 1.5rem;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Navbar
|
|
55
|
+
```css
|
|
56
|
+
.glass-nav {
|
|
57
|
+
background: var(--glass-bg-heavy);
|
|
58
|
+
backdrop-filter: var(--glass-blur-strong);
|
|
59
|
+
-webkit-backdrop-filter: var(--glass-blur-strong);
|
|
60
|
+
border-bottom: var(--glass-border);
|
|
61
|
+
box-shadow: var(--glass-shadow);
|
|
62
|
+
position: sticky;
|
|
63
|
+
top: 0;
|
|
64
|
+
z-index: 100;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Modal Overlay
|
|
69
|
+
```css
|
|
70
|
+
.glass-modal-backdrop {
|
|
71
|
+
background: rgba(0, 0, 0, 0.4);
|
|
72
|
+
backdrop-filter: blur(4px);
|
|
73
|
+
}
|
|
74
|
+
.glass-modal {
|
|
75
|
+
background: var(--glass-bg-heavy);
|
|
76
|
+
backdrop-filter: var(--glass-blur-strong);
|
|
77
|
+
-webkit-backdrop-filter: var(--glass-blur-strong);
|
|
78
|
+
border: var(--glass-border);
|
|
79
|
+
border-radius: var(--glass-radius-lg);
|
|
80
|
+
box-shadow: var(--glass-shadow-elevated);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Button
|
|
85
|
+
```css
|
|
86
|
+
.glass-btn {
|
|
87
|
+
background: var(--glass-bg-light);
|
|
88
|
+
backdrop-filter: var(--glass-blur-light);
|
|
89
|
+
-webkit-backdrop-filter: var(--glass-blur-light);
|
|
90
|
+
border: var(--glass-border);
|
|
91
|
+
border-radius: var(--glass-radius);
|
|
92
|
+
transition: background 0.2s;
|
|
93
|
+
}
|
|
94
|
+
.glass-btn:hover {
|
|
95
|
+
background: var(--glass-bg);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Browser Compatibility
|
|
100
|
+
|
|
101
|
+
| Feature | Chrome | Firefox | Safari | Edge |
|
|
102
|
+
|---------|--------|---------|--------|------|
|
|
103
|
+
| `backdrop-filter` | 76+ | 103+ | 9+ (`-webkit-`) | 79+ |
|
|
104
|
+
| `rgba()` backgrounds | All | All | All | All |
|
|
105
|
+
|
|
106
|
+
- Always include `-webkit-backdrop-filter` for Safari support
|
|
107
|
+
- Firefox <103: use `@supports` fallback with solid semi-transparent bg
|
|
108
|
+
- Fallback pattern:
|
|
109
|
+
|
|
110
|
+
```css
|
|
111
|
+
.glass-card {
|
|
112
|
+
background: rgba(255, 255, 255, 0.85); /* fallback */
|
|
113
|
+
}
|
|
114
|
+
@supports (backdrop-filter: blur(1px)) {
|
|
115
|
+
.glass-card {
|
|
116
|
+
background: var(--glass-bg);
|
|
117
|
+
backdrop-filter: var(--glass-blur);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Accessibility Notes
|
|
123
|
+
|
|
124
|
+
- Ensure **contrast ratio ≥ 4.5:1** for text over glass surfaces — test against all possible backgrounds
|
|
125
|
+
- Provide `prefers-reduced-transparency` media query to disable blur/transparency for users who need it
|
|
126
|
+
- Avoid placing critical text on highly transparent surfaces without a fallback
|
|
127
|
+
- Use `prefers-contrast: more` to increase border opacity and reduce transparency
|
|
128
|
+
|
|
129
|
+
```css
|
|
130
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
131
|
+
.glass-card {
|
|
132
|
+
background: rgba(255, 255, 255, 0.92);
|
|
133
|
+
backdrop-filter: none;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
@media (prefers-contrast: more) {
|
|
137
|
+
.glass-card {
|
|
138
|
+
background: rgba(255, 255, 255, 0.85);
|
|
139
|
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* Backgrounds */
|
|
3
|
+
--glass-bg-light: rgba(255, 255, 255, 0.08);
|
|
4
|
+
--glass-bg: rgba(255, 255, 255, 0.15);
|
|
5
|
+
--glass-bg-heavy: rgba(255, 255, 255, 0.25);
|
|
6
|
+
|
|
7
|
+
/* Blur */
|
|
8
|
+
--glass-blur-light: blur(8px);
|
|
9
|
+
--glass-blur: blur(16px);
|
|
10
|
+
--glass-blur-strong: blur(32px);
|
|
11
|
+
|
|
12
|
+
/* Border */
|
|
13
|
+
--glass-border: 1px solid rgba(255, 255, 255, 0.18);
|
|
14
|
+
|
|
15
|
+
/* Radius */
|
|
16
|
+
--glass-radius: 12px;
|
|
17
|
+
--glass-radius-lg: 20px;
|
|
18
|
+
|
|
19
|
+
/* Shadow */
|
|
20
|
+
--glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
|
21
|
+
--glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.15);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Dark theme overrides */
|
|
25
|
+
[data-theme="dark"] {
|
|
26
|
+
--glass-bg-light: rgba(255, 255, 255, 0.04);
|
|
27
|
+
--glass-bg: rgba(255, 255, 255, 0.08);
|
|
28
|
+
--glass-bg-heavy: rgba(255, 255, 255, 0.14);
|
|
29
|
+
--glass-border: 1px solid rgba(255, 255, 255, 0.12);
|
|
30
|
+
--glass-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
|
|
31
|
+
--glass-shadow-elevated: 0 8px 40px rgba(0, 0, 0, 0.4);
|
|
32
|
+
}
|