// 页面性能优化组件 (function() { let performanceData = {}; let isOptimizing = false; // 性能监测 function measurePerformance() { if ('performance' in window) { const navigation = performance.getEntriesByType('navigation')[0]; const paint = performance.getEntriesByType('paint'); performanceData = { // 页面加载时间 domLoading: navigation.domContentLoadedEventEnd - navigation.navigationStart, pageLoading: navigation.loadEventEnd - navigation.navigationStart, // 渲染时间 firstPaint: paint.find(p => p.name === 'first-paint')?.startTime || 0, firstContentfulPaint: paint.find(p => p.name === 'first-contentful-paint')?.startTime || 0, // 网络时间 dnsTime: navigation.domainLookupEnd - navigation.domainLookupStart, connectTime: navigation.connectEnd - navigation.connectStart, requestTime: navigation.responseStart - navigation.requestStart, downloadTime: navigation.responseEnd - navigation.responseStart, // 内存使用(如果支持) memory: performance.memory ? { used: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024), total: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024), limit: Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024) } : null }; } return performanceData; } // 资源预加载优化 function optimizeResourceLoading() { // 根据当前页面位置调整路径 const isInPagesFolder = window.location.pathname.includes('/pages/'); const basePath = isInPagesFolder ? '../' : ''; // 预加载关键资源 const criticalResources = [ { href: basePath + 'css/styles.css', as: 'style' }, { href: basePath + 'css/animations.css', as: 'style' }, { href: basePath + 'js/nav-component.js', as: 'script' } ]; criticalResources.forEach(resource => { if (!document.querySelector(`link[href*="${resource.href.split('/').pop()}"]`)) { const link = document.createElement('link'); link.rel = 'preload'; link.href = resource.href; link.as = resource.as; document.head.appendChild(link); } }); } // 图片懒加载和优化 function optimizeImages() { // 创建 Intersection Observer 用于懒加载 if ('IntersectionObserver' in window) { const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; // 懒加载图片 if (img.dataset.src) { img.src = img.dataset.src; img.removeAttribute('data-src'); } // 添加加载状态 img.classList.add('loading'); img.addEventListener('load', () => { img.classList.remove('loading'); img.classList.add('loaded'); }); img.addEventListener('error', () => { img.classList.add('error'); img.style.display = 'none'; }); observer.unobserve(img); } }); }, { rootMargin: '50px', threshold: 0.01 }); // 观察所有图片 document.querySelectorAll('img[data-src], img:not([src])').forEach(img => { imageObserver.observe(img); }); } // 为现有图片添加优化 document.querySelectorAll('img').forEach(img => { // 添加 loading="lazy" 属性 if (!img.loading) { img.loading = 'lazy'; } // 添加 decode="async" 属性 if (!img.decode) { img.decode = 'async'; } // 图片错误处理 img.addEventListener('error', function() { this.style.opacity = '0'; this.style.transition = 'opacity 0.3s'; }); }); } // CSS 优化 function optimizeCSS() { // 内联关键 CSS const criticalCSS = ` /* 关键渲染路径 CSS */ body { font-family: 'Inter', sans-serif; margin: 0; padding: 0; } #navbar { position: fixed; top: 0; width: 100%; z-index: 50; background: white; } .container { max-width: 1200px; margin: 0 auto; padding: 0 1rem; } /* 页面加载器样式 */ #page-loader { position: fixed; inset: 0; z-index: 9999; background: white; display: flex; align-items: center; justify-content: center; } `; // 添加关键 CSS 到 head if (!document.getElementById('critical-css')) { const style = document.createElement('style'); style.id = 'critical-css'; style.textContent = criticalCSS; document.head.insertBefore(style, document.head.firstChild); } // 异步加载非关键 CSS const nonCriticalCSS = document.querySelectorAll('link[rel="stylesheet"]:not([data-critical])'); nonCriticalCSS.forEach(link => { if (link.href.includes('tailwind') || link.href.includes('font-awesome')) { link.media = 'print'; link.addEventListener('load', function() { this.media = 'all'; }); } }); } // JavaScript 优化 function optimizeJavaScript() { // 延迟加载非关键脚本 const deferScripts = [ 'js/back-to-top.js', 'js/mobile-optimize.js' ]; deferScripts.forEach(src => { const script = document.querySelector(`script[src*="${src}"]`); if (script && !script.defer && !script.async) { script.defer = true; } }); // 移除未使用的事件监听器(防止内存泄漏) const cleanupEvents = () => { // 移除已销毁元素的事件监听器 document.querySelectorAll('[data-cleanup]').forEach(el => { el.removeEventListener('click', null); el.removeEventListener('scroll', null); el.removeEventListener('resize', null); }); }; // 页面卸载时清理 window.addEventListener('beforeunload', cleanupEvents); } // 网络优化 function optimizeNetwork() { // DNS 预解析 const domains = [ 'fonts.googleapis.com', 'cdnjs.cloudflare.com', 'cdn.jsdelivr.net' ]; domains.forEach(domain => { if (!document.querySelector(`link[rel="dns-prefetch"][href*="${domain}"]`)) { const link = document.createElement('link'); link.rel = 'dns-prefetch'; link.href = `https://${domain}`; document.head.appendChild(link); } }); // 预连接到关键域名 const preconnectDomains = ['fonts.gstatic.com']; preconnectDomains.forEach(domain => { if (!document.querySelector(`link[rel="preconnect"][href*="${domain}"]`)) { const link = document.createElement('link'); link.rel = 'preconnect'; link.href = `https://${domain}`; link.crossOrigin = ''; document.head.appendChild(link); } }); } // 缓存优化 function optimizeCache() { // Service Worker 注册(如果支持) if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js') .then(registration => { console.log('SW registered: ', registration); }) .catch(registrationError => { console.log('SW registration failed: ', registrationError); }); }); } // 本地存储优化 try { // 缓存静态数据 if (localStorage) { const cacheKey = 'page-cache-' + window.location.pathname; const cacheTime = 30 * 60 * 1000; // 30分钟 const cachedData = localStorage.getItem(cacheKey); if (cachedData) { const { timestamp, data } = JSON.parse(cachedData); if (Date.now() - timestamp < cacheTime) { // 使用缓存数据 console.log('Using cached data'); } } } } catch (e) { console.warn('LocalStorage not available'); } } // 动画性能优化 function optimizeAnimations() { // 检测是否需要减少动画 const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (prefersReducedMotion) { document.body.classList.add('reduce-motion'); // 添加减少动画的 CSS const style = document.createElement('style'); style.textContent = ` .reduce-motion *, .reduce-motion *::before, .reduce-motion *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } `; document.head.appendChild(style); } // 使用 transform 和 opacity 进行动画(硬件加速) document.querySelectorAll('[class*="animate-"]').forEach(el => { el.style.willChange = 'transform, opacity'; // 动画完成后移除 will-change el.addEventListener('animationend', function() { this.style.willChange = 'auto'; }, { once: true }); }); } // 内存优化 function optimizeMemory() { // 定期清理无用的 DOM 元素 const cleanup = () => { // 移除隐藏的元素(如果不再需要) document.querySelectorAll('.hidden, [style*="display: none"]').forEach(el => { if (el.dataset.keepHidden !== 'true') { // 这里可以添加更智能的清理逻辑 } }); }; // 每5分钟执行一次清理 setInterval(cleanup, 5 * 60 * 1000); // 监听内存压力(如果支持) if ('memory' in performance) { const checkMemory = () => { const used = performance.memory.usedJSHeapSize; const limit = performance.memory.jsHeapSizeLimit; const usage = used / limit; if (usage > 0.8) { console.warn('High memory usage detected:', Math.round(usage * 100) + '%'); cleanup(); } }; setInterval(checkMemory, 30000); // 每30秒检查一次 } } // 性能监控和报告 function monitorPerformance() { // 使用 Performance Observer 监控 if ('PerformanceObserver' in window) { // 监控 Long Tasks const longTaskObserver = new PerformanceObserver(list => { list.getEntries().forEach(entry => { if (entry.duration > 50) { console.warn('Long task detected:', entry.duration + 'ms'); } }); }); try { longTaskObserver.observe({ entryTypes: ['longtask'] }); } catch (e) { // longtask 不被支持 } // 监控 Layout Shift const clsObserver = new PerformanceObserver(list => { list.getEntries().forEach(entry => { if (entry.value > 0.1) { console.warn('Layout shift detected:', entry.value); } }); }); try { clsObserver.observe({ entryTypes: ['layout-shift'] }); } catch (e) { // layout-shift 不被支持 } } } // 添加性能优化样式 function addPerformanceStyles() { const style = document.createElement('style'); style.textContent = ` /* 硬件加速 */ .gpu-accelerated { transform: translateZ(0); will-change: transform, opacity; } /* 图片加载状态 */ img.loading { opacity: 0.3; filter: blur(5px); transition: opacity 0.3s, filter 0.3s; } img.loaded { opacity: 1; filter: none; } img.error { opacity: 0; display: none !important; } /* 字体加载优化 */ .font-loading { font-display: swap; } /* 减少重绘 */ .contain-layout { contain: layout; } .contain-paint { contain: paint; } /* 滚动优化 */ .scroll-smooth { scroll-behavior: smooth; -webkit-overflow-scrolling: touch; } `; document.head.appendChild(style); } // 初始化性能优化 function init() { if (isOptimizing) return; isOptimizing = true; // 立即执行的优化 optimizeResourceLoading(); optimizeCSS(); optimizeNetwork(); addPerformanceStyles(); // DOM 加载完成后执行 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { optimizeImages(); optimizeJavaScript(); optimizeAnimations(); monitorPerformance(); }); } else { optimizeImages(); optimizeJavaScript(); optimizeAnimations(); monitorPerformance(); } // 页面完全加载后执行 window.addEventListener('load', () => { optimizeCache(); optimizeMemory(); // 测量性能 setTimeout(() => { const perf = measurePerformance(); console.log('Performance metrics:', perf); // 发送性能数据到分析系统(如果需要) if (window.gtag) { gtag('event', 'performance', { 'page_load_time': Math.round(perf.pageLoading), 'dom_load_time': Math.round(perf.domLoading) }); } }, 1000); }); } // 提供外部接口 window.PerformanceOptimizer = { measurePerformance, optimizeImages, getPerformanceData: () => performanceData }; // 初始化 init(); })();