@mohammadhprp/system-prompt 0.11.0 → 0.11.2
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/framework/agents/backend-architect.md +1 -1
- package/framework/commands/commit.md +0 -3
- package/framework/mcps/figma-mcp-go/README.md +0 -1
- package/framework/mcps/gitlab-mcp/README.md +0 -1
- package/framework/mcps/jira-mcp/README.md +0 -1
- package/framework/mcps/laravel-boost/README.md +0 -1
- package/framework/mcps/notion-mcp/README.md +0 -1
- package/framework/mcps/supabase-mcp/README.md +0 -1
- package/framework/plugins/opencode-goal-plugin/README.md +0 -1
- package/framework/references/standards/api.md +0 -1
- package/framework/references/standards/architecture.md +0 -1
- package/framework/references/standards/database.md +0 -1
- package/framework/references/standards/debugging.md +0 -1
- package/framework/references/standards/documentation.md +0 -2
- package/framework/references/standards/logging.md +0 -1
- package/framework/references/standards/naming.md +0 -1
- package/framework/references/standards/observability.md +0 -1
- package/framework/references/standards/performance.md +0 -1
- package/framework/references/standards/pull-requests.md +0 -1
- package/framework/references/standards/security.md +0 -1
- package/framework/references/standards/testing.md +0 -1
- package/framework/skills/README.md +15 -3
- package/framework/skills/codenavi/SKILL.md +306 -0
- package/framework/skills/codenavi/examples.md +33 -0
- package/framework/skills/codenavi/references/coding-principles.md +143 -0
- package/framework/skills/codenavi/references/notebook-spec.md +171 -0
- package/framework/skills/create-adr/SKILL.md +429 -0
- package/framework/skills/create-adr/examples.md +35 -0
- package/framework/skills/docs-writer/SKILL.md +39 -0
- package/framework/skills/docs-writer/examples.md +34 -0
- package/framework/skills/docs-writer/references/style-guide.md +72 -0
- package/framework/skills/frontend-design/SKILL.md +55 -0
- package/framework/skills/frontend-design/examples.md +45 -0
- package/framework/skills/humanizer/SKILL.md +412 -0
- package/framework/skills/humanizer/examples.md +46 -0
- package/framework/skills/learning-opportunities/SKILL.md +140 -0
- package/framework/skills/learning-opportunities/examples.md +34 -0
- package/framework/skills/learning-opportunities/references/PRINCIPLES.md +42 -0
- package/framework/skills/perf-web-optimization/SKILL.md +163 -0
- package/framework/skills/perf-web-optimization/examples.md +35 -0
- package/framework/skills/perf-web-optimization/references/bundle-optimization.md +180 -0
- package/framework/skills/perf-web-optimization/references/core-web-vitals.md +154 -0
- package/framework/skills/perf-web-optimization/references/image-optimization.md +170 -0
- package/framework/skills/security-best-practices/LICENSE.txt +201 -0
- package/framework/skills/security-best-practices/SKILL.md +89 -0
- package/framework/skills/security-best-practices/examples.md +35 -0
- package/framework/skills/security-best-practices/references/golang-general-backend-security.md +988 -0
- package/framework/skills/security-best-practices/references/javascript-express-web-server-security.md +1151 -0
- package/framework/skills/security-best-practices/references/javascript-general-web-frontend-security.md +725 -0
- package/framework/skills/security-best-practices/references/javascript-jquery-web-frontend-security.md +672 -0
- package/framework/skills/security-best-practices/references/javascript-typescript-nextjs-web-server-security.md +1138 -0
- package/framework/skills/security-best-practices/references/javascript-typescript-react-web-frontend-security.md +975 -0
- package/framework/skills/security-best-practices/references/javascript-typescript-vue-web-frontend-security.md +789 -0
- package/framework/skills/security-best-practices/references/python-django-web-server-security.md +880 -0
- package/framework/skills/security-best-practices/references/python-fastapi-web-server-security.md +1030 -0
- package/framework/skills/security-best-practices/references/python-flask-web-server-security.md +835 -0
- package/framework/skills/sentry/SKILL.md +127 -0
- package/framework/skills/sentry/examples.md +34 -0
- package/framework/skills/sentry/scripts/sentry_api.py +238 -0
- package/framework/skills/show-me/SKILL.md +127 -0
- package/framework/skills/show-me/examples.md +78 -0
- package/framework/skills/spec-driven-eval/SKILL.md +341 -0
- package/framework/skills/spec-driven-eval/examples.md +35 -0
- package/framework/skills/spec-driven-eval/references/quickstart.md +118 -0
- package/framework/skills/spec-driven-eval/references/reference.md +295 -0
- package/framework/skills/technical-design-doc-creator/README.md +411 -0
- package/framework/skills/technical-design-doc-creator/SKILL.md +1484 -0
- package/framework/skills/technical-design-doc-creator/examples.md +35 -0
- package/framework/skills/tlc-spec-driven/SKILL.md +184 -0
- package/framework/skills/tlc-spec-driven/examples.md +34 -0
- package/framework/skills/tlc-spec-driven/references/code-analysis.md +98 -0
- package/framework/skills/tlc-spec-driven/references/coding-principles.md +72 -0
- package/framework/skills/tlc-spec-driven/references/context-limits.md +31 -0
- package/framework/skills/tlc-spec-driven/references/design.md +199 -0
- package/framework/skills/tlc-spec-driven/references/discuss.md +159 -0
- package/framework/skills/tlc-spec-driven/references/implement.md +436 -0
- package/framework/skills/tlc-spec-driven/references/lessons.md +115 -0
- package/framework/skills/tlc-spec-driven/references/memory.md +144 -0
- package/framework/skills/tlc-spec-driven/references/specify.md +228 -0
- package/framework/skills/tlc-spec-driven/references/sub-agents.md +147 -0
- package/framework/skills/tlc-spec-driven/references/tasks.md +451 -0
- package/framework/skills/tlc-spec-driven/references/validate.md +355 -0
- package/framework/skills/tlc-spec-driven/scripts/check_commit.py +115 -0
- package/framework/skills/tlc-spec-driven/scripts/lessons.py +412 -0
- package/framework/skills/tlc-spec-driven/scripts/validate_spec.py +260 -0
- package/framework/skills/tlc-spec-driven/scripts/validate_state.py +162 -0
- package/framework/skills/tlc-spec-driven/scripts/validate_tasks.py +251 -0
- package/framework/skills/web-design-guidelines/SKILL.md +65 -0
- package/framework/skills/web-design-guidelines/examples.md +32 -0
- package/framework/skills/web-design-guidelines/references/guideline.md +174 -0
- package/package.json +1 -1
- package/src/catalog.js +15 -3
- package/src/installer.js +66 -1
- package/framework/skills/backend-engineer/SKILL.md +0 -76
- package/framework/skills/backend-engineer/examples.md +0 -31
- package/framework/skills/documentation/SKILL.md +0 -74
- package/framework/skills/documentation/examples.md +0 -31
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Learning Opportunities Examples
|
|
2
|
+
|
|
3
|
+
## Offer an exercise after creating a module
|
|
4
|
+
|
|
5
|
+
User just created auth middleware: "Done, that's the middleware working."
|
|
6
|
+
|
|
7
|
+
Good agent behavior:
|
|
8
|
+
|
|
9
|
+
- Offer one short, optional exercise: "Would you like a quick learning exercise on middleware patterns? About 10-15 minutes."
|
|
10
|
+
- If the user agrees, use a predict-then-observe exercise: ask what happens when a request hits the middleware with an expired token.
|
|
11
|
+
- Stop generating immediately after the question and wait for the user's answer.
|
|
12
|
+
- If the prediction is wrong, be direct about what's incorrect, then explore the gap.
|
|
13
|
+
|
|
14
|
+
## Teach it back after a refactor
|
|
15
|
+
|
|
16
|
+
User: "We just replaced the cache layer. I want to make sure I actually understand it."
|
|
17
|
+
|
|
18
|
+
Good agent behavior:
|
|
19
|
+
|
|
20
|
+
- Ask the user to explain the caching layer as if to a new developer joining the project.
|
|
21
|
+
- Stop after posing the question and wait for the response.
|
|
22
|
+
- Confirm the specific parts they nailed, then name one concrete gap to refine.
|
|
23
|
+
- Keep the exercise exploratory rather than test-like.
|
|
24
|
+
|
|
25
|
+
## Decline when the user is in a hurry
|
|
26
|
+
|
|
27
|
+
User: "Just ship it, this needs to go out now."
|
|
28
|
+
|
|
29
|
+
Good agent behavior:
|
|
30
|
+
|
|
31
|
+
- Recognize urgency and skip the exercise offer entirely.
|
|
32
|
+
- Avoid repeating the offer when the user has already declined once this session.
|
|
33
|
+
- Cap the session at two completed exercises and stop offering.
|
|
34
|
+
- Keep any offer to a single sentence without insisting.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Learning Principles
|
|
2
|
+
|
|
3
|
+
Consult this file when adapting techniques or making judgment calls about learning approaches. These principles explain WHY the techniques in the main skill work.
|
|
4
|
+
|
|
5
|
+
## Generation Effect
|
|
6
|
+
|
|
7
|
+
Users encode information better when they produce it rather than passively consume it. Active retrieval strengthens memory traces in ways that passive review does not. This is why we ask for predictions and explanations before revealing answers.
|
|
8
|
+
|
|
9
|
+
## Pre-testing
|
|
10
|
+
|
|
11
|
+
Attempting to answer before learning new information produces stronger memory — even when the attempt is wrong. A failed attempt makes the correct answer more memorable by contrast. Wrong predictions are valuable data, not failures.
|
|
12
|
+
|
|
13
|
+
## Spacing Effect
|
|
14
|
+
|
|
15
|
+
Distributing learning over time beats cramming. This is why we use retrieval check-ins at session starts and limit exercises to 2 per session rather than drilling continuously.
|
|
16
|
+
|
|
17
|
+
## Desirable Difficulties
|
|
18
|
+
|
|
19
|
+
Conditions that make learning harder in the short term often produce better long-term retention. Exercises should require effort without being frustrating. Struggle during learning is a sign it's working, not failing.
|
|
20
|
+
|
|
21
|
+
## Fluency Illusion
|
|
22
|
+
|
|
23
|
+
When AI-generated code is clean and readable, users overestimate how well they understand it. The fluency of the output masks gaps in mental models. This is the primary risk this skill counteracts.
|
|
24
|
+
|
|
25
|
+
## Dynamic Testing
|
|
26
|
+
|
|
27
|
+
Errors during learning, when followed by clear corrective feedback, enhance retention compared to error-free learning. This is why we are direct about wrong answers rather than softening them.
|
|
28
|
+
|
|
29
|
+
## Transfer and Interleaving
|
|
30
|
+
|
|
31
|
+
Knowledge transfers better when connected to underlying principles and varied contexts. Asking "where else would this apply?" builds flexible knowledge rather than context-bound recall.
|
|
32
|
+
|
|
33
|
+
## Sources
|
|
34
|
+
|
|
35
|
+
- Bjork, R. A., Dunlosky, J., & Kornell, N. (2013). Self-regulated learning: Beliefs, techniques, and illusions.
|
|
36
|
+
- Dunlosky, J., et al. (2013). Improving students' learning with effective learning techniques.
|
|
37
|
+
- Giebl, S., et al. (2021). Answer first or Google first?
|
|
38
|
+
- Hicks, C. M., Lee, C. S., & Foster-Marks, K. (2025). The New Developer: AI Skill Threat, Identity Change & Developer Thriving.
|
|
39
|
+
- Roediger III, H. L., & Karpicke, J. D. (2006). The power of testing memory.
|
|
40
|
+
- Soderstrom, N. C., & Bjork, R. A. (2015). Learning versus performance: An integrative review.
|
|
41
|
+
- Tankelevitch, L., et al. (2024). The metacognitive demands and opportunities of generative AI.
|
|
42
|
+
- Hicks, C. (2025). Cognitive helmets for the AI bicycle. Fight for the Human.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: perf-web-optimization
|
|
3
|
+
description: 'Optimize web performance: bundle size, images, caching, lazy loading, and overall page speed. Use when site is slow, reducing bundle size, fixing layout shifts, improving Time to Interactive, or optimizing for Lighthouse scores. Triggers on: web performance, bundle size, page speed, slow site, lazy loading. Do NOT use for Core Web Vitals-specific fixes (use core-web-vitals), running Lighthouse audits (use perf-lighthouse), or Astro-specific optimization (use perf-astro).'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Performance Optimization
|
|
7
|
+
|
|
8
|
+
Systematic approach: Measure → Identify → Prioritize → Implement → Verify.
|
|
9
|
+
|
|
10
|
+
## Target Metrics
|
|
11
|
+
|
|
12
|
+
| Metric | Good | Needs Work | Poor |
|
|
13
|
+
| ------ | ------- | ---------- | ------- |
|
|
14
|
+
| LCP | < 2.5s | 2.5-4s | > 4s |
|
|
15
|
+
| INP | < 200ms | 200-500ms | > 500ms |
|
|
16
|
+
| CLS | < 0.1 | 0.1-0.25 | > 0.25 |
|
|
17
|
+
| TTFB | < 800ms | 800ms-1.8s | > 1.8s |
|
|
18
|
+
|
|
19
|
+
## Quick Wins
|
|
20
|
+
|
|
21
|
+
### 1. Images (usually biggest impact on LCP)
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<!-- Hero/LCP image: eager + high priority -->
|
|
25
|
+
<img src="/hero.webp" alt="Hero" width="1200" height="600" loading="eager" fetchpriority="high" decoding="async" />
|
|
26
|
+
|
|
27
|
+
<!-- Below fold: lazy load -->
|
|
28
|
+
<img src="/product.webp" alt="Product" width="400" height="300" loading="lazy" decoding="async" />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Always set `width` and `height` to prevent CLS.
|
|
32
|
+
|
|
33
|
+
### 2. Fonts (common LCP/CLS culprit)
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<!-- Preconnect to font origin -->
|
|
37
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
38
|
+
|
|
39
|
+
<!-- Non-blocking font load -->
|
|
40
|
+
<link
|
|
41
|
+
rel="stylesheet"
|
|
42
|
+
href="https://fonts.googleapis.com/css2?family=Inter&display=swap"
|
|
43
|
+
media="print"
|
|
44
|
+
onload="this.media='all'"
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. Third-party Scripts (common INP killer)
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<!-- Defer to user interaction -->
|
|
52
|
+
<script>
|
|
53
|
+
function loadThirdParty() {
|
|
54
|
+
// Load analytics, chat widgets, etc.
|
|
55
|
+
}
|
|
56
|
+
;['scroll', 'click', 'touchstart'].forEach((e) => addEventListener(e, loadThirdParty, { once: true, passive: true }))
|
|
57
|
+
setTimeout(loadThirdParty, 5000)
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 4. Critical CSS
|
|
62
|
+
|
|
63
|
+
Inline critical CSS in `<head>`, defer the rest:
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<style>
|
|
67
|
+
/* critical styles */
|
|
68
|
+
</style>
|
|
69
|
+
<link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'" />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Bundle Analysis
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Webpack
|
|
76
|
+
npx webpack-bundle-analyzer dist/stats.json
|
|
77
|
+
|
|
78
|
+
# Vite
|
|
79
|
+
npx vite-bundle-visualizer
|
|
80
|
+
|
|
81
|
+
# Check package size before installing
|
|
82
|
+
npx bundlephobia <package-name>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Common heavy packages to replace:
|
|
86
|
+
|
|
87
|
+
- `moment` (67KB) → `date-fns` (12KB) or `dayjs` (2KB)
|
|
88
|
+
- `lodash` (72KB) → cherry-pick imports or native methods
|
|
89
|
+
|
|
90
|
+
## Code Splitting Patterns
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
// React lazy
|
|
94
|
+
const Chart = lazy(() => import('./Chart'))
|
|
95
|
+
|
|
96
|
+
// Next.js dynamic
|
|
97
|
+
const Admin = dynamic(() => import('./Admin'), { ssr: false })
|
|
98
|
+
|
|
99
|
+
// Vite/Rollup manual chunks
|
|
100
|
+
build: {
|
|
101
|
+
rollupOptions: {
|
|
102
|
+
output: {
|
|
103
|
+
manualChunks: {
|
|
104
|
+
vendor: ['react', 'react-dom']
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Caching Headers
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
# Static assets (immutable hash in filename)
|
|
115
|
+
Cache-Control: public, max-age=31536000, immutable
|
|
116
|
+
|
|
117
|
+
# HTML (revalidate)
|
|
118
|
+
Cache-Control: no-cache
|
|
119
|
+
|
|
120
|
+
# API responses
|
|
121
|
+
Cache-Control: private, max-age=0, must-revalidate
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Measurement
|
|
125
|
+
|
|
126
|
+
For running audits, reading reports, and setting budgets, use the **perf-lighthouse** skill.
|
|
127
|
+
|
|
128
|
+
## Checklist
|
|
129
|
+
|
|
130
|
+
### Images
|
|
131
|
+
|
|
132
|
+
- [ ] Modern formats (WebP/AVIF)
|
|
133
|
+
- [ ] Responsive `srcset`
|
|
134
|
+
- [ ] `width`/`height` attributes
|
|
135
|
+
- [ ] `loading="lazy"` below fold
|
|
136
|
+
- [ ] `fetchpriority="high"` on LCP image
|
|
137
|
+
|
|
138
|
+
### JavaScript
|
|
139
|
+
|
|
140
|
+
- [ ] Bundle < 200KB gzipped
|
|
141
|
+
- [ ] Code splitting by route
|
|
142
|
+
- [ ] Third-party scripts deferred
|
|
143
|
+
- [ ] No unused dependencies
|
|
144
|
+
|
|
145
|
+
### CSS
|
|
146
|
+
|
|
147
|
+
- [ ] Critical CSS inlined
|
|
148
|
+
- [ ] Non-critical CSS deferred
|
|
149
|
+
- [ ] No unused CSS
|
|
150
|
+
|
|
151
|
+
### Fonts
|
|
152
|
+
|
|
153
|
+
- [ ] `font-display: swap`
|
|
154
|
+
- [ ] Preconnect to font origin
|
|
155
|
+
- [ ] Subset if possible
|
|
156
|
+
|
|
157
|
+
## Detailed Examples
|
|
158
|
+
|
|
159
|
+
For in-depth optimization patterns, see:
|
|
160
|
+
|
|
161
|
+
- [references/core-web-vitals.md](references/core-web-vitals.md) - Fixing LCP, CLS, INP issues
|
|
162
|
+
- [references/bundle-optimization.md](references/bundle-optimization.md) - Reducing JS bundle size
|
|
163
|
+
- [references/image-optimization.md](references/image-optimization.md) - Image formats, responsive images, sharp scripts
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Web Performance Optimization Examples
|
|
2
|
+
|
|
3
|
+
## Slow landing page
|
|
4
|
+
|
|
5
|
+
User: "Our landing page takes forever to load. Make it faster."
|
|
6
|
+
|
|
7
|
+
Good agent behavior:
|
|
8
|
+
|
|
9
|
+
- Follow the measure-identify-prioritize-implement-verify cycle rather than guessing.
|
|
10
|
+
- Start with the highest-impact quick wins: LCP image loading with `fetchpriority="high"`, explicit dimensions, and modern formats.
|
|
11
|
+
- Fix font loading with `font-display: swap` and preconnect to the font origin.
|
|
12
|
+
- Verify against target metrics (LCP < 2.5s, INP < 200ms, CLS < 0.1) before calling it done.
|
|
13
|
+
|
|
14
|
+
## Reduce JavaScript bundle size
|
|
15
|
+
|
|
16
|
+
User: "The main bundle is over 1MB. How do we cut it down?"
|
|
17
|
+
|
|
18
|
+
Good agent behavior:
|
|
19
|
+
|
|
20
|
+
- Run a bundle analyzer (webpack or Vite) to find the heavy dependencies before proposing swaps.
|
|
21
|
+
- Replace large packages like `moment` with lighter alternatives when the API allows.
|
|
22
|
+
- Add route-level code splitting with lazy imports and vendor chunking.
|
|
23
|
+
- Defer third-party scripts to user interaction rather than loading them eagerly.
|
|
24
|
+
- Confirm the gzipped bundle is under 200KB afterward.
|
|
25
|
+
|
|
26
|
+
## Fix layout shift on product pages
|
|
27
|
+
|
|
28
|
+
User: "The images keep jumping around while the page loads."
|
|
29
|
+
|
|
30
|
+
Good agent behavior:
|
|
31
|
+
|
|
32
|
+
- Recognize CLS as the metric and add explicit `width`/`height` attributes to all images.
|
|
33
|
+
- Reserve space for below-fold content instead of letting it shift on load.
|
|
34
|
+
- Lazy load below-the-fold images while keeping the LCP image eager and high priority.
|
|
35
|
+
- Verify the CLS score drops below 0.1 after the change.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Bundle Size Optimization
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Analysis Tools](#analysis-tools)
|
|
5
|
+
- [Heavy Dependencies](#heavy-dependencies)
|
|
6
|
+
- [Code Splitting](#code-splitting)
|
|
7
|
+
- [Tree Shaking](#tree-shaking)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Analysis Tools
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Webpack - generates interactive treemap
|
|
15
|
+
npx webpack-bundle-analyzer dist/stats.json
|
|
16
|
+
|
|
17
|
+
# Generate stats file first
|
|
18
|
+
webpack --profile --json > dist/stats.json
|
|
19
|
+
|
|
20
|
+
# Vite
|
|
21
|
+
npx vite-bundle-visualizer
|
|
22
|
+
|
|
23
|
+
# Source map explorer
|
|
24
|
+
npx source-map-explorer dist/**/*.js
|
|
25
|
+
|
|
26
|
+
# Check package size before adding
|
|
27
|
+
npx bundlephobia lodash
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Heavy Dependencies
|
|
33
|
+
|
|
34
|
+
### moment → date-fns/dayjs
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
// Before: moment (67KB)
|
|
38
|
+
import moment from 'moment';
|
|
39
|
+
moment(date).format('YYYY-MM-DD');
|
|
40
|
+
|
|
41
|
+
// After: date-fns (tree-shakeable, ~2KB per function)
|
|
42
|
+
import { format } from 'date-fns';
|
|
43
|
+
format(date, 'yyyy-MM-dd');
|
|
44
|
+
|
|
45
|
+
// After: dayjs (2KB total, moment-compatible API)
|
|
46
|
+
import dayjs from 'dayjs';
|
|
47
|
+
dayjs(date).format('YYYY-MM-DD');
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### lodash → cherry-pick or native
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// Before: entire lodash (72KB)
|
|
54
|
+
import _ from 'lodash';
|
|
55
|
+
_.uniq(array);
|
|
56
|
+
_.debounce(fn, 300);
|
|
57
|
+
|
|
58
|
+
// After: cherry-pick (2KB each)
|
|
59
|
+
import uniq from 'lodash/uniq';
|
|
60
|
+
import debounce from 'lodash/debounce';
|
|
61
|
+
|
|
62
|
+
// After: native alternatives
|
|
63
|
+
[...new Set(array)]; // uniq
|
|
64
|
+
// debounce - use custom or lodash-es/debounce
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Other common swaps
|
|
68
|
+
|
|
69
|
+
| Heavy | Light Alternative |
|
|
70
|
+
|-------|-------------------|
|
|
71
|
+
| `axios` (13KB) | `fetch` (native) or `ky` (3KB) |
|
|
72
|
+
| `uuid` (4KB) | `crypto.randomUUID()` (native) |
|
|
73
|
+
| `classnames` (1KB) | template literals |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Code Splitting
|
|
78
|
+
|
|
79
|
+
### React.lazy
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { lazy, Suspense } from 'react';
|
|
83
|
+
|
|
84
|
+
const Chart = lazy(() => import('./Chart'));
|
|
85
|
+
const AdminPanel = lazy(() => import('./AdminPanel'));
|
|
86
|
+
|
|
87
|
+
function App() {
|
|
88
|
+
return (
|
|
89
|
+
<Suspense fallback={<Loading />}>
|
|
90
|
+
{showChart && <Chart />}
|
|
91
|
+
{isAdmin && <AdminPanel />}
|
|
92
|
+
</Suspense>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Next.js dynamic
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
import dynamic from 'next/dynamic';
|
|
101
|
+
|
|
102
|
+
// Client-only component
|
|
103
|
+
const Map = dynamic(() => import('./Map'), { ssr: false });
|
|
104
|
+
|
|
105
|
+
// With loading state
|
|
106
|
+
const Chart = dynamic(() => import('./Chart'), {
|
|
107
|
+
loading: () => <Skeleton height={300} />
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Route-based splitting (automatic in most frameworks)
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
// Next.js - each page is a separate chunk
|
|
115
|
+
// pages/dashboard.js → chunks/pages/dashboard.js
|
|
116
|
+
// pages/admin.js → chunks/pages/admin.js
|
|
117
|
+
|
|
118
|
+
// React Router with lazy
|
|
119
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
120
|
+
const Admin = lazy(() => import('./pages/Admin'));
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Manual chunks (Vite/Rollup)
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
// vite.config.js
|
|
127
|
+
export default {
|
|
128
|
+
build: {
|
|
129
|
+
rollupOptions: {
|
|
130
|
+
output: {
|
|
131
|
+
manualChunks: {
|
|
132
|
+
vendor: ['react', 'react-dom'],
|
|
133
|
+
charts: ['recharts', 'd3'],
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Tree Shaking
|
|
144
|
+
|
|
145
|
+
### Enable in webpack
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// webpack.config.js
|
|
149
|
+
module.exports = {
|
|
150
|
+
mode: 'production', // enables tree shaking
|
|
151
|
+
optimization: {
|
|
152
|
+
usedExports: true,
|
|
153
|
+
sideEffects: true,
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Mark package as side-effect free
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
// package.json
|
|
162
|
+
{
|
|
163
|
+
"sideEffects": false
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Or specify files with side effects
|
|
167
|
+
{
|
|
168
|
+
"sideEffects": ["*.css", "*.scss"]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Write tree-shakeable exports
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// Bad: default export of object
|
|
176
|
+
export default { foo, bar, baz };
|
|
177
|
+
|
|
178
|
+
// Good: named exports
|
|
179
|
+
export { foo, bar, baz };
|
|
180
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Core Web Vitals Optimization
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [LCP (Largest Contentful Paint)](#lcp-largest-contentful-paint)
|
|
5
|
+
- [CLS (Cumulative Layout Shift)](#cls-cumulative-layout-shift)
|
|
6
|
+
- [INP (Interaction to Next Paint)](#inp-interaction-to-next-paint)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## LCP (Largest Contentful Paint)
|
|
11
|
+
|
|
12
|
+
Target: < 2.5s
|
|
13
|
+
|
|
14
|
+
### Common Causes
|
|
15
|
+
- Large unoptimized images
|
|
16
|
+
- Slow server response (TTFB)
|
|
17
|
+
- Render-blocking resources
|
|
18
|
+
- Client-side rendering delays
|
|
19
|
+
|
|
20
|
+
### Fix: Optimize LCP Image
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<!-- Preload in <head> -->
|
|
24
|
+
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
|
|
25
|
+
|
|
26
|
+
<!-- Image tag -->
|
|
27
|
+
<picture>
|
|
28
|
+
<source srcset="/hero.avif" type="image/avif">
|
|
29
|
+
<source srcset="/hero.webp" type="image/webp">
|
|
30
|
+
<img src="/hero.jpg" alt="Hero" width="1200" height="600"
|
|
31
|
+
loading="eager" fetchpriority="high" decoding="async">
|
|
32
|
+
</picture>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Fix: Reduce TTFB
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// Next.js: Use static generation when possible
|
|
39
|
+
export async function getStaticProps() {
|
|
40
|
+
const data = await fetchData();
|
|
41
|
+
return { props: { data }, revalidate: 60 };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Add stale-while-revalidate for dynamic content
|
|
45
|
+
// Cache-Control: public, s-maxage=60, stale-while-revalidate=300
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## CLS (Cumulative Layout Shift)
|
|
51
|
+
|
|
52
|
+
Target: < 0.1
|
|
53
|
+
|
|
54
|
+
### Common Causes
|
|
55
|
+
- Images without dimensions
|
|
56
|
+
- Ads/embeds without reserved space
|
|
57
|
+
- Web fonts causing FOIT/FOUT
|
|
58
|
+
- Dynamic content injection
|
|
59
|
+
|
|
60
|
+
### Fix: Reserve Space for Images
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- Always specify dimensions -->
|
|
64
|
+
<img src="/photo.jpg" alt="Photo" width="800" height="600">
|
|
65
|
+
|
|
66
|
+
<!-- Or use aspect-ratio -->
|
|
67
|
+
<img src="/photo.jpg" alt="Photo" style="aspect-ratio: 4/3; width: 100%;">
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Fix: Reserve Space for Dynamic Content
|
|
71
|
+
|
|
72
|
+
```css
|
|
73
|
+
/* Skeleton loader with fixed height */
|
|
74
|
+
.ad-slot {
|
|
75
|
+
min-height: 250px;
|
|
76
|
+
background: #f0f0f0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Aspect ratio container for embeds */
|
|
80
|
+
.video-container {
|
|
81
|
+
aspect-ratio: 16/9;
|
|
82
|
+
width: 100%;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Fix: Prevent Font Flash
|
|
87
|
+
|
|
88
|
+
```css
|
|
89
|
+
@font-face {
|
|
90
|
+
font-family: 'CustomFont';
|
|
91
|
+
src: url('/font.woff2') format('woff2');
|
|
92
|
+
font-display: swap; /* or optional for less shift */
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## INP (Interaction to Next Paint)
|
|
99
|
+
|
|
100
|
+
Target: < 200ms
|
|
101
|
+
|
|
102
|
+
### Common Causes
|
|
103
|
+
- Long JavaScript tasks (>50ms)
|
|
104
|
+
- Heavy event handlers
|
|
105
|
+
- Layout thrashing
|
|
106
|
+
- Too much main thread work
|
|
107
|
+
|
|
108
|
+
### Fix: Break Up Long Tasks
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// Before: blocks main thread
|
|
112
|
+
items.forEach(item => processItem(item));
|
|
113
|
+
|
|
114
|
+
// After: yield to main thread
|
|
115
|
+
async function processWithYield(items) {
|
|
116
|
+
for (const item of items) {
|
|
117
|
+
processItem(item);
|
|
118
|
+
// Yield every 5ms
|
|
119
|
+
if (performance.now() - start > 5) {
|
|
120
|
+
await new Promise(r => setTimeout(r, 0));
|
|
121
|
+
start = performance.now();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Fix: Debounce/Throttle Event Handlers
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
// Debounce search input
|
|
131
|
+
const search = debounce((query) => {
|
|
132
|
+
fetchResults(query);
|
|
133
|
+
}, 300);
|
|
134
|
+
|
|
135
|
+
input.addEventListener('input', (e) => search(e.target.value));
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Fix: Use CSS Instead of JS
|
|
139
|
+
|
|
140
|
+
```css
|
|
141
|
+
/* Prefer CSS for animations */
|
|
142
|
+
.animate {
|
|
143
|
+
transition: transform 0.3s ease;
|
|
144
|
+
}
|
|
145
|
+
.animate:hover {
|
|
146
|
+
transform: scale(1.05);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Use content-visibility for off-screen content */
|
|
150
|
+
.lazy-section {
|
|
151
|
+
content-visibility: auto;
|
|
152
|
+
contain-intrinsic-size: 0 500px;
|
|
153
|
+
}
|
|
154
|
+
```
|