# Frontend Performance Rules
# ==========================
frontend_rules:
- id: "PERF-056"
name: "Debounce search inputs"
severity: warning
description: |
Search inputs should debounce API calls.
Recommended: 300-500ms delay.
Prevents excessive API calls while user is typing.
file_pattern: "**/*.js"
context_patterns:
- "search|filter|query"
anti_patterns:
- '@input=".*search.*fetch'
- '@keyup=".*search.*fetch'
suggested_patterns:
- "debounce|setTimeout.*search|\\$watch.*search"
example_bad: |
example_good: |
// With: debouncedSearch = debounce(searchProducts, 300)
- id: "PERF-057"
name: "Lazy load off-screen content"
severity: info
description: |
Defer loading of off-screen content:
- Modals
- Tabs (inactive)
- Below-the-fold content
- Images
file_pattern: "**/*.html"
suggested_patterns:
- 'loading="lazy"|x-intersect|x-show|x-if'
- id: "PERF-058"
name: "Image optimization"
severity: warning
description: |
Images should be optimized:
- Use appropriate formats (WebP, AVIF)
- Serve responsive sizes
- Lazy load off-screen images
- Use CDN for static assets
file_pattern: "**/*.html"
required_patterns:
- 'loading="lazy"|srcset|x-intersect'
example_good: |
- id: "PERF-059"
name: "Minimize Alpine.js watchers"
severity: info
description: |
Excessive $watch calls impact performance.
Use computed properties or event handlers instead.
file_pattern: "**/*.js"
anti_patterns:
- '\\$watch\\([^)]+\\).*\\$watch\\([^)]+\\).*\\$watch\\('
- id: "PERF-060"
name: "Virtual scrolling for long lists"
severity: info
description: |
Lists with 100+ items should use virtual scrolling.
Only render visible items in the viewport.
file_pattern: "**/*.html|**/*.js"
suggested_patterns:
- "virtual-scroll|x-intersect|IntersectionObserver"
- id: "PERF-061"
name: "Minimize bundle size"
severity: info
description: |
Reduce JavaScript bundle size:
- Import only needed modules
- Use tree-shaking
- Split code by route
file_pattern: "**/*.js"
- id: "PERF-062"
name: "Reasonable polling intervals"
severity: warning
description: |
Polling should be >= 10 seconds for non-critical updates.
Lower intervals waste bandwidth and server resources.
file_pattern: "**/*.js"
anti_patterns:
- 'setInterval\\s*\\([^,]+,\\s*[1-9]\\d{0,3}\\s*\\)'
exclude_patterns:
- "# real-time required"
example_bad: |
setInterval(fetchUpdates, 1000); // Every second
example_good: |
setInterval(fetchUpdates, 30000); // Every 30 seconds
- id: "PERF-063"
name: "CSS containment"
severity: info
description: |
Use CSS containment for complex layouts.
Limits rendering scope for better performance.
file_pattern: "**/*.css|**/*.html"
suggested_patterns:
- "contain:|content-visibility"
- id: "PERF-064"
name: "Avoid layout thrashing"
severity: warning
description: |
Don't interleave DOM reads and writes.
Batch reads first, then writes.
file_pattern: "**/*.js"
anti_patterns:
- 'offsetHeight.*style\\.|style\\..*offsetHeight'
- id: "PERF-065"
name: "Use CSS animations over JavaScript"
severity: info
description: |
CSS animations are hardware-accelerated.
Use CSS for simple animations, JS for complex ones.
file_pattern: "**/*.js"
suggested_patterns:
- "transition|animation|transform"
- id: "PERF-066"
name: "Preload critical resources"
severity: info
description: |
Preload critical CSS, fonts, and above-the-fold images.
Reduces perceived load time.
file_pattern: "**/*.html"
suggested_patterns:
- 'rel="preload"|rel="prefetch"|rel="preconnect"'
- id: "PERF-067"
name: "Defer non-critical JavaScript"
severity: info
description: |
Non-critical JavaScript should be deferred.
Allows page rendering to complete first.
file_pattern: "**/*.html"
suggested_patterns:
- 'defer|async'
- id: "PERF-068"
name: "Minimize DOM nodes"
severity: info
description: |
Excessive DOM nodes slow rendering.
Target: < 1500 nodes, depth < 32, children < 60
file_pattern: "**/*.html"
- id: "PERF-069"
name: "Efficient event handlers"
severity: info
description: |
Use event delegation for repeated elements.
Add listener to parent, not each child.
file_pattern: "**/*.js"
suggested_patterns:
- "@click.delegate|event.target.closest"
- id: "PERF-070"
name: "Cache DOM queries"
severity: info
description: |
Store DOM element references instead of re-querying.
Each querySelector has performance cost.
file_pattern: "**/*.js"
anti_patterns:
- 'document\\.querySelector\\([^)]+\\).*document\\.querySelector\\('