/** * Performance optimization utilities */ // Debounce function to limit how often a function is called export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: ReturnType | null = null; return function(...args: Parameters) { const later = () => { timeout = null; func(...args); }; if (timeout !== null) { clearTimeout(timeout); } timeout = setTimeout(later, wait); }; } // Throttle function to limit the rate at which a function is executed export function throttle any>( func: T, limit: number ): (...args: Parameters) => void { let inThrottle = false; return function(...args: Parameters) { if (!inThrottle) { func(...args); inThrottle = true; setTimeout(() => { inThrottle = false; }, limit); } }; } // Memoize function to cache expensive function calls export function memoize any>( func: T ): (...args: Parameters) => ReturnType { const cache = new Map>(); return function(...args: Parameters): ReturnType { const key = JSON.stringify(args); if (cache.has(key)) { return cache.get(key) as ReturnType; } const result = func(...args); cache.set(key, result); return result; }; } // Lazy load images that are in viewport export function lazyLoadImages() { if ('IntersectionObserver' in window) { const imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target as HTMLImageElement; if (img.dataset.src) { img.src = img.dataset.src; img.removeAttribute('data-src'); imageObserver.unobserve(img); } } }); }); document.querySelectorAll('img[data-src]').forEach(img => { imageObserver.observe(img); }); } else { // Fallback for browsers that don't support IntersectionObserver document.querySelectorAll('img[data-src]').forEach(img => { const imgElement = img as HTMLImageElement; if (imgElement.dataset.src) { imgElement.src = imgElement.dataset.src; imgElement.removeAttribute('data-src'); } }); } } // Initialize performance monitoring export function initPerformanceMonitoring() { if ('PerformanceObserver' in window) { try { // Core Web Vitals const perfObserver = new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { // Log performance metrics }); }); // Observe different performance metrics perfObserver.observe({ type: 'largest-contentful-paint', buffered: true }); perfObserver.observe({ type: 'first-input', buffered: true }); perfObserver.observe({ type: 'layout-shift', buffered: true }); // Resource timing const resourceObserver = new PerformanceObserver((list) => { list.getEntries().forEach((entry) => { if (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest') { // console.log(`[API] ${entry.name}: ${entry.duration.toFixed(0)}ms`); } }); }); resourceObserver.observe({ type: 'resource', buffered: true }); } catch (e) { console.warn('Performance monitoring not fully supported', e); } } }