codewithgarry
Version:
Girish Sharma's NPX business card - DevOps Engineer & Cloud Architect - Connect with me directly via terminal!
320 lines (277 loc) • 8.84 kB
JavaScript
/**
* Performance Optimization Utilities
* Implements lazy loading, caching, and other performance enhancements
*/
// Lazy loading for images and heavy content
class LazyLoader {
constructor() {
this.observer = null;
this.init();
}
init() {
if ('IntersectionObserver' in window) {
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadElement(entry.target);
this.observer.unobserve(entry.target);
}
});
}, {
rootMargin: '50px 0px',
threshold: 0.01
});
this.observeElements();
} else {
// Fallback for older browsers
this.loadAllElements();
}
}
observeElements() {
// Observe images with data-src
document.querySelectorAll('img[data-src]').forEach(img => {
this.observer.observe(img);
});
// Observe lazy-load containers
document.querySelectorAll('.lazy-load').forEach(element => {
this.observer.observe(element);
});
}
loadElement(element) {
if (element.tagName === 'IMG' && element.dataset.src) {
element.src = element.dataset.src;
element.classList.add('loaded');
}
if (element.classList.contains('lazy-load')) {
element.classList.add('loaded');
}
}
loadAllElements() {
document.querySelectorAll('img[data-src]').forEach(img => {
this.loadElement(img);
});
document.querySelectorAll('.lazy-load').forEach(element => {
this.loadElement(element);
});
}
}
// Resource preloader
class ResourcePreloader {
constructor() {
this.cache = new Map();
this.preloadQueue = [];
}
preloadCSS(href) {
if (this.cache.has(href)) return;
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'style';
link.href = href;
link.onload = () => {
link.rel = 'stylesheet';
this.cache.set(href, true);
};
document.head.appendChild(link);
}
preloadJS(src) {
if (this.cache.has(src)) return;
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'script';
link.href = src;
document.head.appendChild(link);
this.cache.set(src, true);
}
preloadImage(src) {
if (this.cache.has(src)) return;
const img = new Image();
img.onload = () => this.cache.set(src, true);
img.src = src;
}
preloadFont(href) {
if (this.cache.has(href)) return;
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'font';
link.type = 'font/woff2';
link.crossOrigin = 'anonymous';
link.href = href;
document.head.appendChild(link);
this.cache.set(href, true);
}
}
// Performance monitor
class PerformanceMonitor {
constructor() {
this.metrics = {};
this.startTime = performance.now();
this.init();
}
init() {
this.measurePageLoad();
this.measureLCP();
this.measureFID();
this.measureCLS();
}
measurePageLoad() {
window.addEventListener('load', () => {
const loadTime = performance.now() - this.startTime;
this.metrics.pageLoadTime = Math.round(loadTime);
console.log(`📊 Page loaded in ${this.metrics.pageLoadTime}ms`);
});
}
measureLCP() {
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
this.metrics.lcp = Math.round(lastEntry.startTime);
console.log(`📊 LCP: ${this.metrics.lcp}ms`);
});
observer.observe({ entryTypes: ['largest-contentful-paint'] });
}
}
measureFID() {
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver((list) => {
const firstEntry = list.getEntries()[0];
this.metrics.fid = Math.round(firstEntry.processingStart - firstEntry.startTime);
console.log(`📊 FID: ${this.metrics.fid}ms`);
});
observer.observe({ entryTypes: ['first-input'] });
}
}
measureCLS() {
if ('PerformanceObserver' in window) {
let clsValue = 0;
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
this.metrics.cls = Math.round(clsValue * 1000) / 1000;
console.log(`📊 CLS: ${this.metrics.cls}`);
});
observer.observe({ entryTypes: ['layout-shift'] });
}
}
getMetrics() {
return this.metrics;
}
}
// Cache management
class CacheManager {
constructor() {
this.storage = window.localStorage;
this.prefix = 'cwg_cache_';
this.ttl = 24 * 60 * 60 * 1000; // 24 hours
}
set(key, value, customTTL = null) {
try {
const item = {
value: value,
timestamp: Date.now(),
ttl: customTTL || this.ttl
};
this.storage.setItem(this.prefix + key, JSON.stringify(item));
} catch (error) {
console.warn('Cache set failed:', error);
}
}
get(key) {
try {
const item = this.storage.getItem(this.prefix + key);
if (!item) return null;
const parsed = JSON.parse(item);
if (Date.now() - parsed.timestamp > parsed.ttl) {
this.delete(key);
return null;
}
return parsed.value;
} catch (error) {
console.warn('Cache get failed:', error);
return null;
}
}
delete(key) {
try {
this.storage.removeItem(this.prefix + key);
} catch (error) {
console.warn('Cache delete failed:', error);
}
}
clear() {
try {
Object.keys(this.storage).forEach(key => {
if (key.startsWith(this.prefix)) {
this.storage.removeItem(key);
}
});
} catch (error) {
console.warn('Cache clear failed:', error);
}
}
}
// Initialize performance optimizations
function initPerformanceOptimizations() {
// Initialize lazy loading
const lazyLoader = new LazyLoader();
// Initialize resource preloader
const preloader = new ResourcePreloader();
// Preload critical resources
preloader.preloadFont('https://fonts.gstatic.com/s/firacode/v21/uU9eCBsR6Z2vfE9aq3bL0fxyUs4tcw4W_D1sJVD7MOzlojwUKaJO.woff2');
preloader.preloadCSS('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css');
// Initialize performance monitoring
const monitor = new PerformanceMonitor();
// Initialize cache
const cache = new CacheManager();
// Add to global scope for access
window.performance_utils = {
lazyLoader,
preloader,
monitor,
cache
};
console.log('🚀 Performance optimizations initialized');
}
// Debounce utility for performance
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Throttle utility for performance
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPerformanceOptimizations);
} else {
initPerformanceOptimizations();
}
// Export for Node.js environment
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
LazyLoader,
ResourcePreloader,
PerformanceMonitor,
CacheManager,
debounce,
throttle
};
}