# 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: | Product - 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\\('