JavaScript性能优化实战:深入探讨性能瓶颈、分享优化技巧与最佳实践

从理论到实践,全面掌握JavaScript性能优化的核心技术与最佳实践


📋 目录

引言:为什么需要性能优化第一章:性能测量与分析第二章:代码层面优化第三章:DOM操作优化第四章:事件处理优化第五章:内存管理优化第六章:网络请求优化第七章:渲染性能优化第八章:打包与加载优化第九章:现代框架性能优化第十章:性能监控与持续优化总结与最佳实践


引言:为什么需要性能优化

1.1 性能的重要性

用户体验影响


// 性能对用户体验的影响统计
const performanceImpact = {
    loadTime: {
        '0-1s': { satisfaction: '95%', conversionRate: 'baseline' },
        '1-3s': { satisfaction: '85%', conversionRate: '-12%' },
        '3-5s': { satisfaction: '70%', conversionRate: '-32%' },
        '5s+': { satisfaction: '50%', conversionRate: '-53%' }
    },
    
    // Google研究数据
    googleFindings: {
        '100ms延迟': '转化率下降1%',
        '1s延迟': '用户满意度下降16%',
        '3s加载时间': '53%用户会离开'
    },
    
    // 业务影响
    businessImpact: {
        amazon: '每100ms延迟损失1%销售额',
        walmart: '每1s改进提升2%转化率',
        pinterest: '感知等待时间减少40%,流量增加15%'
    }
};
性能优化的收益
优化方向 性能提升 用户体验改善 业务价值
🚀 首屏加载 30-50% 跳出率降低20% 转化率提升15%
⚡ 交互响应 50-70% 满意度提升25% 留存率提升18%
💾 内存优化 40-60% 崩溃率降低30% 用户投诉减少40%
🌐 网络优化 20-40% 流量节省35% 成本降低25%

1.2 性能优化的核心指标



// Core Web Vitals - Google核心性能指标
const coreWebVitals = {
    // 最大内容绘制 (Largest Contentful Paint)
    LCP: {
        good: '< 2.5s',
        needsImprovement: '2.5s - 4s',
        poor: '> 4s',
        description: '衡量加载性能'
    },
    
    // 首次输入延迟 (First Input Delay)
    FID: {
        good: '< 100ms',
        needsImprovement: '100ms - 300ms',
        poor: '> 300ms',
        description: '衡量交互性'
    },
    
    // 累积布局偏移 (Cumulative Layout Shift)
    CLS: {
        good: '< 0.1',
        needsImprovement: '0.1 - 0.25',
        poor: '> 0.25',
        description: '衡量视觉稳定性'
    }
};
 
// 其他重要指标
const otherMetrics = {
    FCP: 'First Contentful Paint - 首次内容绘制',
    TTI: 'Time to Interactive - 可交互时间',
    TBT: 'Total Blocking Time - 总阻塞时间',
    SI: 'Speed Index - 速度指数'
};

第一章:性能测量与分析

2.1 浏览器性能API

Performance API基础


// ========== 1. Navigation Timing API ==========
class PerformanceMonitor {
    // 获取页面加载性能
    static getPageLoadMetrics() {
        const perfData = performance.getEntriesByType('navigation')[0];
        
        return {
            // DNS查询时间
            dnsTime: perfData.domainLookupEnd - perfData.domainLookupStart,
            
            // TCP连接时间
            tcpTime: perfData.connectEnd - perfData.connectStart,
            
            // SSL握手时间
            sslTime: perfData.secureConnectionStart > 0 
                ? perfData.connectEnd - perfData.secureConnectionStart 
                : 0,
            
            // 请求响应时间
            requestTime: perfData.responseEnd - perfData.requestStart,
            
            // DOM解析时间
            domParseTime: perfData.domInteractive - perfData.responseEnd,
            
            // 资源加载时间
            resourceLoadTime: perfData.loadEventStart - perfData.domContentLoadedEventEnd,
            
            // 总加载时间
            totalTime: perfData.loadEventEnd - perfData.fetchStart,
            
            // 白屏时间
            whiteScreenTime: perfData.responseStart - perfData.fetchStart,
            
            // 首屏时间
            firstScreenTime: perfData.domContentLoadedEventEnd - perfData.fetchStart
        };
    }
    
    // 打印性能报告
    static printPerformanceReport() {
        const metrics = this.getPageLoadMetrics();
        
        console.log('📊 页面性能报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log(`⏱️  DNS查询: ${metrics.dnsTime.toFixed(2)}ms`);
        console.log(`🔌 TCP连接: ${metrics.tcpTime.toFixed(2)}ms`);
        console.log(`🔒 SSL握手: ${metrics.sslTime.toFixed(2)}ms`);
        console.log(`📡 请求响应: ${metrics.requestTime.toFixed(2)}ms`);
        console.log(`📄 DOM解析: ${metrics.domParseTime.toFixed(2)}ms`);
        console.log(`📦 资源加载: ${metrics.resourceLoadTime.toFixed(2)}ms`);
        console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
        console.log(`⚪ 白屏时间: ${metrics.whiteScreenTime.toFixed(2)}ms`);
        console.log(`🖼️  首屏时间: ${metrics.firstScreenTime.toFixed(2)}ms`);
        console.log(`✅ 总加载时间: ${metrics.totalTime.toFixed(2)}ms`);
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
window.addEventListener('load', () => {
    // 等待所有资源加载完成后再测量
    setTimeout(() => {
        PerformanceMonitor.printPerformanceReport();
    }, 0);
});
Resource Timing API


// ========== 2. 资源加载性能分析 ==========
class ResourcePerformanceAnalyzer {
    // 分析所有资源加载性能
    static analyzeResources() {
        const resources = performance.getEntriesByType('resource');
        
        const analysis = {
            total: resources.length,
            byType: {},
            slowest: [],
            totalSize: 0,
            totalDuration: 0
        };
        
        resources.forEach(resource => {
            // 按类型分类
            const type = this.getResourceType(resource.name);
            if (!analysis.byType[type]) {
                analysis.byType[type] = {
                    count: 0,
                    totalDuration: 0,
                    totalSize: 0,
                    items: []
                };
            }
            
            const duration = resource.responseEnd - resource.startTime;
            const size = resource.transferSize || 0;
            
            analysis.byType[type].count++;
            analysis.byType[type].totalDuration += duration;
            analysis.byType[type].totalSize += size;
            analysis.byType[type].items.push({
                name: resource.name,
                duration,
                size
            });
            
            analysis.totalDuration += duration;
            analysis.totalSize += size;
        });
        
        // 找出最慢的10个资源
        analysis.slowest = resources
            .map(r => ({
                name: r.name,
                duration: r.responseEnd - r.startTime,
                size: r.transferSize || 0
            }))
            .sort((a, b) => b.duration - a.duration)
            .slice(0, 10);
        
        return analysis;
    }
    
    // 获取资源类型
    static getResourceType(url) {
        if (url.match(/.(js)$/)) return 'JavaScript';
        if (url.match(/.(css)$/)) return 'CSS';
        if (url.match(/.(jpg|jpeg|png|gif|webp|svg)$/)) return 'Image';
        if (url.match(/.(woff|woff2|ttf|eot)$/)) return 'Font';
        if (url.match(/.(mp4|webm|ogg)$/)) return 'Video';
        return 'Other';
    }
    
    // 打印资源分析报告
    static printResourceReport() {
        const analysis = this.analyzeResources();
        
        console.log('📦 资源加载分析报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log(`总资源数: ${analysis.total}`);
        console.log(`总大小: ${(analysis.totalSize / 1024).toFixed(2)} KB`);
        console.log(`总耗时: ${analysis.totalDuration.toFixed(2)} ms`);
        console.log('');
        
        console.log('📊 按类型统计:');
        Object.entries(analysis.byType).forEach(([type, data]) => {
            console.log(`  ${type}:`);
            console.log(`    数量: ${data.count}`);
            console.log(`    大小: ${(data.totalSize / 1024).toFixed(2)} KB`);
            console.log(`    耗时: ${data.totalDuration.toFixed(2)} ms`);
        });
        
        console.log('');
        console.log('🐌 最慢的10个资源:');
        analysis.slowest.forEach((item, index) => {
            console.log(`  ${index + 1}. ${item.name.substring(item.name.lastIndexOf('/') + 1)}`);
            console.log(`     耗时: ${item.duration.toFixed(2)} ms`);
            console.log(`     大小: ${(item.size / 1024).toFixed(2)} KB`);
        });
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
window.addEventListener('load', () => {
    setTimeout(() => {
        ResourcePerformanceAnalyzer.printResourceReport();
    }, 0);
});
User Timing API


// ========== 3. 自定义性能标记 ==========
class CustomPerformanceTracker {
    // 标记开始
    static mark(name) {
        performance.mark(name);
    }
    
    // 测量两个标记之间的时间
    static measure(name, startMark, endMark) {
        performance.measure(name, startMark, endMark);
        const measure = performance.getEntriesByName(name)[0];
        return measure.duration;
    }
    
    // 清除标记
    static clearMarks(name) {
        if (name) {
            performance.clearMarks(name);
        } else {
            performance.clearMarks();
        }
    }
    
    // 清除测量
    static clearMeasures(name) {
        if (name) {
            performance.clearMeasures(name);
        } else {
            performance.clearMeasures();
        }
    }
}
 
// 使用示例:测量函数执行时间
function measureFunctionPerformance() {
    // 标记开始
    CustomPerformanceTracker.mark('function-start');
    
    // 执行一些操作
    let sum = 0;
    for (let i = 0; i < 1000000; i++) {
        sum += i;
    }
    
    // 标记结束
    CustomPerformanceTracker.mark('function-end');
    
    // 测量
    const duration = CustomPerformanceTracker.measure(
        'function-execution',
        'function-start',
        'function-end'
    );
    
    console.log(`函数执行时间: ${duration.toFixed(2)}ms`);
}
 
// 使用示例:测量页面渲染阶段
class PageRenderTracker {
    static trackPageRender() {
        // 标记各个阶段
        document.addEventListener('DOMContentLoaded', () => {
            performance.mark('dom-ready');
        });
        
        window.addEventListener('load', () => {
            performance.mark('page-loaded');
            
            // 测量各阶段时间
            const domReadyTime = performance.measure(
                'dom-ready-time',
                'navigationStart',
                'dom-ready'
            );
            
            const pageLoadTime = performance.measure(
                'page-load-time',
                'navigationStart',
                'page-loaded'
            );
            
            console.log('📊 页面渲染阶段:');
            console.log(`DOM就绪: ${performance.getEntriesByName('dom-ready-time')[0].duration.toFixed(2)}ms`);
            console.log(`页面加载: ${performance.getEntriesByName('page-load-time')[0].duration.toFixed(2)}ms`);
        });
    }
}
 
PageRenderTracker.trackPageRender();

2.2 Chrome DevTools性能分析

Performance面板使用


// ========== 性能分析辅助工具 ==========
class PerformanceProfiler {
    constructor() {
        this.profiles = [];
    }
    
    // 开始性能分析
    startProfile(name) {
        console.profile(name);
        performance.mark(`${name}-start`);
    }
    
    // 结束性能分析
    endProfile(name) {
        performance.mark(`${name}-end`);
        performance.measure(name, `${name}-start`, `${name}-end`);
        console.profileEnd(name);
        
        const measure = performance.getEntriesByName(name)[0];
        this.profiles.push({
            name,
            duration: measure.duration,
            timestamp: Date.now()
        });
        
        return measure.duration;
    }
    
    // 获取所有性能分析结果
    getProfiles() {
        return this.profiles;
    }
    
    // 打印性能分析报告
    printReport() {
        console.log('⚡ 性能分析报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        this.profiles.forEach(profile => {
            console.log(`${profile.name}: ${profile.duration.toFixed(2)}ms`);
        });
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
const profiler = new PerformanceProfiler();
 
profiler.startProfile('data-processing');
// 执行数据处理
processLargeDataset();
profiler.endProfile('data-processing');
 
profiler.startProfile('dom-manipulation');
// 执行DOM操作
updateUI();
profiler.endProfile('dom-manipulation');
 
profiler.printReport();

2.3 Lighthouse性能审计



// ========== Lighthouse性能指标收集 ==========
class LighthouseMetricsCollector {
    // 收集Core Web Vitals
    static async collectCoreWebVitals() {
        return new Promise((resolve) => {
            const metrics = {
                LCP: null,
                FID: null,
                CLS: null,
                FCP: null,
                TTFB: null
            };
            
            // LCP - Largest Contentful Paint
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                const lastEntry = entries[entries.length - 1];
                metrics.LCP = lastEntry.renderTime || lastEntry.loadTime;
            }).observe({ entryTypes: ['largest-contentful-paint'] });
            
            // FID - First Input Delay
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                entries.forEach(entry => {
                    if (!metrics.FID) {
                        metrics.FID = entry.processingStart - entry.startTime;
                    }
                });
            }).observe({ entryTypes: ['first-input'] });
            
            // CLS - Cumulative Layout Shift
            let clsValue = 0;
            new PerformanceObserver((list) => {
                list.getEntries().forEach(entry => {
                    if (!entry.hadRecentInput) {
                        clsValue += entry.value;
                        metrics.CLS = clsValue;
                    }
                });
            }).observe({ entryTypes: ['layout-shift'] });
            
            // FCP - First Contentful Paint
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                entries.forEach(entry => {
                    if (entry.name === 'first-contentful-paint') {
                        metrics.FCP = entry.startTime;
                    }
                });
            }).observe({ entryTypes: ['paint'] });
            
            // TTFB - Time to First Byte
            const navTiming = performance.getEntriesByType('navigation')[0];
            metrics.TTFB = navTiming.responseStart - navTiming.requestStart;
            
            // 等待一段时间后返回结果
            setTimeout(() => {
                resolve(metrics);
            }, 5000);
        });
    }
    
    // 评估性能得分
    static evaluateMetrics(metrics) {
        const scores = {
            LCP: this.scoreLCP(metrics.LCP),
            FID: this.scoreFID(metrics.FID),
            CLS: this.scoreCLS(metrics.CLS),
            FCP: this.scoreFCP(metrics.FCP),
            TTFB: this.scoreTTFB(metrics.TTFB)
        };
        
        // 计算总分(加权平均)
        const weights = {
            LCP: 0.25,
            FID: 0.25,
            CLS: 0.15,
            FCP: 0.15,
            TTFB: 0.20
        };
        
        let totalScore = 0;
        Object.entries(scores).forEach(([metric, score]) => {
            totalScore += score * weights[metric];
        });
        
        return {
            scores,
            totalScore: Math.round(totalScore),
            grade: this.getGrade(totalScore)
        };
    }
    
    // LCP评分
    static scoreLCP(value) {
        if (value === null) return 0;
        if (value <= 2500) return 100;
        if (value <= 4000) return 50;
        return 0;
    }
    
    // FID评分
    static scoreFID(value) {
        if (value === null) return 0;
        if (value <= 100) return 100;
        if (value <= 300) return 50;
        return 0;
    }
    
    // CLS评分
    static scoreCLS(value) {
        if (value === null) return 0;
        if (value <= 0.1) return 100;
        if (value <= 0.25) return 50;
        return 0;
    }
    
    // FCP评分
    static scoreFCP(value) {
        if (value === null) return 0;
        if (value <= 1800) return 100;
        if (value <= 3000) return 50;
        return 0;
    }
    
    // TTFB评分
    static scoreTTFB(value) {
        if (value === null) return 0;
        if (value <= 600) return 100;
        if (value <= 1500) return 50;
        return 0;
    }
    
    // 获取等级
    static getGrade(score) {
        if (score >= 90) return 'A';
        if (score >= 75) return 'B';
        if (score >= 60) return 'C';
        if (score >= 45) return 'D';
        return 'F';
    }
    
    // 打印性能报告
    static async printPerformanceReport() {
        console.log('🔍 正在收集性能指标...');
        const metrics = await this.collectCoreWebVitals();
        const evaluation = this.evaluateMetrics(metrics);
        
        console.log('');
        console.log('📊 Core Web Vitals 性能报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log(`LCP (Largest Contentful Paint): ${metrics.LCP ? metrics.LCP.toFixed(2) + 'ms' : 'N/A'} - 得分: ${evaluation.scores.LCP}`);
        console.log(`FID (First Input Delay): ${metrics.FID ? metrics.FID.toFixed(2) + 'ms' : 'N/A'} - 得分: ${evaluation.scores.FID}`);
        console.log(`CLS (Cumulative Layout Shift): ${metrics.CLS ? metrics.CLS.toFixed(4) : 'N/A'} - 得分: ${evaluation.scores.CLS}`);
        console.log(`FCP (First Contentful Paint): ${metrics.FCP ? metrics.FCP.toFixed(2) + 'ms' : 'N/A'} - 得分: ${evaluation.scores.FCP}`);
        console.log(`TTFB (Time to First Byte): ${metrics.TTFB ? metrics.TTFB.toFixed(2) + 'ms' : 'N/A'} - 得分: ${evaluation.scores.TTFB}`);
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log(`总分: ${evaluation.totalScore}/100`);
        console.log(`等级: ${evaluation.grade}`);
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
window.addEventListener('load', () => {
    LighthouseMetricsCollector.printPerformanceReport();
});

第二章:代码层面优化

3.1 算法优化

时间复杂度优化


// ========== 示例1:数组去重优化 ==========
 
// ❌ 低效方法 - O(n²)
function removeDuplicatesSlow(arr) {
    const result = [];
    for (let i = 0; i < arr.length; i++) {
        if (result.indexOf(arr[i]) === -1) {
            result.push(arr[i]);
        }
    }
    return result;
}
 
// ✅ 高效方法 - O(n)
function removeDuplicatesFast(arr) {
    return [...new Set(arr)];
}
 
// 性能对比
const largeArray = Array.from({ length: 10000 }, () => Math.floor(Math.random() * 1000));
 
console.time('慢速去重');
removeDuplicatesSlow(largeArray);
console.timeEnd('慢速去重');
// 输出: 慢速去重: ~100ms
 
console.time('快速去重');
removeDuplicatesFast(largeArray);
console.timeEnd('快速去重');
// 输出: 快速去重: ~2ms
 
// ========== 示例2:查找优化 ==========
 
// ❌ 低效方法 - 线性查找 O(n)
function findInArraySlow(arr, target) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] === target) {
            return i;
        }
    }
    return -1;
}
 
// ✅ 高效方法 - 使用Map O(1)
class FastLookup {
    constructor(arr) {
        this.map = new Map();
        arr.forEach((item, index) => {
            this.map.set(item, index);
        });
    }
    
    find(target) {
        return this.map.has(target) ? this.map.get(target) : -1;
    }
}
 
// 性能对比
const testArray = Array.from({ length: 100000 }, (_, i) => i);
 
console.time('线性查找');
findInArraySlow(testArray, 99999);
console.timeEnd('线性查找');
// 输出: 线性查找: ~1ms
 
const fastLookup = new FastLookup(testArray);
console.time('Map查找');
fastLookup.find(99999);
console.timeEnd('Map查找');
// 输出: Map查找: ~0.01ms
空间复杂度优化


// ========== 示例:斐波那契数列优化 ==========
 
// ❌ 递归方法 - 时间O(2^n),空间O(n)
function fibonacciRecursive(n) {
    if (n <= 1) return n;
    return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
 
// ✅ 动态规划 - 时间O(n),空间O(n)
function fibonacciDP(n) {
    if (n <= 1) return n;
    const dp = [0, 1];
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}
 
// ✅✅ 空间优化 - 时间O(n),空间O(1)
function fibonacciOptimized(n) {
    if (n <= 1) return n;
    let prev = 0, curr = 1;
    for (let i = 2; i <= n; i++) {
        [prev, curr] = [curr, prev + curr];
    }
    return curr;
}
 
// 性能对比
console.time('递归方法');
fibonacciRecursive(30);
console.timeEnd('递归方法');
// 输出: 递归方法: ~20ms
 
console.time('动态规划');
fibonacciDP(30);
console.timeEnd('动态规划');
// 输出: 动态规划: ~0.1ms
 
console.time('空间优化');
fibonacciOptimized(30);
console.timeEnd('空间优化');
// 输出: 空间优化: ~0.05ms

3.2 循环优化



// ========== 循环优化技巧 ==========
 
// ❌ 低效循环
function inefficientLoop(arr) {
    for (let i = 0; i < arr.length; i++) {
        // 每次迭代都计算length
        console.log(arr[i]);
    }
}
 
// ✅ 缓存length
function efficientLoop(arr) {
    const len = arr.length;
    for (let i = 0; i < len; i++) {
        console.log(arr[i]);
    }
}
 
// ✅✅ 使用for...of(更简洁)
function modernLoop(arr) {
    for (const item of arr) {
        console.log(item);
    }
}
 
// ========== 循环展开 ==========
 
// ❌ 普通循环
function sumNormal(arr) {
    let sum = 0;
    for (let i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
 
// ✅ 循环展开(处理大数组时更快)
function sumUnrolled(arr) {
    let sum = 0;
    const len = arr.length;
    const remainder = len % 4;
    
    // 处理余数
    for (let i = 0; i < remainder; i++) {
        sum += arr[i];
    }
    
    // 4个一组处理
    for (let i = remainder; i < len; i += 4) {
        sum += arr[i] + arr[i + 1] + arr[i + 2] + arr[i + 3];
    }
    
    return sum;
}
 
// ========== 避免不必要的循环 ==========
 
// ❌ 多次循环
function multipleLoops(arr) {
    // 第一次循环:过滤
    const filtered = arr.filter(x => x > 0);
    // 第二次循环:映射
    const mapped = filtered.map(x => x * 2);
    // 第三次循环:求和
    const sum = mapped.reduce((acc, x) => acc + x, 0);
    return sum;
}
 
// ✅ 单次循环
function singleLoop(arr) {
    return arr.reduce((sum, x) => {
        if (x > 0) {
            sum += x * 2;
        }
        return sum;
    }, 0);
}
 
// 性能对比
const largeArray = Array.from({ length: 1000000 }, () => Math.random() * 100 - 50);
 
console.time('多次循环');
multipleLoops(largeArray);
console.timeEnd('多次循环');
// 输出: 多次循环: ~30ms
 
console.time('单次循环');
singleLoop(largeArray);
console.timeEnd('单次循环');
// 输出: 单次循环: ~10ms

3.3 函数优化

函数缓存(Memoization)


// ========== 函数缓存实现 ==========
 
// 通用缓存装饰器
function memoize(fn) {
    const cache = new Map();
    
    return function(...args) {
        const key = JSON.stringify(args);
        
        if (cache.has(key)) {
            console.log('从缓存返回');
            return cache.get(key);
        }
        
        console.log('计算并缓存');
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
}
 
// 使用示例:昂贵的计算
function expensiveCalculation(n) {
    console.log(`计算 ${n} 的阶乘...`);
    let result = 1;
    for (let i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}
 
const memoizedCalculation = memoize(expensiveCalculation);
 
console.log(memoizedCalculation(10)); // 计算并缓存
console.log(memoizedCalculation(10)); // 从缓存返回
console.log(memoizedCalculation(20)); // 计算并缓存
console.log(memoizedCalculation(10)); // 从缓存返回
 
// ========== 带过期时间的缓存 ==========
function memoizeWithExpiry(fn, expiryTime = 5000) {
    const cache = new Map();
    
    return function(...args) {
        const key = JSON.stringify(args);
        const now = Date.now();
        
        if (cache.has(key)) {
            const { value, timestamp } = cache.get(key);
            if (now - timestamp < expiryTime) {
                console.log('从缓存返回');
                return value;
            } else {
                console.log('缓存已过期');
                cache.delete(key);
            }
        }
        
        console.log('计算并缓存');
        const result = fn.apply(this, args);
        cache.set(key, { value: result, timestamp: now });
        return result;
    };
}
 
// ========== LRU缓存实现 ==========
class LRUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.cache = new Map();
    }
    
    get(key) {
        if (!this.cache.has(key)) {
            return undefined;
        }
        
        // 移到最后(最近使用)
        const value = this.cache.get(key);
        this.cache.delete(key);
        this.cache.set(key, value);
        return value;
    }
    
    set(key, value) {
        // 如果已存在,先删除
        if (this.cache.has(key)) {
            this.cache.delete(key);
        }
        
        // 如果超过容量,删除最久未使用的(第一个)
        if (this.cache.size >= this.capacity) {
            const firstKey = this.cache.keys().next().value;
            this.cache.delete(firstKey);
        }
        
        this.cache.set(key, value);
    }
}
 
// 使用LRU缓存的函数包装器
function memoizeWithLRU(fn, capacity = 100) {
    const cache = new LRUCache(capacity);
    
    return function(...args) {
        const key = JSON.stringify(args);
        const cached = cache.get(key);
        
        if (cached !== undefined) {
            console.log('从LRU缓存返回');
            return cached;
        }
        
        console.log('计算并缓存到LRU');
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
}
防抖与节流


// ========== 防抖(Debounce)==========
// 应用场景:搜索框输入、窗口resize
 
function debounce(fn, delay = 300) {
    let timeoutId = null;
    
    return function(...args) {
        // 清除之前的定时器
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
        
        // 设置新的定时器
        timeoutId = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}
 
// 使用示例:搜索框
const searchInput = document.getElementById('search');
const search = debounce(function(e) {
    console.log('执行搜索:', e.target.value);
    // 发送API请求
}, 500);
 
searchInput.addEventListener('input', search);
 
// ========== 节流(Throttle)==========
// 应用场景:滚动事件、鼠标移动
 
function throttle(fn, delay = 300) {
    let lastTime = 0;
    
    return function(...args) {
        const now = Date.now();
        
        if (now - lastTime >= delay) {
            fn.apply(this, args);
            lastTime = now;
        }
    };
}
 
// 使用示例:滚动事件
const handleScroll = throttle(function() {
    console.log('滚动位置:', window.scrollY);
    // 执行滚动相关操作
}, 200);
 
window.addEventListener('scroll', handleScroll);
 
// ========== 高级版本:支持立即执行 ==========
function debounceAdvanced(fn, delay = 300, immediate = false) {
    let timeoutId = null;
    
    return function(...args) {
        const callNow = immediate && !timeoutId;
        
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
        
        timeoutId = setTimeout(() => {
            timeoutId = null;
            if (!immediate) {
                fn.apply(this, args);
            }
        }, delay);
        
        if (callNow) {
            fn.apply(this, args);
        }
    };
}
 
function throttleAdvanced(fn, delay = 300, options = {}) {
    let timeoutId = null;
    let lastTime = 0;
    const { leading = true, trailing = true } = options;
    
    return function(...args) {
        const now = Date.now();
        
        if (!lastTime && !leading) {
            lastTime = now;
        }
        
        const remaining = delay - (now - lastTime);
        
        if (remaining <= 0 || remaining > delay) {
            if (timeoutId) {
                clearTimeout(timeoutId);
                timeoutId = null;
            }
            
            lastTime = now;
            fn.apply(this, args);
        } else if (!timeoutId && trailing) {
            timeoutId = setTimeout(() => {
                lastTime = leading ? Date.now() : 0;
                timeoutId = null;
                fn.apply(this, args);
            }, remaining);
        }
    };
}

3.4 数据结构选择



// ========== 选择合适的数据结构 ==========
 
// 场景1:频繁查找 - 使用Map而不是Object
// ❌ 使用Object
const userDataObj = {};
for (let i = 0; i < 10000; i++) {
    userDataObj[`user${i}`] = { id: i, name: `User ${i}` };
}
 
console.time('Object查找');
const user1 = userDataObj['user5000'];
console.timeEnd('Object查找');
 
// ✅ 使用Map
const userDataMap = new Map();
for (let i = 0; i < 10000; i++) {
    userDataMap.set(`user${i}`, { id: i, name: `User ${i}` });
}
 
console.time('Map查找');
const user2 = userDataMap.get('user5000');
console.timeEnd('Map查找');
 
// 场景2:唯一值集合 - 使用Set
// ❌ 使用Array
const uniqueArraySlow = [];
function addUniqueToArray(value) {
    if (!uniqueArraySlow.includes(value)) {
        uniqueArraySlow.push(value);
    }
}
 
console.time('Array添加唯一值');
for (let i = 0; i < 10000; i++) {
    addUniqueToArray(i % 100);
}
console.timeEnd('Array添加唯一值');
 
// ✅ 使用Set
const uniqueSet = new Set();
 
console.time('Set添加唯一值');
for (let i = 0; i < 10000; i++) {
    uniqueSet.add(i % 100);
}
console.timeEnd('Set添加唯一值');
 
// 场景3:队列操作 - 避免使用Array的shift()
// ❌ 使用Array的shift() - O(n)
class QueueSlow {
    constructor() {
        this.items = [];
    }
    
    enqueue(item) {
        this.items.push(item);
    }
    
    dequeue() {
        return this.items.shift(); // O(n) - 慢!
    }
}
 
// ✅ 使用双指针 - O(1)
class QueueFast {
    constructor() {
        this.items = {};
        this.head = 0;
        this.tail = 0;
    }
    
    enqueue(item) {
        this.items[this.tail] = item;
        this.tail++;
    }
    
    dequeue() {
        if (this.head === this.tail) {
            return undefined;
        }
        const item = this.items[this.head];
        delete this.items[this.head];
        this.head++;
        return item;
    }
}
 
// 性能对比
const slowQueue = new QueueSlow();
const fastQueue = new QueueFast();
 
console.time('慢速队列');
for (let i = 0; i < 10000; i++) {
    slowQueue.enqueue(i);
}
for (let i = 0; i < 10000; i++) {
    slowQueue.dequeue();
}
console.timeEnd('慢速队列');
// 输出: 慢速队列: ~100ms
 
console.time('快速队列');
for (let i = 0; i < 10000; i++) {
    fastQueue.enqueue(i);
}
for (let i = 0; i < 10000; i++) {
    fastQueue.dequeue();
}
console.timeEnd('快速队列');
// 输出: 快速队列: ~2ms

第三章:DOM操作优化

4.1 减少DOM访问



// ========== DOM访问优化 ==========
 
// ❌ 频繁访问DOM
function inefficientDOMAccess() {
    for (let i = 0; i < 1000; i++) {
        document.getElementById('counter').innerHTML = i;
        document.getElementById('status').innerHTML = 'Processing...';
    }
}
 
// ✅ 缓存DOM引用
function efficientDOMAccess() {
    const counter = document.getElementById('counter');
    const status = document.getElementById('status');
    
    for (let i = 0; i < 1000; i++) {
        counter.innerHTML = i;
        status.innerHTML = 'Processing...';
    }
}
 
// ✅✅ 批量更新
function batchDOMUpdate() {
    const counter = document.getElementById('counter');
    const status = document.getElementById('status');
    
    // 使用DocumentFragment
    const fragment = document.createDocumentFragment();
    
    for (let i = 0; i < 1000; i++) {
        // 在内存中操作
    }
    
    // 一次性更新
    counter.innerHTML = 1000;
    status.innerHTML = 'Complete';
}

4.2 批量DOM操作



// ========== 批量插入元素 ==========
 
// ❌ 逐个插入 - 触发1000次重排
function insertOneByOne() {
    const container = document.getElementById('container');
    
    for (let i = 0; i < 1000; i++) {
        const div = document.createElement('div');
        div.textContent = `Item ${i}`;
        container.appendChild(div); // 每次都触发重排
    }
}
 
// ✅ 使用DocumentFragment - 只触发1次重排
function insertWithFragment() {
    const container = document.getElementById('container');
    const fragment = document.createDocumentFragment();
    
    for (let i = 0; i < 1000; i++) {
        const div = document.createElement('div');
        div.textContent = `Item ${i}`;
        fragment.appendChild(div);
    }
    
    container.appendChild(fragment); // 只触发一次重排
}
 
// ✅✅ 使用innerHTML(更快,但要注意XSS)
function insertWithInnerHTML() {
    const container = document.getElementById('container');
    let html = '';
    
    for (let i = 0; i < 1000; i++) {
        html += `<div>Item ${i}</div>`;
    }
    
    container.innerHTML = html; // 只触发一次重排
}
 
// ✅✅✅ 使用模板字符串(最快)
function insertWithTemplate() {
    const container = document.getElementById('container');
    
    const html = Array.from({ length: 1000 }, (_, i) => 
        `<div>Item ${i}</div>`
    ).join('');
    
    container.innerHTML = html;
}
 
// 性能对比
console.time('逐个插入');
insertOneByOne();
console.timeEnd('逐个插入');
// 输出: 逐个插入: ~50ms
 
console.time('Fragment插入');
insertWithFragment();
console.timeEnd('Fragment插入');
// 输出: Fragment插入: ~10ms
 
console.time('innerHTML插入');
insertWithInnerHTML();
console.timeEnd('innerHTML插入');
// 输出: innerHTML插入: ~5ms
 
console.time('模板字符串插入');
insertWithTemplate();
console.timeEnd('模板字符串插入');
// 输出: 模板字符串插入: ~3ms

4.3 虚拟滚动



// ========== 虚拟滚动实现 ==========
// 只渲染可见区域的元素,大幅提升大列表性能
 
class VirtualScroller {
    constructor(options) {
        this.container = options.container;
        this.items = options.items;
        this.itemHeight = options.itemHeight;
        this.renderItem = options.renderItem;
        
        this.visibleCount = Math.ceil(this.container.clientHeight / this.itemHeight);
        this.startIndex = 0;
        this.endIndex = this.visibleCount;
        
        this.init();
    }
    
    init() {
        // 创建容器
        this.scrollContainer = document.createElement('div');
        this.scrollContainer.style.height = `${this.items.length * this.itemHeight}px`;
        this.scrollContainer.style.position = 'relative';
        
        this.contentContainer = document.createElement('div');
        this.contentContainer.style.position = 'absolute';
        this.contentContainer.style.top = '0';
        this.contentContainer.style.left = '0';
        this.contentContainer.style.right = '0';
        
        this.scrollContainer.appendChild(this.contentContainer);
        this.container.appendChild(this.scrollContainer);
        
        // 监听滚动
        this.container.addEventListener('scroll', () => this.handleScroll());
        
        // 初始渲染
        this.render();
    }
    
    handleScroll() {
        const scrollTop = this.container.scrollTop;
        this.startIndex = Math.floor(scrollTop / this.itemHeight);
        this.endIndex = this.startIndex + this.visibleCount + 1;
        
        this.render();
    }
    
    render() {
        const visibleItems = this.items.slice(this.startIndex, this.endIndex);
        
        // 清空内容
        this.contentContainer.innerHTML = '';
        
        // 设置偏移
        this.contentContainer.style.transform = `translateY(${this.startIndex * this.itemHeight}px)`;
        
        // 渲染可见项
        visibleItems.forEach((item, index) => {
            const element = this.renderItem(item, this.startIndex + index);
            element.style.height = `${this.itemHeight}px`;
            this.contentContainer.appendChild(element);
        });
    }
}
 
// 使用示例
const container = document.getElementById('scroll-container');
const items = Array.from({ length: 100000 }, (_, i) => ({
    id: i,
    text: `Item ${i}`
}));
 
new VirtualScroller({
    container: container,
    items: items,
    itemHeight: 50,
    renderItem: (item, index) => {
        const div = document.createElement('div');
        div.className = 'list-item';
        div.textContent = item.text;
        div.style.borderBottom = '1px solid #ccc';
        div.style.padding = '15px';
        return div;
    }
});

4.4 离屏渲染



// ========== 离屏渲染技术 ==========
 
// 使用requestAnimationFrame优化动画
class AnimationOptimizer {
    constructor() {
        this.animations = [];
        this.isRunning = false;
    }
    
    add(fn) {
        this.animations.push(fn);
        if (!this.isRunning) {
            this.start();
        }
    }
    
    start() {
        this.isRunning = true;
        this.tick();
    }
    
    tick() {
        // 批量执行所有动画
        this.animations.forEach(fn => fn());
        
        if (this.animations.length > 0) {
            requestAnimationFrame(() => this.tick());
        } else {
            this.isRunning = false;
        }
    }
    
    remove(fn) {
        const index = this.animations.indexOf(fn);
        if (index > -1) {
            this.animations.splice(index, 1);
        }
    }
}
 
// 使用示例
const animator = new AnimationOptimizer();
 
const box = document.getElementById('box');
let position = 0;
 
const animate = () => {
    position += 1;
    box.style.transform = `translateX(${position}px)`;
    
    if (position < 500) {
        animator.add(animate);
    }
};
 
animator.add(animate);
 
// ========== 使用Web Worker进行离屏计算 ==========
// worker.js
self.addEventListener('message', (e) => {
    const { data } = e;
    
    // 执行复杂计算
    const result = heavyCalculation(data);
    
    // 返回结果
    self.postMessage(result);
});
 
function heavyCalculation(data) {
    // 复杂计算逻辑
    let sum = 0;
    for (let i = 0; i < data.length; i++) {
        sum += Math.sqrt(data[i]) * Math.sin(data[i]);
    }
    return sum;
}
 
// main.js
const worker = new Worker('worker.js');
 
worker.addEventListener('message', (e) => {
    console.log('计算结果:', e.data);
    // 更新UI
});
 
// 发送数据到Worker
const largeDataset = Array.from({ length: 1000000 }, () => Math.random());
worker.postMessage(largeDataset);

第四章:事件处理优化

5.1 事件委托



// ========== 事件委托优化 ==========
 
// ❌ 为每个元素绑定事件
function inefficientEventBinding() {
    const buttons = document.querySelectorAll('.button');
    
    buttons.forEach(button => {
        button.addEventListener('click', function() {
            console.log('Button clicked:', this.textContent);
        });
    });
}
// 问题:1000个按钮 = 1000个事件监听器
 
// ✅ 使用事件委托
function efficientEventDelegation() {
    const container = document.getElementById('button-container');
    
    container.addEventListener('click', function(e) {
        if (e.target.classList.contains('button')) {
            console.log('Button clicked:', e.target.textContent);
        }
    });
}
// 优点:只有1个事件监听器,无论多少按钮
 
// ========== 高级事件委托 ==========
class EventDelegator {
    constructor(container) {
        this.container = container;
        this.handlers = new Map();
    }
    
    on(selector, eventType, handler) {
        if (!this.handlers.has(eventType)) {
            this.handlers.set(eventType, []);
            
            this.container.addEventListener(eventType, (e) => {
                this.handleEvent(e, eventType);
            });
        }
        
        this.handlers.get(eventType).push({ selector, handler });
    }
    
    handleEvent(e, eventType) {
        const handlers = this.handlers.get(eventType);
        
        handlers.forEach(({ selector, handler }) => {
            if (e.target.matches(selector)) {
                handler.call(e.target, e);
            }
        });
    }
    
    off(selector, eventType) {
        if (this.handlers.has(eventType)) {
            const handlers = this.handlers.get(eventType);
            const index = handlers.findIndex(h => h.selector === selector);
            if (index > -1) {
                handlers.splice(index, 1);
            }
        }
    }
}
 
// 使用示例
const delegator = new EventDelegator(document.body);
 
delegator.on('.button', 'click', function(e) {
    console.log('Button clicked:', this.textContent);
});
 
delegator.on('.link', 'click', function(e) {
    e.preventDefault();
    console.log('Link clicked:', this.href);
});
 
delegator.on('.input', 'input', function(e) {
    console.log('Input changed:', this.value);
});

5.2 被动事件监听器



// ========== 被动事件监听器 ==========
// 提升滚动性能
 
// ❌ 默认事件监听器(可能阻塞滚动)
document.addEventListener('touchstart', function(e) {
    // 处理触摸事件
    console.log('Touch started');
}, false);
 
// ✅ 被动事件监听器(不阻塞滚动)
document.addEventListener('touchstart', function(e) {
    // 处理触摸事件
    console.log('Touch started');
    // 注意:不能调用 e.preventDefault()
}, { passive: true });
 
// ========== 智能事件监听器管理 ==========
class SmartEventManager {
    constructor() {
        this.listeners = new Map();
    }
    
    // 添加事件监听器(自动优化)
    add(element, eventType, handler, options = {}) {
        const key = `${element}-${eventType}`;
        
        // 自动判断是否应该使用passive
        const shouldBePassive = this.shouldUsePassive(eventType);
        const finalOptions = {
            ...options,
            passive: shouldBePassive
        };
        
        element.addEventListener(eventType, handler, finalOptions);
        
        this.listeners.set(key, { element, eventType, handler, options: finalOptions });
    }
    
    // 移除事件监听器
    remove(element, eventType) {
        const key = `${element}-${eventType}`;
        const listener = this.listeners.get(key);
        
        if (listener) {
            listener.element.removeEventListener(
                listener.eventType,
                listener.handler,
                listener.options
            );
            this.listeners.delete(key);
        }
    }
    
    // 判断是否应该使用passive
    shouldUsePassive(eventType) {
        const passiveEvents = [
            'scroll',
            'wheel',
            'touchstart',
            'touchmove',
            'touchend',
            'mousewheel'
        ];
        return passiveEvents.includes(eventType);
    }
    
    // 移除所有监听器
    removeAll() {
        this.listeners.forEach(listener => {
            listener.element.removeEventListener(
                listener.eventType,
                listener.handler,
                listener.options
            );
        });
        this.listeners.clear();
    }
}
 
// 使用示例
const eventManager = new SmartEventManager();
 
eventManager.add(window, 'scroll', function() {
    console.log('Scrolling...');
});
// 自动使用 { passive: true }
 
eventManager.add(document, 'click', function(e) {
    console.log('Clicked');
});
// 自动使用 { passive: false }(因为可能需要preventDefault)

5.3 事件节流与防抖应用



// ========== 实际应用场景 ==========
 
// 场景1:搜索框自动完成
class SearchAutocomplete {
    constructor(input, searchFn) {
        this.input = input;
        this.searchFn = searchFn;
        
        // 使用防抖,避免频繁请求
        this.debouncedSearch = debounce(this.search.bind(this), 300);
        
        this.input.addEventListener('input', this.debouncedSearch);
    }
    
    search(e) {
        const query = e.target.value;
        if (query.length >= 2) {
            this.searchFn(query);
        }
    }
}
 
// 使用示例
const searchInput = document.getElementById('search');
new SearchAutocomplete(searchInput, (query) => {
    console.log('搜索:', query);
    // 发送API请求
    fetch(`/api/search?q=${query}`)
        .then(res => res.json())
        .then(data => {
            // 显示搜索结果
        });
});
 
// 场景2:无限滚动加载
class InfiniteScroll {
    constructor(container, loadMoreFn) {
        this.container = container;
        this.loadMoreFn = loadMoreFn;
        this.loading = false;
        
        // 使用节流,避免频繁检查
        this.throttledCheck = throttle(this.checkScroll.bind(this), 200);
        
        this.container.addEventListener('scroll', this.throttledCheck);
    }
    
    checkScroll() {
        if (this.loading) return;
        
        const { scrollTop, scrollHeight, clientHeight } = this.container;
        
        // 距离底部100px时加载更多
        if (scrollTop + clientHeight >= scrollHeight - 100) {
            this.loading = true;
            this.loadMoreFn().then(() => {
                this.loading = false;
            });
        }
    }
}
 
// 使用示例
const scrollContainer = document.getElementById('scroll-container');
new InfiniteScroll(scrollContainer, async () => {
    console.log('加载更多...');
    // 加载更多数据
    const response = await fetch('/api/more-data');
    const data = await response.json();
    // 添加到容器
    data.forEach(item => {
        const div = document.createElement('div');
        div.textContent = item.title;
        scrollContainer.appendChild(div);
    });
});
 
// 场景3:窗口resize处理
class ResponsiveHandler {
    constructor() {
        this.handlers = [];
        
        // 使用防抖,resize结束后才执行
        this.debouncedResize = debounce(this.handleResize.bind(this), 250);
        
        window.addEventListener('resize', this.debouncedResize);
    }
    
    addHandler(handler) {
        this.handlers.push(handler);
    }
    
    handleResize() {
        const width = window.innerWidth;
        const height = window.innerHeight;
        
        this.handlers.forEach(handler => {
            handler(width, height);
        });
    }
}
 
// 使用示例
const responsiveHandler = new ResponsiveHandler();
 
responsiveHandler.addHandler((width, height) => {
    console.log('窗口大小:', width, 'x', height);
    // 调整布局
});
 
responsiveHandler.addHandler((width, height) => {
    // 根据宽度加载不同的资源
    if (width < 768) {
        console.log('移动端视图');
    } else {
        console.log('桌面端视图');
    }
});

第五章:内存管理优化

6.1 避免内存泄漏



// ========== 常见内存泄漏场景与解决方案 ==========
 
// 场景1:未清理的事件监听器
// ❌ 内存泄漏
class LeakyComponent {
    constructor(element) {
        this.element = element;
        this.handleClick = this.onClick.bind(this);
        this.element.addEventListener('click', this.handleClick);
    }
    
    onClick() {
        console.log('Clicked');
    }
    
    // 没有清理事件监听器!
}
 
// ✅ 正确做法
class ProperComponent {
    constructor(element) {
        this.element = element;
        this.handleClick = this.onClick.bind(this);
        this.element.addEventListener('click', this.handleClick);
    }
    
    onClick() {
        console.log('Clicked');
    }
    
    destroy() {
        this.element.removeEventListener('click', this.handleClick);
        this.element = null;
        this.handleClick = null;
    }
}
 
// 场景2:定时器未清理
// ❌ 内存泄漏
class LeakyTimer {
    constructor() {
        this.data = new Array(1000000).fill('data');
        this.intervalId = setInterval(() => {
            console.log('Timer running');
        }, 1000);
    }
}
 
// ✅ 正确做法
class ProperTimer {
    constructor() {
        this.data = new Array(1000000).fill('data');
        this.intervalId = setInterval(() => {
            console.log('Timer running');
        }, 1000);
    }
    
    destroy() {
        clearInterval(this.intervalId);
        this.data = null;
    }
}
 
// 场景3:闭包引用
// ❌ 内存泄漏
function createLeakyClosure() {
    const largeData = new Array(1000000).fill('data');
    
    return function() {
        // 即使不使用largeData,它也会被保留在内存中
        console.log('Closure function');
    };
}
 
// ✅ 正确做法
function createProperClosure() {
    const largeData = new Array(1000000).fill('data');
    
    // 只保留需要的数据
    const summary = largeData.length;
    
    return function() {
        console.log('Data length:', summary);
    };
}
 
// 场景4:DOM引用
// ❌ 内存泄漏
class LeakyDOMReference {
    constructor() {
        this.elements = [];
        const container = document.getElementById('container');
        
        for (let i = 0; i < 1000; i++) {
            const div = document.createElement('div');
            container.appendChild(div);
            this.elements.push(div); // 保留了DOM引用
        }
    }
    
    clear() {
        const container = document.getElementById('container');
        container.innerHTML = ''; // DOM被清除,但this.elements仍然引用
    }
}
 
// ✅ 正确做法
class ProperDOMReference {
    constructor() {
        this.elements = [];
        const container = document.getElementById('container');
        
        for (let i = 0; i < 1000; i++) {
            const div = document.createElement('div');
            container.appendChild(div);
            this.elements.push(div);
        }
    }
    
    clear() {
        const container = document.getElementById('container');
        container.innerHTML = '';
        this.elements = []; // 清除引用
    }
}
 
// ========== 内存泄漏检测工具 ==========
class MemoryLeakDetector {
    constructor() {
        this.snapshots = [];
    }
    
    // 拍摄内存快照
    takeSnapshot(label) {
        if (performance.memory) {
            this.snapshots.push({
                label,
                timestamp: Date.now(),
                usedJSHeapSize: performance.memory.usedJSHeapSize,
                totalJSHeapSize: performance.memory.totalJSHeapSize,
                jsHeapSizeLimit: performance.memory.jsHeapSizeLimit
            });
        }
    }
    
    // 分析内存增长
    analyze() {
        if (this.snapshots.length < 2) {
            console.log('需要至少2个快照');
            return;
        }
        
        console.log('📊 内存分析报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        
        for (let i = 1; i < this.snapshots.length; i++) {
            const prev = this.snapshots[i - 1];
            const curr = this.snapshots[i];
            
            const growth = curr.usedJSHeapSize - prev.usedJSHeapSize;
            const growthMB = (growth / 1024 / 1024).toFixed(2);
            
            console.log(`${prev.label} -> ${curr.label}:`);
            console.log(`  内存增长: ${growthMB} MB`);
            console.log(`  当前使用: ${(curr.usedJSHeapSize / 1024 / 1024).toFixed(2)} MB`);
        }
        
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
    
    // 清除快照
    clear() {
        this.snapshots = [];
    }
}
 
// 使用示例
const detector = new MemoryLeakDetector();
 
detector.takeSnapshot('初始状态');
 
// 执行一些操作
for (let i = 0; i < 10000; i++) {
    const div = document.createElement('div');
    document.body.appendChild(div);
}
 
detector.takeSnapshot('创建10000个div后');
 
// 清理
document.body.innerHTML = '';
 
detector.takeSnapshot('清理后');
 
detector.analyze();

6.2 对象池技术



// ========== 对象池实现 ==========
// 复用对象,减少GC压力
 
class ObjectPool {
    constructor(createFn, resetFn, initialSize = 10) {
        this.createFn = createFn;
        this.resetFn = resetFn;
        this.pool = [];
        
        // 预创建对象
        for (let i = 0; i < initialSize; i++) {
            this.pool.push(this.createFn());
        }
    }
    
    // 获取对象
    acquire() {
        if (this.pool.length > 0) {
            return this.pool.pop();
        }
        return this.createFn();
    }
    
    // 归还对象
    release(obj) {
        this.resetFn(obj);
        this.pool.push(obj);
    }
    
    // 获取池大小
    size() {
        return this.pool.length;
    }
}
 
// 使用示例:粒子系统
class Particle {
    constructor() {
        this.x = 0;
        this.y = 0;
        this.vx = 0;
        this.vy = 0;
        this.life = 0;
    }
    
    update() {
        this.x += this.vx;
        this.y += this.vy;
        this.life--;
    }
    
    isAlive() {
        return this.life > 0;
    }
}
 
// 创建粒子池
const particlePool = new ObjectPool(
    () => new Particle(),
    (particle) => {
        particle.x = 0;
        particle.y = 0;
        particle.vx = 0;
        particle.vy = 0;
        particle.life = 0;
    },
    100
);
 
// 粒子系统
class ParticleSystem {
    constructor() {
        this.particles = [];
    }
    
    emit(x, y) {
        const particle = particlePool.acquire();
        particle.x = x;
        particle.y = y;
        particle.vx = (Math.random() - 0.5) * 5;
        particle.vy = (Math.random() - 0.5) * 5;
        particle.life = 100;
        this.particles.push(particle);
    }
    
    update() {
        for (let i = this.particles.length - 1; i >= 0; i--) {
            const particle = this.particles[i];
            particle.update();
            
            if (!particle.isAlive()) {
                this.particles.splice(i, 1);
                particlePool.release(particle); // 归还到对象池
            }
        }
    }
}
 
// 性能对比
console.time('不使用对象池');
for (let i = 0; i < 10000; i++) {
    const p = new Particle();
    // 使用后直接丢弃,等待GC
}
console.timeEnd('不使用对象池');
// 输出: 不使用对象池: ~5ms
 
console.time('使用对象池');
for (let i = 0; i < 10000; i++) {
    const p = particlePool.acquire();
    particlePool.release(p);
}
console.timeEnd('使用对象池');
// 输出: 使用对象池: ~1ms

6.3 WeakMap和WeakSet



// ========== WeakMap使用场景 ==========
 
// 场景1:私有数据存储
const privateData = new WeakMap();
 
class User {
    constructor(name, password) {
        this.name = name;
        privateData.set(this, { password });
    }
    
    checkPassword(password) {
        return privateData.get(this).password === password;
    }
}
 
const user = new User('Alice', 'secret123');
console.log(user.name); // 'Alice'
console.log(user.password); // undefined(无法访问)
console.log(user.checkPassword('secret123')); // true
 
// 场景2:DOM元素关联数据
const elementData = new WeakMap();
 
function attachData(element, data) {
    elementData.set(element, data);
}
 
function getData(element) {
    return elementData.get(element);
}
 
const div = document.createElement('div');
attachData(div, { id: 1, name: 'Test' });
console.log(getData(div)); // { id: 1, name: 'Test' }
 
// 当div被移除时,关联的数据会自动被垃圾回收
 
// ========== WeakSet使用场景 ==========
 
// 场景:标记对象
const processedObjects = new WeakSet();
 
function processObject(obj) {
    if (processedObjects.has(obj)) {
        console.log('对象已处理过');
        return;
    }
    
    // 处理对象
    console.log('处理对象:', obj);
    processedObjects.add(obj);
}
 
const obj1 = { id: 1 };
const obj2 = { id: 2 };
 
processObject(obj1); // 处理对象: { id: 1 }
processObject(obj1); // 对象已处理过
processObject(obj2); // 处理对象: { id: 2 }
 
// ========== Map vs WeakMap 对比 ==========
 
// Map - 会阻止垃圾回收
const regularMap = new Map();
let obj = { data: 'large data' };
regularMap.set(obj, 'value');
obj = null; // obj仍然在Map中,不会被回收
 
// WeakMap - 不会阻止垃圾回收
const weakMap = new WeakMap();
let obj2 = { data: 'large data' };
weakMap.set(obj2, 'value');
obj2 = null; // obj2会被垃圾回收,WeakMap中的条目也会被清除

第六章:网络请求优化

7.1 请求合并与批处理



// ========== 请求批处理器 ==========
class RequestBatcher {
    constructor(batchFn, delay = 50) {
        this.batchFn = batchFn;
        this.delay = delay;
        this.queue = [];
        this.timeoutId = null;
    }
    
    add(request) {
        return new Promise((resolve, reject) => {
            this.queue.push({ request, resolve, reject });
            
            if (this.timeoutId) {
                clearTimeout(this.timeoutId);
            }
            
            this.timeoutId = setTimeout(() => {
                this.flush();
            }, this.delay);
        });
    }
    
    async flush() {
        if (this.queue.length === 0) return;
        
        const batch = this.queue.splice(0);
        const requests = batch.map(item => item.request);
        
        try {
            const results = await this.batchFn(requests);
            
            batch.forEach((item, index) => {
                item.resolve(results[index]);
            });
        } catch (error) {
            batch.forEach(item => {
                item.reject(error);
            });
        }
    }
}
 
// 使用示例:批量获取用户信息
const userBatcher = new RequestBatcher(async (userIds) => {
    console.log('批量请求用户信息:', userIds);
    const response = await fetch('/api/users/batch', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ids: userIds })
    });
    return response.json();
}, 50);
 
// 多个组件同时请求用户信息
async function loadUserProfile(userId) {
    const user = await userBatcher.add(userId);
    console.log('用户信息:', user);
}
 
// 这些请求会被合并成一个批量请求
loadUserProfile(1);
loadUserProfile(2);
loadUserProfile(3);
loadUserProfile(4);
loadUserProfile(5);
// 实际只发送一次请求:POST /api/users/batch { ids: [1,2,3,4,5] }

7.2 请求缓存



// ========== HTTP缓存管理器 ==========
class CacheManager {
    constructor() {
        this.cache = new Map();
        this.pendingRequests = new Map();
    }
    
    // 生成缓存键
    getCacheKey(url, options = {}) {
        return `${url}:${JSON.stringify(options)}`;
    }
    
    // 获取缓存
    get(url, options = {}) {
        const key = this.getCacheKey(url, options);
        const cached = this.cache.get(key);
        
        if (cached && Date.now() < cached.expiry) {
            console.log('从缓存返回:', url);
            return Promise.resolve(cached.data);
        }
        
        return null;
    }
    
    // 设置缓存
    set(url, data, ttl = 60000, options = {}) {
        const key = this.getCacheKey(url, options);
        this.cache.set(key, {
            data,
            expiry: Date.now() + ttl
        });
    }
    
    // 清除缓存
    clear(url, options = {}) {
        if (url) {
            const key = this.getCacheKey(url, options);
            this.cache.delete(key);
        } else {
            this.cache.clear();
        }
    }
    
    // 带缓存的fetch
    async fetch(url, options = {}, ttl = 60000) {
        // 检查缓存
        const cached = this.get(url, options);
        if (cached) {
            return cached;
        }
        
        // 检查是否有相同的请求正在进行
        const key = this.getCacheKey(url, options);
        if (this.pendingRequests.has(key)) {
            console.log('等待进行中的请求:', url);
            return this.pendingRequests.get(key);
        }
        
        // 发起新请求
        console.log('发起新请求:', url);
        const promise = fetch(url, options)
            .then(response => response.json())
            .then(data => {
                this.set(url, data, ttl, options);
                this.pendingRequests.delete(key);
                return data;
            })
            .catch(error => {
                this.pendingRequests.delete(key);
                throw error;
            });
        
        this.pendingRequests.set(key, promise);
        return promise;
    }
}
 
// 使用示例
const cacheManager = new CacheManager();
 
// 第一次请求 - 发起网络请求
cacheManager.fetch('/api/users/1', {}, 60000)
    .then(data => console.log('数据1:', data));
 
// 第二次请求(立即) - 等待第一次请求
cacheManager.fetch('/api/users/1', {}, 60000)
    .then(data => console.log('数据2:', data));
 
// 第三次请求(1秒后) - 从缓存返回
setTimeout(() => {
    cacheManager.fetch('/api/users/1', {}, 60000)
        .then(data => console.log('数据3:', data));
}, 1000);
 
// ========== Service Worker缓存 ==========
// sw.js
self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open('v1').then((cache) => {
            return cache.addAll([
                '/',
                '/styles/main.css',
                '/scripts/main.js',
                '/images/logo.png'
            ]);
        })
    );
});
 
self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((response) => {
            // 缓存命中,返回缓存
            if (response) {
                return response;
            }
            
            // 缓存未命中,发起网络请求
            return fetch(event.request).then((response) => {
                // 检查是否是有效响应
                if (!response || response.status !== 200 || response.type !== 'basic') {
                    return response;
                }
                
                // 克隆响应(因为响应流只能使用一次)
                const responseToCache = response.clone();
                
                caches.open('v1').then((cache) => {
                    cache.put(event.request, responseToCache);
                });
                
                return response;
            });
        })
    );
});

7.3 预加载与懒加载



// ========== 资源预加载 ==========
 
// 1. DNS预解析
function prefetchDNS(domains) {
    domains.forEach(domain => {
        const link = document.createElement('link');
        link.rel = 'dns-prefetch';
        link.href = `//${domain}`;
        document.head.appendChild(link);
    });
}
 
prefetchDNS(['api.example.com', 'cdn.example.com']);
 
// 2. 预连接
function preconnect(urls) {
    urls.forEach(url => {
        const link = document.createElement('link');
        link.rel = 'preconnect';
        link.href = url;
        document.head.appendChild(link);
    });
}
 
preconnect(['https://api.example.com', 'https://cdn.example.com']);
 
// 3. 预加载资源
function preloadResource(url, as) {
    const link = document.createElement('link');
    link.rel = 'preload';
    link.href = url;
    link.as = as;
    document.head.appendChild(link);
}
 
preloadResource('/fonts/main.woff2', 'font');
preloadResource('/styles/critical.css', 'style');
preloadResource('/scripts/main.js', 'script');
 
// 4. 预获取资源(低优先级)
function prefetchResource(url) {
    const link = document.createElement('link');
    link.rel = 'prefetch';
    link.href = url;
    document.head.appendChild(link);
}
 
prefetchResource('/next-page.html');
prefetchResource('/images/next-page-hero.jpg');
 
// ========== 图片懒加载 ==========
class LazyImageLoader {
    constructor(options = {}) {
        this.options = {
            root: null,
            rootMargin: '50px',
            threshold: 0.01,
            ...options
        };
        
        this.observer = new IntersectionObserver(
            this.handleIntersection.bind(this),
            this.options
        );
        
        this.loadImage = this.loadImage.bind(this);
    }
    
    observe(images) {
        images.forEach(img => {
            this.observer.observe(img);
        });
    }
    
    handleIntersection(entries) {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                this.loadImage(entry.target);
                this.observer.unobserve(entry.target);
            }
        });
    }
    
    loadImage(img) {
        const src = img.dataset.src;
        const srcset = img.dataset.srcset;
        
        if (!src) return;
        
        // 创建新图片对象预加载
        const tempImg = new Image();
        
        tempImg.onload = () => {
            img.src = src;
            if (srcset) {
                img.srcset = srcset;
            }
            img.classList.add('loaded');
        };
        
        tempImg.onerror = () => {
            console.error('图片加载失败:', src);
            img.classList.add('error');
        };
        
        tempImg.src = src;
    }
    
    disconnect() {
        this.observer.disconnect();
    }
}
 
// 使用示例
const lazyLoader = new LazyImageLoader({
    rootMargin: '100px' // 提前100px开始加载
});
 
const lazyImages = document.querySelectorAll('img[data-src]');
lazyLoader.observe(lazyImages);
 
// HTML示例:
// <img data-src="image.jpg" data-srcset="image-2x.jpg 2x" alt="Lazy loaded image">
 
// ========== 路由懒加载 ==========
class RouteLoader {
    constructor() {
        this.routes = new Map();
        this.cache = new Map();
    }
    
    // 注册路由
    register(path, loader) {
        this.routes.set(path, loader);
    }
    
    // 加载路由
    async load(path) {
        // 检查缓存
        if (this.cache.has(path)) {
            console.log('从缓存加载路由:', path);
            return this.cache.get(path);
        }
        
        // 获取加载器
        const loader = this.routes.get(path);
        if (!loader) {
            throw new Error(`路由未找到: ${path}`);
        }
        
        // 加载模块
        console.log('加载路由:', path);
        const module = await loader();
        
        // 缓存模块
        this.cache.set(path, module);
        
        return module;
    }
    
    // 预加载路由
    async prefetch(path) {
        if (!this.cache.has(path)) {
            await this.load(path);
        }
    }
}
 
// 使用示例
const routeLoader = new RouteLoader();
 
// 注册路由
routeLoader.register('/home', () => import('./pages/Home.js'));
routeLoader.register('/about', () => import('./pages/About.js'));
routeLoader.register('/contact', () => import('./pages/Contact.js'));
 
// 加载路由
async function navigateTo(path) {
    const module = await routeLoader.load(path);
    module.render();
}
 
// 预加载可能访问的路由
routeLoader.prefetch('/about');
 
// ========== 组件懒加载(React示例)==========
import React, { lazy, Suspense } from 'react';
 
// 懒加载组件
const HeavyComponent = lazy(() => import('./HeavyComponent'));
 
function App() {
    return (
        <div>
            <Suspense fallback={<div>Loading...</div>}>
                <HeavyComponent />
            </Suspense>
        </div>
    );
}

第七章:渲染性能优化

8.1 重排与重绘优化



// ========== 避免强制同步布局 ==========
 
// ❌ 强制同步布局(Layout Thrashing)
function inefficientLayout() {
    const boxes = document.querySelectorAll('.box');
    
    boxes.forEach(box => {
        // 读取布局属性
        const width = box.offsetWidth;
        // 立即修改样式
        box.style.width = width + 10 + 'px';
        // 浏览器被迫重新计算布局
    });
}
 
// ✅ 批量读取,批量写入
function efficientLayout() {
    const boxes = document.querySelectorAll('.box');
    
    // 第一步:批量读取
    const widths = Array.from(boxes).map(box => box.offsetWidth);
    
    // 第二步:批量写入
    boxes.forEach((box, index) => {
        box.style.width = widths[index] + 10 + 'px';
    });
}
 
// ========== 使用requestAnimationFrame ==========
class LayoutOptimizer {
    constructor() {
        this.readQueue = [];
        this.writeQueue = [];
        this.scheduled = false;
    }
    
    // 添加读操作
    read(fn) {
        this.readQueue.push(fn);
        this.schedule();
    }
    
    // 添加写操作
    write(fn) {
        this.writeQueue.push(fn);
        this.schedule();
    }
    
    // 调度执行
    schedule() {
        if (this.scheduled) return;
        
        this.scheduled = true;
        requestAnimationFrame(() => {
            this.flush();
        });
    }
    
    // 执行队列
    flush() {
        // 先执行所有读操作
        this.readQueue.forEach(fn => fn());
        this.readQueue = [];
        
        // 再执行所有写操作
        this.writeQueue.forEach(fn => fn());
        this.writeQueue = [];
        
        this.scheduled = false;
    }
}
 
// 使用示例
const optimizer = new LayoutOptimizer();
 
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
    let width;
    
    // 添加读操作
    optimizer.read(() => {
        width = box.offsetWidth;
    });
    
    // 添加写操作
    optimizer.write(() => {
        box.style.width = width + 10 + 'px';
    });
});
 
// ========== CSS优化 ==========
 
// 1. 使用transform代替top/left
// ❌ 触发重排
element.style.left = '100px';
element.style.top = '100px';
 
// ✅ 只触发合成
element.style.transform = 'translate(100px, 100px)';
 
// 2. 使用opacity代替visibility
// ❌ 触发重绘
element.style.visibility = 'hidden';
 
// ✅ 只触发合成
element.style.opacity = '0';
 
// 3. 使用will-change提示浏览器
element.style.willChange = 'transform, opacity';
 
// 4. 避免复杂的CSS选择器
// ❌ 复杂选择器
// .container .list .item:nth-child(odd) > .content > .title
 
// ✅ 简单选择器
// .item-title
 
// ========== 批量DOM操作 ==========
class DOMBatcher {
    constructor() {
        this.mutations = [];
        this.scheduled = false;
    }
    
    // 添加变更
    add(fn) {
        this.mutations.push(fn);
        this.schedule();
    }
    
    // 调度执行
    schedule() {
        if (this.scheduled) return;
        
        this.scheduled = true;
        requestAnimationFrame(() => {
            this.flush();
        });
    }
    
    // 执行变更
    flush() {
        // 使用DocumentFragment批量操作
        const fragment = document.createDocumentFragment();
        
        this.mutations.forEach(fn => fn(fragment));
        this.mutations = [];
        
        // 一次性应用所有变更
        document.body.appendChild(fragment);
        
        this.scheduled = false;
    }
}
 
// 使用示例
const batcher = new DOMBatcher();
 
for (let i = 0; i < 1000; i++) {
    batcher.add((fragment) => {
        const div = document.createElement('div');
        div.textContent = `Item ${i}`;
        fragment.appendChild(div);
    });
}

8.2 CSS动画优化



// ========== GPU加速动画 ==========
 
// ❌ CPU动画(慢)
function cpuAnimation(element) {
    let position = 0;
    
    function animate() {
        position += 1;
        element.style.left = position + 'px'; // 触发重排
        
        if (position < 500) {
            requestAnimationFrame(animate);
        }
    }
    
    animate();
}
 
// ✅ GPU动画(快)
function gpuAnimation(element) {
    let position = 0;
    
    // 启用GPU加速
    element.style.transform = 'translateZ(0)';
    
    function animate() {
        position += 1;
        element.style.transform = `translate3d(${position}px, 0, 0)`; // 只触发合成
        
        if (position < 500) {
            requestAnimationFrame(animate);
        }
    }
    
    animate();
}
 
// ========== Web Animations API ==========
class AnimationController {
    constructor(element) {
        this.element = element;
        this.animations = [];
    }
    
    // 创建动画
    animate(keyframes, options) {
        const animation = this.element.animate(keyframes, options);
        this.animations.push(animation);
        return animation;
    }
    
    // 淡入动画
    fadeIn(duration = 300) {
        return this.animate(
            [
                { opacity: 0 },
                { opacity: 1 }
            ],
            {
                duration,
                easing: 'ease-in-out',
                fill: 'forwards'
            }
        );
    }
    
    // 滑入动画
    slideIn(direction = 'left', duration = 300) {
        const transforms = {
            left: ['translateX(-100%)', 'translateX(0)'],
            right: ['translateX(100%)', 'translateX(0)'],
            top: ['translateY(-100%)', 'translateY(0)'],
            bottom: ['translateY(100%)', 'translateY(0)']
        };
        
        return this.animate(
            [
                { transform: transforms[direction][0], opacity: 0 },
                { transform: transforms[direction][1], opacity: 1 }
            ],
            {
                duration,
                easing: 'ease-out',
                fill: 'forwards'
            }
        );
    }
    
    // 缩放动画
    scale(from = 0, to = 1, duration = 300) {
        return this.animate(
            [
                { transform: `scale(${from})`, opacity: 0 },
                { transform: `scale(${to})`, opacity: 1 }
            ],
            {
                duration,
                easing: 'ease-out',
                fill: 'forwards'
            }
        );
    }
    
    // 暂停所有动画
    pauseAll() {
        this.animations.forEach(anim => anim.pause());
    }
    
    // 播放所有动画
    playAll() {
        this.animations.forEach(anim => anim.play());
    }
    
    // 取消所有动画
    cancelAll() {
        this.animations.forEach(anim => anim.cancel());
        this.animations = [];
    }
}
 
// 使用示例
const element = document.getElementById('animated-element');
const controller = new AnimationController(element);
 
// 淡入
controller.fadeIn(500);
 
// 滑入
controller.slideIn('left', 500);
 
// 缩放
controller.scale(0.5, 1, 500);
 
// ========== CSS动画性能监控 ==========
class AnimationPerformanceMonitor {
    constructor() {
        this.metrics = [];
    }
    
    // 监控动画性能
    monitor(animationName, callback) {
        const startTime = performance.now();
        let frameCount = 0;
        let lastTime = startTime;
        
        const element = document.querySelector(`[data-animation="${animationName}"]`);
        
        const observer = new PerformanceObserver((list) => {
            list.getEntries().forEach((entry) => {
                if (entry.name === animationName) {
                    frameCount++;
                    const currentTime = performance.now();
                    const fps = 1000 / (currentTime - lastTime);
                    lastTime = currentTime;
                    
                    this.metrics.push({
                        time: currentTime - startTime,
                        fps: fps
                    });
                }
            });
        });
        
        observer.observe({ entryTypes: ['measure'] });
        
        element.addEventListener('animationend', () => {
            observer.disconnect();
            const duration = performance.now() - startTime;
            const avgFPS = (frameCount / duration) * 1000;
            
            callback({
                duration,
                frameCount,
                avgFPS,
                metrics: this.metrics
            });
        });
    }
    
    // 生成报告
    generateReport() {
        const avgFPS = this.metrics.reduce((sum, m) => sum + m.fps, 0) / this.metrics.length;
        const minFPS = Math.min(...this.metrics.map(m => m.fps));
        const maxFPS = Math.max(...this.metrics.map(m => m.fps));
        
        return {
            avgFPS: avgFPS.toFixed(2),
            minFPS: minFPS.toFixed(2),
            maxFPS: maxFPS.toFixed(2),
            frameDrops: this.metrics.filter(m => m.fps < 30).length
        };
    }
}
 
// 使用示例
const monitor = new AnimationPerformanceMonitor();
 
monitor.monitor('slide-in', (result) => {
    console.log('动画性能报告:');
    console.log(`持续时间: ${result.duration.toFixed(2)}ms`);
    console.log(`帧数: ${result.frameCount}`);
    console.log(`平均FPS: ${result.avgFPS.toFixed(2)}`);
    
    const report = monitor.generateReport();
    console.log('详细报告:', report);
});

8.3 Canvas优化



// ========== Canvas性能优化技巧 ==========
 
// 1. 离屏Canvas
class OffscreenCanvasRenderer {
    constructor(width, height) {
        // 主Canvas
        this.canvas = document.getElementById('main-canvas');
        this.ctx = this.canvas.getContext('2d');
        
        // 离屏Canvas
        this.offscreenCanvas = document.createElement('canvas');
        this.offscreenCanvas.width = width;
        this.offscreenCanvas.height = height;
        this.offscreenCtx = this.offscreenCanvas.getContext('2d');
    }
    
    // 在离屏Canvas上绘制
    drawOffscreen() {
        this.offscreenCtx.clearRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
        
        // 复杂的绘制操作
        for (let i = 0; i < 1000; i++) {
            this.offscreenCtx.fillStyle = `hsl(${i % 360}, 50%, 50%)`;
            this.offscreenCtx.fillRect(
                Math.random() * this.offscreenCanvas.width,
                Math.random() * this.offscreenCanvas.height,
                10, 10
            );
        }
    }
    
    // 将离屏Canvas绘制到主Canvas
    render() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.drawImage(this.offscreenCanvas, 0, 0);
    }
}
 
// 2. 分层Canvas
class LayeredCanvasRenderer {
    constructor() {
        this.layers = {
            background: this.createLayer('background'),
            objects: this.createLayer('objects'),
            ui: this.createLayer('ui')
        };
    }
    
    createLayer(name) {
        const canvas = document.createElement('canvas');
        canvas.width = 800;
        canvas.height = 600;
        canvas.style.position = 'absolute';
        canvas.style.left = '0';
        canvas.style.top = '0';
        canvas.id = `layer-${name}`;
        document.getElementById('canvas-container').appendChild(canvas);
        
        return {
            canvas,
            ctx: canvas.getContext('2d'),
            dirty: true
        };
    }
    
    // 只重绘变化的层
    render() {
        Object.values(this.layers).forEach(layer => {
            if (layer.dirty) {
                layer.ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
                // 绘制该层内容
                layer.dirty = false;
            }
        });
    }
    
    // 标记层为脏
    markDirty(layerName) {
        if (this.layers[layerName]) {
            this.layers[layerName].dirty = true;
        }
    }
}
 
// 3. 批量绘制
class BatchRenderer {
    constructor(ctx) {
        this.ctx = ctx;
        this.drawCalls = [];
    }
    
    // 添加绘制调用
    add(type, ...args) {
        this.drawCalls.push({ type, args });
    }
    
    // 批量执行
    flush() {
        this.ctx.save();
        
        // 按类型分组
        const groups = this.groupByType();
        
        // 批量绘制相同类型
        Object.entries(groups).forEach(([type, calls]) => {
            this.ctx.beginPath();
            
            calls.forEach(call => {
                switch (type) {
                    case 'rect':
                        this.ctx.rect(...call.args);
                        break;
                    case 'circle':
                        const [x, y, r] = call.args;
                        this.ctx.arc(x, y, r, 0, Math.PI * 2);
                        break;
                }
            });
            
            this.ctx.fill();
        });
        
        this.ctx.restore();
        this.drawCalls = [];
    }
    
    groupByType() {
        return this.drawCalls.reduce((groups, call) => {
            if (!groups[call.type]) {
                groups[call.type] = [];
            }
            groups[call.type].push(call);
            return groups;
        }, {});
    }
}
 
// 使用示例
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const batchRenderer = new BatchRenderer(ctx);
 
// 添加大量绘制调用
for (let i = 0; i < 1000; i++) {
    batchRenderer.add('rect', i * 10, 0, 8, 8);
}
 
// 批量绘制
batchRenderer.flush();
 
// 4. 使用WebGL(通过Three.js)
class WebGLRenderer {
    constructor(container) {
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
        
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        container.appendChild(this.renderer.domElement);
        
        this.objects = [];
    }
    
    addObject(geometry, material) {
        const mesh = new THREE.Mesh(geometry, material);
        this.scene.add(mesh);
        this.objects.push(mesh);
        return mesh;
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        
        // 更新对象
        this.objects.forEach(obj => {
            obj.rotation.x += 0.01;
            obj.rotation.y += 0.01;
        });
        
        this.renderer.render(this.scene, this.camera);
    }
}


第八章:打包与加载优化

8.1 代码分割



// ========== Webpack代码分割配置 ==========
 
// webpack.config.js
module.exports = {
    entry: {
        main: './src/index.js',
        vendor: './src/vendor.js'
    },
    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'dist'),
        chunkFilename: '[name].[contenthash].chunk.js'
    },
    optimization: {
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                // 第三方库单独打包
                vendor: {
                    test: /[\/]node_modules[\/]/,
                    name: 'vendors',
                    priority: 10
                },
                // 公共代码单独打包
                common: {
                    minChunks: 2,
                    priority: 5,
                    reuseExistingChunk: true
                },
                // React相关单独打包
                react: {
                    test: /[\/]node_modules[\/](react|react-dom)[\/]/,
                    name: 'react',
                    priority: 20
                }
            }
        },
        // 运行时代码单独提取
        runtimeChunk: {
            name: 'runtime'
        }
    }
};
 
// ========== 动态导入(Dynamic Import)==========
 
// 1. 路由级别的代码分割
class Router {
    constructor() {
        this.routes = new Map();
        this.currentRoute = null;
    }
    
    // 注册路由(使用动态导入)
    register(path, loader) {
        this.routes.set(path, loader);
    }
    
    // 导航到路由
    async navigate(path) {
        const loader = this.routes.get(path);
        
        if (!loader) {
            console.error('路由不存在:', path);
            return;
        }
        
        // 显示加载状态
        this.showLoading();
        
        try {
            // 动态导入模块
            const module = await loader();
            
            // 卸载当前路由
            if (this.currentRoute && this.currentRoute.unmount) {
                this.currentRoute.unmount();
            }
            
            // 挂载新路由
            this.currentRoute = module.default;
            this.currentRoute.mount();
            
            // 更新URL
            window.history.pushState({ path }, '', path);
        } catch (error) {
            console.error('路由加载失败:', error);
            this.showError();
        } finally {
            this.hideLoading();
        }
    }
    
    showLoading() {
        document.getElementById('loading').style.display = 'block';
    }
    
    hideLoading() {
        document.getElementById('loading').style.display = 'none';
    }
    
    showError() {
        document.getElementById('error').style.display = 'block';
    }
}
 
// 使用示例
const router = new Router();
 
// 注册路由(每个路由都是独立的chunk)
router.register('/', () => import('./pages/Home'));
router.register('/about', () => import('./pages/About'));
router.register('/products', () => import('./pages/Products'));
router.register('/contact', () => import('./pages/Contact'));
 
// 导航
document.getElementById('nav-home').addEventListener('click', () => {
    router.navigate('/');
});
 
document.getElementById('nav-about').addEventListener('click', () => {
    router.navigate('/about');
});
 
// 2. 组件级别的代码分割
class ComponentLoader {
    constructor() {
        this.cache = new Map();
    }
    
    // 懒加载组件
    async load(componentName, container) {
        // 检查缓存
        if (this.cache.has(componentName)) {
            const Component = this.cache.get(componentName);
            return new Component(container);
        }
        
        // 动态导入组件
        const module = await import(`./components/${componentName}.js`);
        const Component = module.default;
        
        // 缓存组件
        this.cache.set(componentName, Component);
        
        // 实例化并返回
        return new Component(container);
    }
    
    // 预加载组件
    async preload(componentNames) {
        const promises = componentNames.map(name => 
            import(`./components/${name}.js`).then(module => {
                this.cache.set(name, module.default);
            })
        );
        
        await Promise.all(promises);
    }
}
 
// 使用示例
const loader = new ComponentLoader();
 
// 懒加载组件
document.getElementById('load-chart').addEventListener('click', async () => {
    const container = document.getElementById('chart-container');
    const chart = await loader.load('Chart', container);
    chart.render();
});
 
// 预加载可能需要的组件
loader.preload(['Chart', 'Table', 'Modal']);
 
// 3. 条件加载
class ConditionalLoader {
    // 根据条件动态加载
    static async loadIfNeeded(condition, loader) {
        if (condition) {
            return await loader();
        }
        return null;
    }
    
    // 根据用户权限加载
    static async loadByPermission(permission, loader) {
        const hasPermission = await this.checkPermission(permission);
        if (hasPermission) {
            return await loader();
        }
        return null;
    }
    
    // 根据设备类型加载
    static async loadByDevice(loader) {
        const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
        
        if (isMobile) {
            return await import('./mobile-version.js');
        } else {
            return await import('./desktop-version.js');
        }
    }
    
    // 根据功能支持加载
    static async loadByFeatureSupport(feature, loader) {
        const isSupported = this.checkFeatureSupport(feature);
        
        if (isSupported) {
            return await loader();
        } else {
            // 加载polyfill
            return await import('./polyfills.js');
        }
    }
    
    static async checkPermission(permission) {
        // 模拟权限检查
        return fetch('/api/check-permission', {
            method: 'POST',
            body: JSON.stringify({ permission })
        }).then(res => res.json());
    }
    
    static checkFeatureSupport(feature) {
        const features = {
            'webgl': () => {
                const canvas = document.createElement('canvas');
                return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
            },
            'webworker': () => typeof Worker !== 'undefined',
            'serviceworker': () => 'serviceWorker' in navigator,
            'intersectionobserver': () => 'IntersectionObserver' in window
        };
        
        return features[feature] ? features[feature]() : false;
    }
}
 
// 使用示例
 
// 仅在需要时加载3D渲染器
const load3DRenderer = async () => {
    const renderer = await ConditionalLoader.loadIfNeeded(
        document.getElementById('enable-3d').checked,
        () => import('./renderers/3D.js')
    );
    
    if (renderer) {
        renderer.default.init();
    }
};
 
// 根据权限加载管理面板
const loadAdminPanel = async () => {
    const panel = await ConditionalLoader.loadByPermission(
        'admin',
        () => import('./components/AdminPanel.js')
    );
    
    if (panel) {
        panel.default.render();
    }
};
 
// 根据设备加载不同版本
const loadAppropriateVersion = async () => {
    const module = await ConditionalLoader.loadByDevice();
    module.default.init();
};
 
// 根据功能支持加载
const loadWithPolyfill = async () => {
    const module = await ConditionalLoader.loadByFeatureSupport(
        'intersectionobserver',
        () => import('./features/LazyLoad.js')
    );
    module.default.init();
};

8.2 Tree Shaking



// ========== Tree Shaking优化 ==========
 
// ❌ 不利于Tree Shaking的写法
 
// utils.js
export default {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
    multiply: (a, b) => a * b,
    divide: (a, b) => a / b
};
 
// main.js
import utils from './utils';
console.log(utils.add(1, 2)); // 整个对象都会被打包
 
// ✅ 利于Tree Shaking的写法
 
// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
export const divide = (a, b) => a / b;
 
// main.js
import { add } from './utils'; // 只打包add函数
console.log(add(1, 2));
 
// ========== 副作用标记 ==========
 
// package.json
{
    "name": "my-library",
    "version": "1.0.0",
    "sideEffects": false  // 标记为无副作用,可以安全地Tree Shaking
}
 
// 或者指定有副作用的文件
{
    "sideEffects": [
        "*.css",
        "*.scss",
        "./src/polyfills.js"
    ]
}
 
// ========== 优化第三方库导入 ==========
 
// ❌ 导入整个库
import _ from 'lodash';
const result = _.debounce(fn, 300);
 
// ✅ 只导入需要的函数
import debounce from 'lodash/debounce';
const result = debounce(fn, 300);
 
// 或使用lodash-es(ES模块版本)
import { debounce } from 'lodash-es';
const result = debounce(fn, 300);
 
// ========== Webpack配置优化 ==========
 
// webpack.config.js
module.exports = {
    mode: 'production', // 生产模式自动启用Tree Shaking
    optimization: {
        usedExports: true, // 标记未使用的导出
        minimize: true,    // 压缩代码
        sideEffects: true  // 识别副作用
    },
    module: {
        rules: [
            {
                test: /.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            ['@babel/preset-env', {
                                modules: false // 保留ES模块,不转换为CommonJS
                            }]
                        ]
                    }
                }
            }
        ]
    }
};
 
// ========== 分析打包结果 ==========
 
// 使用webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
    plugins: [
        new BundleAnalyzerPlugin({
            analyzerMode: 'static',
            reportFilename: 'bundle-report.html',
            openAnalyzer: false
        })
    ]
};
 
// 运行后会生成可视化报告,显示每个模块的大小

8.3 资源压缩



// ========== Webpack压缩配置 ==========
 
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
 
module.exports = {
    optimization: {
        minimize: true,
        minimizer: [
            // JavaScript压缩
            new TerserPlugin({
                terserOptions: {
                    compress: {
                        drop_console: true,  // 删除console
                        drop_debugger: true, // 删除debugger
                        pure_funcs: ['console.log'] // 删除特定函数调用
                    },
                    format: {
                        comments: false // 删除注释
                    }
                },
                extractComments: false,
                parallel: true // 多线程压缩
            }),
            
            // CSS压缩
            new CssMinimizerPlugin({
                minimizerOptions: {
                    preset: [
                        'default',
                        {
                            discardComments: { removeAll: true },
                            normalizeWhitespace: true
                        }
                    ]
                }
            })
        ]
    },
    
    plugins: [
        // 图片压缩
        new ImageMinimizerPlugin({
            minimizer: {
                implementation: ImageMinimizerPlugin.imageminMinify,
                options: {
                    plugins: [
                        ['gifsicle', { interlaced: true }],
                        ['jpegtran', { progressive: true }],
                        ['optipng', { optimizationLevel: 5 }],
                        ['svgo', {
                            plugins: [
                                {
                                    name: 'removeViewBox',
                                    active: false
                                }
                            ]
                        }]
                    ]
                }
            }
        }),
        
        // Gzip压缩
        new CompressionPlugin({
            algorithm: 'gzip',
            test: /.(js|css|html|svg)$/,
            threshold: 10240, // 只压缩大于10KB的文件
            minRatio: 0.8
        }),
        
        // Brotli压缩(更高压缩率)
        new CompressionPlugin({
            filename: '[path][base].br',
            algorithm: 'brotliCompress',
            test: /.(js|css|html|svg)$/,
            compressionOptions: {
                level: 11
            },
            threshold: 10240,
            minRatio: 0.8
        })
    ]
};
 
// ========== 运行时压缩 ==========
 
// 服务端配置示例(Express)
const express = require('express');
const compression = require('compression');
 
const app = express();
 
// 启用压缩中间件
app.use(compression({
    level: 6, // 压缩级别(0-9)
    threshold: 1024, // 只压缩大于1KB的响应
    filter: (req, res) => {
        // 自定义过滤器
        if (req.headers['x-no-compression']) {
            return false;
        }
        return compression.filter(req, res);
    }
}));
 
// ========== 图片优化 ==========
 
class ImageOptimizer {
    // 响应式图片
    static generateResponsiveImages(src, sizes) {
        const srcset = sizes.map(size => 
            `${src.replace(/.(jpg|png)$/, `-${size}w.$1`)} ${size}w`
        ).join(', ');
        
        return {
            src,
            srcset,
            sizes: '(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw'
        };
    }
    
    // WebP支持检测
    static async supportsWebP() {
        if (!self.createImageBitmap) return false;
        
        const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
        const blob = await fetch(webpData).then(r => r.blob());
        
        return createImageBitmap(blob).then(() => true, () => false);
    }
    
    // 动态选择图片格式
    static async getOptimalImageSrc(baseSrc) {
        const supportsWebP = await this.supportsWebP();
        
        if (supportsWebP) {
            return baseSrc.replace(/.(jpg|png)$/, '.webp');
        }
        
        return baseSrc;
    }
}
 
// 使用示例
const imageData = ImageOptimizer.generateResponsiveImages(
    '/images/hero.jpg',
    [320, 640, 960, 1280, 1920]
);
 
const img = document.createElement('img');
img.src = imageData.src;
img.srcset = imageData.srcset;
img.sizes = imageData.sizes;
 
// ========== 字体优化 ==========
 
// CSS字体优化
/*
@font-face {
    font-family: 'MyFont';
    src: url('/fonts/myfont.woff2') format('woff2'),
         url('/fonts/myfont.woff') format('woff');
    font-display: swap; // 使用系统字体直到自定义字体加载完成
    unicode-range: U+0000-00FF; // 只加载需要的字符范围
}
*/
 
class FontLoader {
    // 预加载字体
    static preload(fontUrl) {
        const link = document.createElement('link');
        link.rel = 'preload';
        link.as = 'font';
        link.type = 'font/woff2';
        link.href = fontUrl;
        link.crossOrigin = 'anonymous';
        document.head.appendChild(link);
    }
    
    // 使用Font Loading API
    static async load(fontFamily, fontUrl) {
        const font = new FontFace(fontFamily, `url(${fontUrl})`);
        
        try {
            await font.load();
            document.fonts.add(font);
            console.log(`字体 ${fontFamily} 加载成功`);
        } catch (error) {
            console.error(`字体 ${fontFamily} 加载失败:`, error);
        }
    }
    
    // 字体子集化(只包含需要的字符)
    static generateSubset(text) {
        // 获取唯一字符
        const chars = [...new Set(text)].sort().join('');
        
        // 生成unicode范围
        const ranges = [];
        let start = chars.charCodeAt(0);
        let end = start;
        
        for (let i = 1; i < chars.length; i++) {
            const code = chars.charCodeAt(i);
            if (code === end + 1) {
                end = code;
            } else {
                ranges.push(start === end ? 
                    `U+${start.toString(16).toUpperCase()}` :
                    `U+${start.toString(16).toUpperCase()}-${end.toString(16).toUpperCase()}`
                );
                start = end = code;
            }
        }
        
        ranges.push(start === end ? 
            `U+${start.toString(16).toUpperCase()}` :
            `U+${start.toString(16).toUpperCase()}-${end.toString(16).toUpperCase()}`
        );
        
        return ranges.join(', ');
    }
}
 
// 使用示例
FontLoader.preload('/fonts/myfont.woff2');
FontLoader.load('MyFont', '/fonts/myfont.woff2');
 
// 生成字体子集
const pageText = document.body.textContent;
const unicodeRange = FontLoader.generateSubset(pageText);
console.log('Unicode范围:', unicodeRange);

8.4 CDN优化



// ========== CDN配置与优化 ==========
 
class CDNManager {
    constructor(config) {
        this.config = {
            primary: config.primary,
            fallbacks: config.fallbacks || [],
            timeout: config.timeout || 3000
        };
    }
    
    // 加载资源(带降级)
    async loadResource(path, type = 'script') {
        const urls = [this.config.primary + path, ...this.config.fallbacks.map(cdn => cdn + path)];
        
        for (let i = 0; i < urls.length; i++) {
            try {
                await this.load(urls[i], type);
                console.log(`从CDN加载成功: ${urls[i]}`);
                return;
            } catch (error) {
                console.warn(`CDN加载失败: ${urls[i]}`, error);
                if (i === urls.length - 1) {
                    throw new Error('所有CDN都加载失败');
                }
            }
        }
    }
    
    // 加载单个资源
    load(url, type) {
        return new Promise((resolve, reject) => {
            const element = type === 'script' ? 
                document.createElement('script') :
                document.createElement('link');
            
            const timeout = setTimeout(() => {
                reject(new Error('加载超时'));
            }, this.config.timeout);
            
            element.onload = () => {
                clearTimeout(timeout);
                resolve();
            };
            
            element.onerror = () => {
                clearTimeout(timeout);
                reject(new Error('加载失败'));
            };
            
            if (type === 'script') {
                element.src = url;
                element.async = true;
            } else {
                element.rel = 'stylesheet';
                element.href = url;
            }
            
            document.head.appendChild(element);
        });
    }
    
    // 预连接到CDN
    preconnect() {
        const domains = [this.config.primary, ...this.config.fallbacks];
        
        domains.forEach(domain => {
            const link = document.createElement('link');
            link.rel = 'preconnect';
            link.href = domain;
            document.head.appendChild(link);
        });
    }
    
    // DNS预解析
    dnsPrefetch() {
        const domains = [this.config.primary, ...this.config.fallbacks];
        
        domains.forEach(domain => {
            const link = document.createElement('link');
            link.rel = 'dns-prefetch';
            link.href = domain;
            document.head.appendChild(link);
        });
    }
}
 
// 使用示例
const cdnManager = new CDNManager({
    primary: 'https://cdn1.example.com',
    fallbacks: [
        'https://cdn2.example.com',
        'https://cdn3.example.com'
    ],
    timeout: 5000
});
 
// 预连接
cdnManager.preconnect();
 
// 加载资源
cdnManager.loadResource('/js/vendor.js', 'script')
    .then(() => console.log('资源加载成功'))
    .catch(error => console.error('资源加载失败', error));
 
// ========== 智能CDN选择 ==========
 
class SmartCDNSelector {
    constructor(cdns) {
        this.cdns = cdns;
        this.performanceData = new Map();
    }
    
    // 测试CDN速度
    async testCDN(cdn) {
        const testUrl = `${cdn}/test.png?t=${Date.now()}`;
        const startTime = performance.now();
        
        try {
            await fetch(testUrl, { method: 'HEAD' });
            const endTime = performance.now();
            const latency = endTime - startTime;
            
            this.performanceData.set(cdn, {
                latency,
                timestamp: Date.now(),
                available: true
            });
            
            return latency;
        } catch (error) {
            this.performanceData.set(cdn, {
                latency: Infinity,
                timestamp: Date.now(),
                available: false
            });
            
            return Infinity;
        }
    }
    
    // 选择最快的CDN
    async selectFastest() {
        const tests = this.cdns.map(cdn => this.testCDN(cdn));
        await Promise.all(tests);
        
        let fastest = null;
        let minLatency = Infinity;
        
        this.performanceData.forEach((data, cdn) => {
            if (data.available && data.latency < minLatency) {
                minLatency = data.latency;
                fastest = cdn;
            }
        });
        
        return fastest;
    }
    
    // 获取性能报告
    getPerformanceReport() {
        const report = [];
        
        this.performanceData.forEach((data, cdn) => {
            report.push({
                cdn,
                latency: data.latency,
                available: data.available,
                status: data.available ? 
                    `${data.latency.toFixed(2)}ms` : 
                    '不可用'
            });
        });
        
        return report.sort((a, b) => a.latency - b.latency);
    }
}
 
// 使用示例
const cdnSelector = new SmartCDNSelector([
    'https://cdn1.example.com',
    'https://cdn2.example.com',
    'https://cdn3.example.com'
]);
 
// 选择最快的CDN
cdnSelector.selectFastest().then(fastest => {
    console.log('最快的CDN:', fastest);
    console.log('性能报告:', cdnSelector.getPerformanceReport());
});

第九章:现代框架性能优化

9.1 React性能优化



// ========== React性能优化技巧 ==========
 
import React, { 
    memo, 
    useMemo, 
    useCallback, 
    lazy, 
    Suspense,
    useState,
    useEffect,
    useRef
} from 'react';
 
// 1. 使用React.memo避免不必要的重渲染
// ❌ 未优化的组件
function ExpensiveComponent({ data, onClick }) {
    console.log('ExpensiveComponent渲染');
    
    return (
        <div onClick={onClick}>
            {data.map(item => (
                <div key={item.id}>{item.name}</div>
            ))}
        </div>
    );
}
 
// ✅ 使用memo优化
const OptimizedComponent = memo(function ExpensiveComponent({ data, onClick }) {
    console.log('OptimizedComponent渲染');
    
    return (
        <div onClick={onClick}>
            {data.map(item => (
                <div key={item.id}>{item.name}</div>
            ))}
        </div>
    );
}, (prevProps, nextProps) => {
    // 自定义比较函数
    return prevProps.data === nextProps.data && 
           prevProps.onClick === nextProps.onClick;
});
 
// 2. 使用useMemo缓存计算结果
function DataProcessor({ items }) {
    // ❌ 每次渲染都重新计算
    const processedData = items.map(item => ({
        ...item,
        processed: expensiveOperation(item)
    }));
    
    // ✅ 使用useMemo缓存
    const optimizedData = useMemo(() => {
        return items.map(item => ({
            ...item,
            processed: expensiveOperation(item)
        }));
    }, [items]); // 只在items改变时重新计算
    
    return <div>{/* 使用optimizedData */}</div>;
}
 
// 3. 使用useCallback缓存回调函数
function ParentComponent() {
    const [count, setCount] = useState(0);
    const [text, setText] = useState('');
    
    // ❌ 每次渲染都创建新函数
    const handleClick = () => {
        setCount(c => c + 1);
    };
    
    // ✅ 使用useCallback缓存
    const optimizedHandleClick = useCallback(() => {
        setCount(c => c + 1);
    }, []); // 依赖为空,函数永远不变
    
    return (
        <div>
            <input value={text} onChange={e => setText(e.target.value)} />
            <OptimizedComponent 
                data={[]} 
                onClick={optimizedHandleClick} 
            />
        </div>
    );
}
 
// 4. 列表渲染优化
function ListComponent({ items }) {
    return (
        <div>
            {items.map(item => (
                // ✅ 使用稳定的key
                <ListItem key={item.id} item={item} />
            ))}
        </div>
    );
}
 
const ListItem = memo(function ListItem({ item }) {
    return <div>{item.name}</div>;
});
 
// 5. 虚拟滚动(使用react-window)
import { FixedSizeList } from 'react-window';
 
function VirtualList({ items }) {
    const Row = ({ index, style }) => (
        <div style={style}>
            {items[index].name}
        </div>
    );
    
    return (
        <FixedSizeList
            height={600}
            itemCount={items.length}
            itemSize={50}
            width="100%"
        >
            {Row}
        </FixedSizeList>
    );
}
 
// 6. 代码分割与懒加载
const HeavyComponent = lazy(() => import('./HeavyComponent'));
 
function App() {
    return (
        <Suspense fallback={<div>Loading...</div>}>
            <HeavyComponent />
        </Suspense>
    );
}
 
// 7. 避免内联对象和数组
function BadComponent() {
    return (
        // ❌ 每次渲染都创建新对象
        <ChildComponent style={{ color: 'red' }} data={[1, 2, 3]} />
    );
}
 
function GoodComponent() {
    // ✅ 在组件外部定义
    const style = useMemo(() => ({ color: 'red' }), []);
    const data = useMemo(() => [1, 2, 3], []);
    
    return <ChildComponent style={style} data={data} />;
}
 
// 8. 使用Profiler分析性能
import { Profiler } from 'react';
 
function onRenderCallback(
    id, // 发生提交的 Profiler 树的 "id"
    phase, // "mount" (首次挂载)或 "update" (重渲染)
    actualDuration, // 本次更新花费的时间
    baseDuration, // 估计不使用 memoization 的情况下渲染整颗子树需要的时间
    startTime, // 本次更新开始渲染的时间
    commitTime, // 本次更新提交的时间
    interactions // 属于本次更新的 interactions 的集合
) {
    console.log(`${id} (${phase}) 渲染耗时: ${actualDuration}ms`);
}
 
function ProfiledApp() {
    return (
        <Profiler id="App" onRender={onRenderCallback}>
            <App />
        </Profiler>
    );
}
 
// 9. 状态管理优化
// 使用Context时避免不必要的重渲染
const DataContext = React.createContext();
const UpdateContext = React.createContext();
 
function DataProvider({ children }) {
    const [data, setData] = useState({});
    
    // 分离数据和更新函数
    return (
        <DataContext.Provider value={data}>
            <UpdateContext.Provider value={setData}>
                {children}
            </UpdateContext.Provider>
        </DataContext.Provider>
    );
}
 
// 10. 使用useTransition处理非紧急更新
import { useTransition } from 'react';
 
function SearchComponent() {
    const [query, setQuery] = useState('');
    const [results, setResults] = useState([]);
    const [isPending, startTransition] = useTransition();
    
    const handleChange = (e) => {
        const value = e.target.value;
        setQuery(value);
        
        // 将搜索结果更新标记为非紧急
        startTransition(() => {
            const filtered = expensiveSearch(value);
            setResults(filtered);
        });
    };
    
    return (
        <div>
            <input value={query} onChange={handleChange} />
            {isPending && <div>搜索中...</div>}
            <ResultsList results={results} />
        </div>
    );
}
 
// ========== React性能监控 ==========
 
class ReactPerformanceMonitor {
    constructor() {
        this.measurements = [];
    }
    
    // 测量组件渲染时间
    measureComponent(componentName, callback) {
        const startTime = performance.now();
        const result = callback();
        const endTime = performance.now();
        
        this.measurements.push({
            component: componentName,
            duration: endTime - startTime,
            timestamp: Date.now()
        });
        
        return result;
    }
    
    // 获取性能报告
    getReport() {
        const grouped = this.measurements.reduce((acc, m) => {
            if (!acc[m.component]) {
                acc[m.component] = {
                    count: 0,
                    totalDuration: 0,
                    avgDuration: 0
                };
            }
            
            acc[m.component].count++;
            acc[m.component].totalDuration += m.duration;
            acc[m.component].avgDuration = 
                acc[m.component].totalDuration / acc[m.component].count;
            
            return acc;
        }, {});
        
        return Object.entries(grouped)
            .map(([component, stats]) => ({
                component,
                ...stats
            }))
            .sort((a, b) => b.avgDuration - a.avgDuration);
    }
    
    // 打印报告
    printReport() {
        const report = this.getReport();
        
        console.log('📊 React性能报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        report.forEach(item => {
            console.log(`${item.component}:`);
            console.log(`  渲染次数: ${item.count}`);
            console.log(`  平均耗时: ${item.avgDuration.toFixed(2)}ms`);
            console.log(`  总耗时: ${item.totalDuration.toFixed(2)}ms`);
        });
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
const monitor = new ReactPerformanceMonitor();
 
function MonitoredComponent() {
    return monitor.measureComponent('MonitoredComponent', () => {
        // 组件逻辑
        return <div>Hello</div>;
    });
}

9.2 Vue性能优化



// ========== Vue 3性能优化技巧 ==========
 
import { 
    ref, 
    computed, 
    watch, 
    watchEffect,
    shallowRef,
    shallowReactive,
    markRaw,
    defineAsyncComponent,
    KeepAlive,
    Teleport
} from 'vue';
 
// 1. 使用shallowRef和shallowReactive
// ❌ 深度响应式(性能开销大)
const deepState = ref({
    nested: {
        deep: {
            value: 1
        }
    }
});
 
// ✅ 浅层响应式(性能更好)
const shallowState = shallowRef({
    nested: {
        deep: {
            value: 1
        }
    }
});
 
// 更新时需要替换整个对象
shallowState.value = {
    nested: {
        deep: {
            value: 2
        }
    }
};
 
// 2. 使用computed缓存计算结果
export default {
    setup() {
        const items = ref([]);
        
        // ❌ 每次访问都重新计算
        const getFilteredItems = () => {
            return items.value.filter(item => item.active);
        };
        
        // ✅ 使用computed缓存
        const filteredItems = computed(() => {
            return items.value.filter(item => item.active);
        });
        
        return { filteredItems };
    }
};
 
// 3. v-once和v-memo优化
// template:
/*
<!-- 只渲染一次 -->
<div v-once>{{ staticContent }}</div>
 
<!-- 根据依赖决定是否更新 -->
<div v-memo="[item.id, item.name]">
    {{ item.name }} - {{ item.description }}
</div>
*/
 
// 4. 虚拟滚动
import { ref, computed } from 'vue';
 
export default {
    setup() {
        const items = ref(Array.from({ length: 10000 }, (_, i) => ({
            id: i,
            name: `Item ${i}`
        })));
        
        const scrollTop = ref(0);
        const itemHeight = 50;
        const visibleCount = 20;
        
        const visibleItems = computed(() => {
            const start = Math.floor(scrollTop.value / itemHeight);
            const end = start + visibleCount;
            return items.value.slice(start, end);
        });
        
        const offsetY = computed(() => {
            return Math.floor(scrollTop.value / itemHeight) * itemHeight;
        });
        
        const totalHeight = computed(() => {
            return items.value.length * itemHeight;
        });
        
        const handleScroll = (e) => {
            scrollTop.value = e.target.scrollTop;
        };
        
        return {
            visibleItems,
            offsetY,
            totalHeight,
            handleScroll
        };
    }
};
 
// 5. 异步组件
const AsyncComponent = defineAsyncComponent({
    loader: () => import('./HeavyComponent.vue'),
    loadingComponent: LoadingComponent,
    errorComponent: ErrorComponent,
    delay: 200,
    timeout: 3000
});
 
// 6. KeepAlive缓存组件
// template:
/*
<KeepAlive :max="10">
    <component :is="currentComponent" />
</KeepAlive>
*/
 
// 7. 避免不必要的响应式
export default {
    setup() {
        // ❌ 大型数据结构不需要响应式
        const largeData = ref({
            // 10000条数据
        });
        
        // ✅ 使用markRaw标记为非响应式
        const optimizedData = markRaw({
            // 10000条数据
        });
        
        return { optimizedData };
    }
};
 
// 8. 函数式组件
import { h } from 'vue';
 
// 函数式组件没有实例,性能更好
export default function FunctionalComponent(props) {
    return h('div', props.text);
}
 
// 9. 优化watch
export default {
    setup() {
        const data = ref({});
        
        // ❌ 深度监听(性能开销大)
        watch(data, () => {
            console.log('changed');
        }, { deep: true });
        
        // ✅ 监听特定属性
        watch(() => data.value.specificProp, () => {
            console.log('changed');
        });
        
        // ✅ 使用watchEffect(自动追踪依赖)
        watchEffect(() => {
            console.log(data.value.specificProp);
        });
    }
};
 
// 10. 延迟加载路由
const routes = [
    {
        path: '/',
        component: () => import('./views/Home.vue')
    },
    {
        path: '/about',
        component: () => import('./views/About.vue')
    }
];
 
// ========== Vue性能监控 ==========
 
class VuePerformanceMonitor {
    constructor(app) {
        this.app = app;
        this.measurements = new Map();
        this.setupHooks();
    }
    
    setupHooks() {
        // 监听组件挂载
        this.app.mixin({
            beforeMount() {
                const name = this.$options.name || 'Anonymous';
                performance.mark(`${name}-mount-start`);
            },
            mounted() {
                const name = this.$options.name || 'Anonymous';
                performance.mark(`${name}-mount-end`);
                performance.measure(
                    `${name}-mount`,
                    `${name}-mount-start`,
                    `${name}-mount-end`
                );
                
                const measure = performance.getEntriesByName(`${name}-mount`)[0];
                this.recordMeasurement(name, 'mount', measure.duration);
            },
            
            beforeUpdate() {
                const name = this.$options.name || 'Anonymous';
                performance.mark(`${name}-update-start`);
            },
            updated() {
                const name = this.$options.name || 'Anonymous';
                performance.mark(`${name}-update-end`);
                performance.measure(
                    `${name}-update`,
                    `${name}-update-start`,
                    `${name}-update-end`
                );
                
                const measure = performance.getEntriesByName(`${name}-update`)[0];
                this.recordMeasurement(name, 'update', measure.duration);
            }
        });
    }
    
    recordMeasurement(component, type, duration) {
        if (!this.measurements.has(component)) {
            this.measurements.set(component, {
                mount: [],
                update: []
            });
        }
        
        this.measurements.get(component)[type].push(duration);
    }
    
    getReport() {
        const report = [];
        
        this.measurements.forEach((data, component) => {
            const mountAvg = data.mount.length > 0 ?
                data.mount.reduce((a, b) => a + b, 0) / data.mount.length : 0;
            
            const updateAvg = data.update.length > 0 ?
                data.update.reduce((a, b) => a + b, 0) / data.update.length : 0;
            
            report.push({
                component,
                mountCount: data.mount.length,
                updateCount: data.update.length,
                avgMountTime: mountAvg.toFixed(2),
                avgUpdateTime: updateAvg.toFixed(2)
            });
        });
        
        return report.sort((a, b) => 
            parseFloat(b.avgUpdateTime) - parseFloat(a.avgUpdateTime)
        );
    }
    
    printReport() {
        const report = this.getReport();
        
        console.log('📊 Vue性能报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        report.forEach(item => {
            console.log(`${item.component}:`);
            console.log(`  挂载次数: ${item.mountCount}`);
            console.log(`  更新次数: ${item.updateCount}`);
            console.log(`  平均挂载时间: ${item.avgMountTime}ms`);
            console.log(`  平均更新时间: ${item.avgUpdateTime}ms`);
        });
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
import { createApp } from 'vue';
import App from './App.vue';
 
const app = createApp(App);
const monitor = new VuePerformanceMonitor(app);
 
app.mount('#app');
 
// 在开发环境打印性能报告
if (process.env.NODE_ENV === 'development') {
    setTimeout(() => {
        monitor.printReport();
    }, 5000);
}

第十章:性能监控与持续优化

10.1 性能监控系统



// ========== 综合性能监控系统 ==========
 
class PerformanceMonitoringSystem {
    constructor(config = {}) {
        this.config = {
            reportInterval: config.reportInterval || 60000, // 1分钟
            sampleRate: config.sampleRate || 1, // 100%采样
            endpoint: config.endpoint || '/api/performance',
            ...config
        };
        
        this.metrics = {
            navigation: [],
            resources: [],
            paint: [],
            interactions: [],
            errors: [],
            customMetrics: []
        };
        
        this.init();
    }
    
    init() {
        // 监听页面加载性能
        this.observeNavigation();
        
        // 监听资源加载性能
        this.observeResources();
        
        // 监听绘制性能
        this.observePaint();
        
        // 监听用户交互性能
        this.observeInteractions();
        
        // 监听错误
        this.observeErrors();
        
        // 定期上报
        this.startReporting();
    }
    
    // 监听导航性能
    observeNavigation() {
        window.addEventListener('load', () => {
            setTimeout(() => {
                const navTiming = performance.getEntriesByType('navigation')[0];
                
                if (navTiming) {
                    this.metrics.navigation.push({
                        timestamp: Date.now(),
                        url: window.location.href,
                        dns: navTiming.domainLookupEnd - navTiming.domainLookupStart,
                        tcp: navTiming.connectEnd - navTiming.connectStart,
                        request: navTiming.responseEnd - navTiming.requestStart,
                        response: navTiming.responseEnd - navTiming.responseStart,
                        dom: navTiming.domComplete - navTiming.domInteractive,
                        load: navTiming.loadEventEnd - navTiming.fetchStart,
                        ttfb: navTiming.responseStart - navTiming.requestStart
                    });
                }
            }, 0);
        });
    }
    
    // 监听资源加载性能
    observeResources() {
        const observer = new PerformanceObserver((list) => {
            list.getEntries().forEach((entry) => {
                if (Math.random() <= this.config.sampleRate) {
                    this.metrics.resources.push({
                        timestamp: Date.now(),
                        name: entry.name,
                        type: this.getResourceType(entry.name),
                        duration: entry.duration,
                        size: entry.transferSize || 0,
                        cached: entry.transferSize === 0 && entry.decodedBodySize > 0
                    });
                }
            });
        });
        
        observer.observe({ entryTypes: ['resource'] });
    }
    
    // 监听绘制性能
    observePaint() {
        const observer = new PerformanceObserver((list) => {
            list.getEntries().forEach((entry) => {
                this.metrics.paint.push({
                    timestamp: Date.now(),
                    name: entry.name,
                    startTime: entry.startTime
                });
            });
        });
        
        observer.observe({ entryTypes: ['paint'] });
        
        // 监听LCP
        const lcpObserver = new PerformanceObserver((list) => {
            const entries = list.getEntries();
            const lastEntry = entries[entries.length - 1];
            
            this.metrics.paint.push({
                timestamp: Date.now(),
                name: 'largest-contentful-paint',
                startTime: lastEntry.renderTime || lastEntry.loadTime
            });
        });
        
        lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] });
    }
    
    // 监听用户交互性能
    observeInteractions() {
        // FID
        const fidObserver = new PerformanceObserver((list) => {
            list.getEntries().forEach((entry) => {
                this.metrics.interactions.push({
                    timestamp: Date.now(),
                    type: 'first-input-delay',
                    delay: entry.processingStart - entry.startTime,
                    eventType: entry.name
                });
            });
        });
        
        fidObserver.observe({ entryTypes: ['first-input'] });
        
        // CLS
        let clsValue = 0;
        const clsObserver = new PerformanceObserver((list) => {
            list.getEntries().forEach((entry) => {
                if (!entry.hadRecentInput) {
                    clsValue += entry.value;
                }
            });
        });
        
        clsObserver.observe({ entryTypes: ['layout-shift'] });
        
        // 页面卸载时记录CLS
        window.addEventListener('beforeunload', () => {
            this.metrics.interactions.push({
                timestamp: Date.now(),
                type: 'cumulative-layout-shift',
                value: clsValue
            });
        });
    }
    
    // 监听错误
    observeErrors() {
        // JavaScript错误
        window.addEventListener('error', (event) => {
            this.metrics.errors.push({
                timestamp: Date.now(),
                type: 'javascript',
                message: event.message,
                filename: event.filename,
                lineno: event.lineno,
                colno: event.colno,
                stack: event.error?.stack
            });
        });
        
        // Promise错误
        window.addEventListener('unhandledrejection', (event) => {
            this.metrics.errors.push({
                timestamp: Date.now(),
                type: 'promise',
                reason: event.reason,
                promise: event.promise
            });
        });
        
        // 资源加载错误
        window.addEventListener('error', (event) => {
            if (event.target !== window) {
                this.metrics.errors.push({
                    timestamp: Date.now(),
                    type: 'resource',
                    target: event.target.tagName,
                    src: event.target.src || event.target.href
                });
            }
        }, true);
    }
    
    // 记录自定义指标
    recordCustomMetric(name, value, tags = {}) {
        this.metrics.customMetrics.push({
            timestamp: Date.now(),
            name,
            value,
            tags
        });
    }
    
    // 获取资源类型
    getResourceType(url) {
        if (url.match(/.(js)$/)) return 'script';
        if (url.match(/.(css)$/)) return 'stylesheet';
        if (url.match(/.(jpg|jpeg|png|gif|webp|svg)$/)) return 'image';
        if (url.match(/.(woff|woff2|ttf|eot)$/)) return 'font';
        return 'other';
    }
    
    // 生成报告
    generateReport() {
        return {
            timestamp: Date.now(),
            url: window.location.href,
            userAgent: navigator.userAgent,
            metrics: {
                navigation: this.aggregateNavigation(),
                resources: this.aggregateResources(),
                paint: this.aggregatePaint(),
                interactions: this.aggregateInteractions(),
                errors: this.metrics.errors,
                custom: this.metrics.customMetrics
            }
        };
    }
    
    // 聚合导航数据
    aggregateNavigation() {
        if (this.metrics.navigation.length === 0) return null;
        
        const latest = this.metrics.navigation[this.metrics.navigation.length - 1];
        return latest;
    }
    
    // 聚合资源数据
    aggregateResources() {
        const byType = {};
        
        this.metrics.resources.forEach(resource => {
            if (!byType[resource.type]) {
                byType[resource.type] = {
                    count: 0,
                    totalSize: 0,
                    totalDuration: 0,
                    cached: 0
                };
            }
            
            byType[resource.type].count++;
            byType[resource.type].totalSize += resource.size;
            byType[resource.type].totalDuration += resource.duration;
            if (resource.cached) byType[resource.type].cached++;
        });
        
        return byType;
    }
    
    // 聚合绘制数据
    aggregatePaint() {
        const paintMetrics = {};
        
        this.metrics.paint.forEach(paint => {
            paintMetrics[paint.name] = paint.startTime;
        });
        
        return paintMetrics;
    }
    
    // 聚合交互数据
    aggregateInteractions() {
        const interactions = {};
        
        this.metrics.interactions.forEach(interaction => {
            if (interaction.type === 'first-input-delay') {
                interactions.fid = interaction.delay;
            } else if (interaction.type === 'cumulative-layout-shift') {
                interactions.cls = interaction.value;
            }
        });
        
        return interactions;
    }
    
    // 上报数据
    async report() {
        const report = this.generateReport();
        
        try {
            // 使用sendBeacon确保数据发送
            if (navigator.sendBeacon) {
                const blob = new Blob([JSON.stringify(report)], {
                    type: 'application/json'
                });
                navigator.sendBeacon(this.config.endpoint, blob);
            } else {
                // 降级到fetch
                await fetch(this.config.endpoint, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(report),
                    keepalive: true
                });
            }
            
            // 清空已上报的数据
            this.clearMetrics();
        } catch (error) {
            console.error('性能数据上报失败:', error);
        }
    }
    
    // 清空指标
    clearMetrics() {
        this.metrics.resources = [];
        this.metrics.errors = [];
        this.metrics.customMetrics = [];
    }
    
    // 开始定期上报
    startReporting() {
        setInterval(() => {
            this.report();
        }, this.config.reportInterval);
        
        // 页面卸载时上报
        window.addEventListener('beforeunload', () => {
            this.report();
        });
        
        // 页面隐藏时上报
        document.addEventListener('visibilitychange', () => {
            if (document.visibilityState === 'hidden') {
                this.report();
            }
        });
    }
    
    // 打印本地报告
    printReport() {
        const report = this.generateReport();
        
        console.log('📊 性能监控报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log('URL:', report.url);
        console.log('时间:', new Date(report.timestamp).toLocaleString());
        console.log('');
        
        if (report.metrics.navigation) {
            console.log('📡 导航性能:');
            console.log(`  DNS: ${report.metrics.navigation.dns.toFixed(2)}ms`);
            console.log(`  TCP: ${report.metrics.navigation.tcp.toFixed(2)}ms`);
            console.log(`  请求: ${report.metrics.navigation.request.toFixed(2)}ms`);
            console.log(`  DOM: ${report.metrics.navigation.dom.toFixed(2)}ms`);
            console.log(`  加载: ${report.metrics.navigation.load.toFixed(2)}ms`);
            console.log(`  TTFB: ${report.metrics.navigation.ttfb.toFixed(2)}ms`);
            console.log('');
        }
        
        if (Object.keys(report.metrics.resources).length > 0) {
            console.log('📦 资源加载:');
            Object.entries(report.metrics.resources).forEach(([type, data]) => {
                console.log(`  ${type}:`);
                console.log(`    数量: ${data.count}`);
                console.log(`    大小: ${(data.totalSize / 1024).toFixed(2)} KB`);
                console.log(`    耗时: ${data.totalDuration.toFixed(2)}ms`);
                console.log(`    缓存: ${data.cached}/${data.count}`);
            });
            console.log('');
        }
        
        if (Object.keys(report.metrics.paint).length > 0) {
            console.log('🎨 绘制性能:');
            Object.entries(report.metrics.paint).forEach(([name, time]) => {
                console.log(`  ${name}: ${time.toFixed(2)}ms`);
            });
            console.log('');
        }
        
        if (Object.keys(report.metrics.interactions).length > 0) {
            console.log('👆 交互性能:');
            if (report.metrics.interactions.fid !== undefined) {
                console.log(`  FID: ${report.metrics.interactions.fid.toFixed(2)}ms`);
            }
            if (report.metrics.interactions.cls !== undefined) {
                console.log(`  CLS: ${report.metrics.interactions.cls.toFixed(4)}`);
            }
            console.log('');
        }
        
        if (report.metrics.errors.length > 0) {
            console.log('❌ 错误统计:');
            console.log(`  总数: ${report.metrics.errors.length}`);
            const errorsByType = report.metrics.errors.reduce((acc, err) => {
                acc[err.type] = (acc[err.type] || 0) + 1;
                return acc;
            }, {});
            Object.entries(errorsByType).forEach(([type, count]) => {
                console.log(`  ${type}: ${count}`);
            });
        }
        
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
const monitor = new PerformanceMonitoringSystem({
    reportInterval: 30000, // 30秒上报一次
    sampleRate: 0.1, // 10%采样率
    endpoint: '/api/performance'
});
 
// 记录自定义指标
monitor.recordCustomMetric('api-call', 234, {
    endpoint: '/api/users',
    method: 'GET'
});
 
// 打印本地报告
setTimeout(() => {
    monitor.printReport();
}, 5000);

10.2 性能预算



// ========== 性能预算系统 ==========
 
class PerformanceBudget {
    constructor(budgets) {
        this.budgets = {
            // 页面加载预算
            pageLoad: {
                ttfb: budgets.ttfb || 600,           // Time to First Byte
                fcp: budgets.fcp || 1800,            // First Contentful Paint
                lcp: budgets.lcp || 2500,            // Largest Contentful Paint
                tti: budgets.tti || 3800,            // Time to Interactive
                totalLoad: budgets.totalLoad || 5000 // Total Load Time
            },
            
            // 资源预算
            resources: {
                javascript: budgets.javascript || 200,  // KB
                css: budgets.css || 100,                // KB
                images: budgets.images || 500,          // KB
                fonts: budgets.fonts || 100,            // KB
                total: budgets.total || 1000            // KB
            },
            
            // 交互预算
            interactions: {
                fid: budgets.fid || 100,    // First Input Delay (ms)
                cls: budgets.cls || 0.1     // Cumulative Layout Shift
            },
            
            // 请求数量预算
            requests: {
                total: budgets.requests || 50,
                javascript: budgets.jsRequests || 10,
                css: budgets.cssRequests || 5,
                images: budgets.imageRequests || 30
            }
        };
        
        this.violations = [];
    }
    
    // 检查页面加载性能
    checkPageLoad() {
        const navTiming = performance.getEntriesByType('navigation')[0];
        if (!navTiming) return;
        
        const metrics = {
            ttfb: navTiming.responseStart - navTiming.requestStart,
            totalLoad: navTiming.loadEventEnd - navTiming.fetchStart
        };
        
        // 检查TTFB
        if (metrics.ttfb > this.budgets.pageLoad.ttfb) {
            this.violations.push({
                type: 'pageLoad',
                metric: 'TTFB',
                actual: metrics.ttfb.toFixed(2),
                budget: this.budgets.pageLoad.ttfb,
                severity: this.calculateSeverity(metrics.ttfb, this.budgets.pageLoad.ttfb)
            });
        }
        
        // 检查总加载时间
        if (metrics.totalLoad > this.budgets.pageLoad.totalLoad) {
            this.violations.push({
                type: 'pageLoad',
                metric: 'Total Load',
                actual: metrics.totalLoad.toFixed(2),
                budget: this.budgets.pageLoad.totalLoad,
                severity: this.calculateSeverity(metrics.totalLoad, this.budgets.pageLoad.totalLoad)
            });
        }
    }
    
    // 检查资源大小
    checkResources() {
        const resources = performance.getEntriesByType('resource');
        const sizes = {
            javascript: 0,
            css: 0,
            images: 0,
            fonts: 0,
            total: 0
        };
        
        const counts = {
            total: resources.length,
            javascript: 0,
            css: 0,
            images: 0
        };
        
        resources.forEach(resource => {
            const size = (resource.transferSize || 0) / 1024; // 转换为KB
            sizes.total += size;
            
            if (resource.name.match(/.js$/)) {
                sizes.javascript += size;
                counts.javascript++;
            } else if (resource.name.match(/.css$/)) {
                sizes.css += size;
                counts.css++;
            } else if (resource.name.match(/.(jpg|jpeg|png|gif|webp|svg)$/)) {
                sizes.images += size;
                counts.images++;
            } else if (resource.name.match(/.(woff|woff2|ttf|eot)$/)) {
                sizes.fonts += size;
            }
        });
        
        // 检查各类资源大小
        Object.entries(sizes).forEach(([type, size]) => {
            if (size > this.budgets.resources[type]) {
                this.violations.push({
                    type: 'resources',
                    metric: `${type} size`,
                    actual: size.toFixed(2) + ' KB',
                    budget: this.budgets.resources[type] + ' KB',
                    severity: this.calculateSeverity(size, this.budgets.resources[type])
                });
            }
        });
        
        // 检查请求数量
        Object.entries(counts).forEach(([type, count]) => {
            if (count > this.budgets.requests[type]) {
                this.violations.push({
                    type: 'requests',
                    metric: `${type} requests`,
                    actual: count,
                    budget: this.budgets.requests[type],
                    severity: this.calculateSeverity(count, this.budgets.requests[type])
                });
            }
        });
    }
    
    // 检查Core Web Vitals
    async checkCoreWebVitals() {
        return new Promise((resolve) => {
            const metrics = {
                lcp: null,
                fid: null,
                cls: null
            };
            
            // LCP
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                const lastEntry = entries[entries.length - 1];
                metrics.lcp = lastEntry.renderTime || lastEntry.loadTime;
                
                if (metrics.lcp > this.budgets.pageLoad.lcp) {
                    this.violations.push({
                        type: 'coreWebVitals',
                        metric: 'LCP',
                        actual: metrics.lcp.toFixed(2) + ' ms',
                        budget: this.budgets.pageLoad.lcp + ' ms',
                        severity: this.calculateSeverity(metrics.lcp, this.budgets.pageLoad.lcp)
                    });
                }
            }).observe({ entryTypes: ['largest-contentful-paint'] });
            
            // FID
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                entries.forEach(entry => {
                    if (!metrics.fid) {
                        metrics.fid = entry.processingStart - entry.startTime;
                        
                        if (metrics.fid > this.budgets.interactions.fid) {
                            this.violations.push({
                                type: 'coreWebVitals',
                                metric: 'FID',
                                actual: metrics.fid.toFixed(2) + ' ms',
                                budget: this.budgets.interactions.fid + ' ms',
                                severity: this.calculateSeverity(metrics.fid, this.budgets.interactions.fid)
                            });
                        }
                    }
                });
            }).observe({ entryTypes: ['first-input'] });
            
            // CLS
            let clsValue = 0;
            new PerformanceObserver((list) => {
                list.getEntries().forEach(entry => {
                    if (!entry.hadRecentInput) {
                        clsValue += entry.value;
                        metrics.cls = clsValue;
                    }
                });
            }).observe({ entryTypes: ['layout-shift'] });
            
            // 5秒后检查CLS
            setTimeout(() => {
                if (metrics.cls > this.budgets.interactions.cls) {
                    this.violations.push({
                        type: 'coreWebVitals',
                        metric: 'CLS',
                        actual: metrics.cls.toFixed(4),
                        budget: this.budgets.interactions.cls,
                        severity: this.calculateSeverity(metrics.cls, this.budgets.interactions.cls)
                    });
                }
                resolve(metrics);
            }, 5000);
        });
    }
    
    // 计算严重程度
    calculateSeverity(actual, budget) {
        const ratio = actual / budget;
        
        if (ratio >= 2) return 'critical';
        if (ratio >= 1.5) return 'high';
        if (ratio >= 1.2) return 'medium';
        return 'low';
    }
    
    // 执行所有检查
    async runAllChecks() {
        this.violations = [];
        
        this.checkPageLoad();
        this.checkResources();
        await this.checkCoreWebVitals();
        
        return this.violations;
    }
    
    // 生成报告
    generateReport() {
        const report = {
            timestamp: Date.now(),
            url: window.location.href,
            totalViolations: this.violations.length,
            violationsBySeverity: {
                critical: 0,
                high: 0,
                medium: 0,
                low: 0
            },
            violations: this.violations
        };
        
        this.violations.forEach(v => {
            report.violationsBySeverity[v.severity]++;
        });
        
        return report;
    }
    
    // 打印报告
    printReport() {
        const report = this.generateReport();
        
        console.log('💰 性能预算报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        console.log(`URL: ${report.url}`);
        console.log(`时间: ${new Date(report.timestamp).toLocaleString()}`);
        console.log(`总违规数: ${report.totalViolations}`);
        console.log('');
        
        console.log('按严重程度统计:');
        console.log(`  🔴 严重: ${report.violationsBySeverity.critical}`);
        console.log(`  🟠 高: ${report.violationsBySeverity.high}`);
        console.log(`  🟡 中: ${report.violationsBySeverity.medium}`);
        console.log(`  🟢 低: ${report.violationsBySeverity.low}`);
        console.log('');
        
        if (report.violations.length > 0) {
            console.log('违规详情:');
            report.violations.forEach((v, index) => {
                const icon = {
                    critical: '🔴',
                    high: '🟠',
                    medium: '🟡',
                    low: '🟢'
                }[v.severity];
                
                console.log(`${index + 1}. ${icon} ${v.metric}`);
                console.log(`   实际值: ${v.actual}`);
                console.log(`   预算值: ${v.budget}`);
                console.log(`   严重程度: ${v.severity}`);
            });
        } else {
            console.log('✅ 所有指标都在预算范围内!');
        }
        
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
}
 
// 使用示例
const budget = new PerformanceBudget({
    // 页面加载预算(毫秒)
    ttfb: 600,
    fcp: 1800,
    lcp: 2500,
    tti: 3800,
    totalLoad: 5000,
    
    // 资源预算(KB)
    javascript: 200,
    css: 100,
    images: 500,
    fonts: 100,
    total: 1000,
    
    // 交互预算
    fid: 100,
    cls: 0.1,
    
    // 请求数量预算
    requests: 50,
    jsRequests: 10,
    cssRequests: 5,
    imageRequests: 30
});
 
// 页面加载完成后检查
window.addEventListener('load', async () => {
    await budget.runAllChecks();
    budget.printReport();
    
    // 如果有严重违规,发出警告
    const report = budget.generateReport();
    if (report.violationsBySeverity.critical > 0) {
        console.error('⚠️ 检测到严重的性能预算违规!');
    }
});

10.3 持续优化流程



// ========== 持续优化流程管理 ==========
 
class ContinuousOptimizationPipeline {
    constructor() {
        this.optimizations = new Map();
        this.history = [];
        this.baseline = null;
    }
    
    // 设置性能基线
    async setBaseline() {
        const metrics = await this.measurePerformance();
        this.baseline = {
            timestamp: Date.now(),
            metrics
        };
        
        console.log('📊 性能基线已设置');
        this.printMetrics(metrics);
    }
    
    // 测量性能
    async measurePerformance() {
        return new Promise((resolve) => {
            const metrics = {
                navigation: null,
                resources: null,
                paint: null,
                interactions: null
            };
            
            // 导航性能
            const navTiming = performance.getEntriesByType('navigation')[0];
            if (navTiming) {
                metrics.navigation = {
                    ttfb: navTiming.responseStart - navTiming.requestStart,
                    domLoad: navTiming.domContentLoadedEventEnd - navTiming.fetchStart,
                    totalLoad: navTiming.loadEventEnd - navTiming.fetchStart
                };
            }
            
            // 资源性能
            const resources = performance.getEntriesByType('resource');
            const totalSize = resources.reduce((sum, r) => sum + (r.transferSize || 0), 0);
            metrics.resources = {
                count: resources.length,
                totalSize: totalSize / 1024, // KB
                avgDuration: resources.reduce((sum, r) => sum + r.duration, 0) / resources.length
            };
            
            // 绘制性能
            const paintEntries = performance.getEntriesByType('paint');
            metrics.paint = {};
            paintEntries.forEach(entry => {
                metrics.paint[entry.name] = entry.startTime;
            });
            
            // Core Web Vitals
            let lcp = null;
            let fid = null;
            let cls = 0;
            
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                lcp = entries[entries.length - 1].renderTime || entries[entries.length - 1].loadTime;
            }).observe({ entryTypes: ['largest-contentful-paint'] });
            
            new PerformanceObserver((list) => {
                const entries = list.getEntries();
                if (entries.length > 0 && !fid) {
                    fid = entries[0].processingStart - entries[0].startTime;
                }
            }).observe({ entryTypes: ['first-input'] });
            
            new PerformanceObserver((list) => {
                list.getEntries().forEach(entry => {
                    if (!entry.hadRecentInput) {
                        cls += entry.value;
                    }
                });
            }).observe({ entryTypes: ['layout-shift'] });
            
            setTimeout(() => {
                metrics.interactions = { lcp, fid, cls };
                resolve(metrics);
            }, 3000);
        });
    }
    
    // 注册优化
    registerOptimization(name, implementation, expectedImprovement) {
        this.optimizations.set(name, {
            name,
            implementation,
            expectedImprovement,
            applied: false,
            actualImprovement: null
        });
    }
    
    // 应用优化
    async applyOptimization(name) {
        const optimization = this.optimizations.get(name);
        if (!optimization) {
            console.error(`优化 ${name} 不存在`);
            return;
        }
        
        if (optimization.applied) {
            console.warn(`优化 ${name} 已经应用过`);
            return;
        }
        
        console.log(`🔧 应用优化: ${name}`);
        
        // 应用前测量
        const before = await this.measurePerformance();
        
        // 应用优化
        await optimization.implementation();
        
        // 等待一段时间让优化生效
        await new Promise(resolve => setTimeout(resolve, 2000));
        
        // 应用后测量
        const after = await this.measurePerformance();
        
        // 计算改进
        const improvement = this.calculateImprovement(before, after);
        
        optimization.applied = true;
        optimization.actualImprovement = improvement;
        
        // 记录历史
        this.history.push({
            timestamp: Date.now(),
            optimization: name,
            before,
            after,
            improvement
        });
        
        console.log(`✅ 优化 ${name} 已应用`);
        this.printImprovement(improvement);
    }
    
    // 计算改进
    calculateImprovement(before, after) {
        const improvement = {};
        
        // 导航性能改进
        if (before.navigation && after.navigation) {
            improvement.navigation = {
                ttfb: this.percentChange(before.navigation.ttfb, after.navigation.ttfb),
                domLoad: this.percentChange(before.navigation.domLoad, after.navigation.domLoad),
                totalLoad: this.percentChange(before.navigation.totalLoad, after.navigation.totalLoad)
            };
        }
        
        // 资源改进
        if (before.resources && after.resources) {
            improvement.resources = {
                count: this.percentChange(before.resources.count, after.resources.count),
                totalSize: this.percentChange(before.resources.totalSize, after.resources.totalSize),
                avgDuration: this.percentChange(before.resources.avgDuration, after.resources.avgDuration)
            };
        }
        
        // Core Web Vitals改进
        if (before.interactions && after.interactions) {
            improvement.interactions = {
                lcp: this.percentChange(before.interactions.lcp, after.interactions.lcp),
                fid: before.interactions.fid && after.interactions.fid ? 
                    this.percentChange(before.interactions.fid, after.interactions.fid) : null,
                cls: this.percentChange(before.interactions.cls, after.interactions.cls)
            };
        }
        
        return improvement;
    }
    
    // 计算百分比变化
    percentChange(before, after) {
        if (!before || !after) return null;
        return ((before - after) / before * 100).toFixed(2);
    }
    
    // 生成优化报告
    generateOptimizationReport() {
        const report = {
            baseline: this.baseline,
            optimizations: [],
            totalImprovement: null
        };
        
        this.optimizations.forEach((opt, name) => {
            if (opt.applied) {
                report.optimizations.push({
                    name: opt.name,
                    expectedImprovement: opt.expectedImprovement,
                    actualImprovement: opt.actualImprovement
                });
            }
        });
        
        // 计算总体改进
        if (this.baseline && this.history.length > 0) {
            const latest = this.history[this.history.length - 1];
            report.totalImprovement = this.calculateImprovement(
                this.baseline.metrics,
                latest.after
            );
        }
        
        return report;
    }
    
    // 打印指标
    printMetrics(metrics) {
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        if (metrics.navigation) {
            console.log('导航性能:');
            console.log(`  TTFB: ${metrics.navigation.ttfb.toFixed(2)}ms`);
            console.log(`  DOM加载: ${metrics.navigation.domLoad.toFixed(2)}ms`);
            console.log(`  总加载: ${metrics.navigation.totalLoad.toFixed(2)}ms`);
        }
        
        if (metrics.resources) {
            console.log('资源性能:');
            console.log(`  数量: ${metrics.resources.count}`);
            console.log(`  总大小: ${metrics.resources.totalSize.toFixed(2)} KB`);
            console.log(`  平均耗时: ${metrics.resources.avgDuration.toFixed(2)}ms`);
        }
        
        if (metrics.interactions) {
            console.log('Core Web Vitals:');
            if (metrics.interactions.lcp) {
                console.log(`  LCP: ${metrics.interactions.lcp.toFixed(2)}ms`);
            }
            if (metrics.interactions.fid) {
                console.log(`  FID: ${metrics.interactions.fid.toFixed(2)}ms`);
            }
            console.log(`  CLS: ${metrics.interactions.cls.toFixed(4)}`);
        }
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
    
    // 打印改进
    printImprovement(improvement) {
        console.log('📈 性能改进:');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        
        if (improvement.navigation) {
            console.log('导航性能改进:');
            Object.entries(improvement.navigation).forEach(([key, value]) => {
                if (value !== null) {
                    const icon = parseFloat(value) > 0 ? '✅' : '❌';
                    console.log(`  ${icon} ${key}: ${value}%`);
                }
            });
        }
        
        if (improvement.resources) {
            console.log('资源性能改进:');
            Object.entries(improvement.resources).forEach(([key, value]) => {
                if (value !== null) {
                    const icon = parseFloat(value) > 0 ? '✅' : '❌';
                    console.log(`  ${icon} ${key}: ${value}%`);
                }
            });
        }
        
        if (improvement.interactions) {
            console.log('Core Web Vitals改进:');
            Object.entries(improvement.interactions).forEach(([key, value]) => {
                if (value !== null) {
                    const icon = parseFloat(value) > 0 ? '✅' : '❌';
                    console.log(`  ${icon} ${key.toUpperCase()}: ${value}%`);
                }
            });
        }
        
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    }
    
    // 打印完整报告
    printFullReport() {
        const report = this.generateOptimizationReport();
        
        console.log('📊 持续优化完整报告');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
        
        if (report.baseline) {
            console.log('基线指标:');
            this.printMetrics(report.baseline.metrics);
        }
        
        console.log('已应用的优化:');
        report.optimizations.forEach((opt, index) => {
            console.log(`${index + 1}. ${opt.name}`);
            console.log(`   预期改进: ${opt.expectedImprovement}`);
        });
        
        if (report.totalImprovement) {
            console.log('');
            console.log('总体改进:');
            this.printImprovement(report.totalImprovement);
        }
    }
}
 
// 使用示例
const pipeline = new ContinuousOptimizationPipeline();
 
// 设置基线
window.addEventListener('load', async () => {
    await pipeline.setBaseline();
    
    // 注册优化措施
    pipeline.registerOptimization(
        '图片懒加载',
        async () => {
            // 实现图片懒加载
            const images = document.querySelectorAll('img[data-src]');
            images.forEach(img => {
                img.src = img.dataset.src;
            });
        },
        '预计减少初始加载时间30%'
    );
    
    pipeline.registerOptimization(
        '代码分割',
        async () => {
            // 实现代码分割
            // 这里只是示例,实际需要配置webpack
            console.log('应用代码分割...');
        },
        '预计减少JavaScript大小40%'
    );
    
    pipeline.registerOptimization(
        '启用Gzip压缩',
        async () => {
            // 这需要服务端配置,这里只是示例
            console.log('启用Gzip压缩...');
        },
        '预计减少传输大小60%'
    );
    
    // 逐个应用优化
    await pipeline.applyOptimization('图片懒加载');
    await pipeline.applyOptimization('代码分割');
    await pipeline.applyOptimization('启用Gzip压缩');
    
    // 打印完整报告
    pipeline.printFullReport();
});

总结与最佳实践

性能优化核心原则



// ========== JavaScript性能优化最佳实践总结 ==========
 
const PERFORMANCE_BEST_PRACTICES = {
    // 1. 测量优先
    measurement: {
        principle: "先测量,再优化",
        practices: [
            "使用Performance API测量关键指标",
            "设置性能基线",
            "持续监控Core Web Vitals",
            "使用Lighthouse进行定期审计",
            "建立性能预算"
        ],
        tools: [
            "Chrome DevTools Performance",
            "Lighthouse",
            "WebPageTest",
            "Performance Observer API",
            "Real User Monitoring (RUM)"
        ]
    },
    
    // 2. 代码优化
    codeOptimization: {
        principle: "写高效的代码",
        practices: [
            "选择合适的算法和数据结构",
            "避免不必要的循环和计算",
            "使用函数缓存(memoization)",
            "实施防抖和节流",
            "避免内存泄漏"
        ],
        antiPatterns: [
            "过早优化",
            "忽略可读性",
            "过度优化微小细节",
            "不测量就优化"
        ]
    },
    
    // 3. DOM优化
    domOptimization: {
        principle: "最小化DOM操作",
        practices: [
            "批量DOM操作",
            "使用DocumentFragment",
            "避免强制同步布局",
            "使用事件委托",
            "实施虚拟滚动"
        ],
        cssOptimization: [
            "使用transform代替position",
            "使用opacity代替visibility",
            "避免复杂的CSS选择器",
            "使用will-change提示浏览器"
        ]
    },
    
    // 4. 资源优化
    resourceOptimization: {
        principle: "减少资源大小和数量",
        practices: [
            "代码分割和懒加载",
            "Tree Shaking移除未使用代码",
            "压缩JavaScript、CSS和图片",
            "使用现代图片格式(WebP、AVIF)",
            "实施资源缓存策略"
        ],
        loading: [
            "关键资源预加载",
            "非关键资源延迟加载",
            "使用CDN加速",
            "启用HTTP/2或HTTP/3",
            "实施Service Worker缓存"
        ]
    },
    
    // 5. 渲染优化
    renderingOptimization: {
        principle: "优化渲染性能",
        practices: [
            "减少重排和重绘",
            "使用CSS动画代替JavaScript动画",
            "启用GPU加速",
            "使用requestAnimationFrame",
            "实施离屏渲染"
        ],
        frameworks: {
            react: [
                "使用React.memo避免不必要渲染",
                "使用useMemo和useCallback",
                "实施代码分割",
                "使用虚拟滚动",
                "优化列表渲染的key"
            ],
            vue: [
                "使用shallowRef和shallowReactive",
                "使用computed缓存计算",
                "使用v-once和v-memo",
                "实施异步组件",
                "使用KeepAlive缓存组件"
            ]
        }
    },
    
    // 6. 网络优化
    networkOptimization: {
        principle: "减少网络延迟",
        practices: [
            "请求合并和批处理",
            "实施HTTP缓存",
            "使用预连接和DNS预解析",
            "启用压缩(Gzip/Brotli)",
            "优化API响应大小"
        ],
        strategies: [
            "使用CDN",
            "实施智能CDN选择",
            "优化首屏加载",
            "实施渐进式渲染",
            "使用Service Worker离线缓存"
        ]
    },
    
    // 7. 监控与持续优化
    monitoring: {
        principle: "持续监控和优化",
        practices: [
            "实施性能监控系统",
            "设置性能预算",
            "建立持续优化流程",
            "定期性能审计",
            "A/B测试优化效果"
        ],
        metrics: [
            "TTFB (Time to First Byte)",
            "FCP (First Contentful Paint)",
            "LCP (Largest Contentful Paint)",
            "FID (First Input Delay)",
            "CLS (Cumulative Layout Shift)",
            "TTI (Time to Interactive)"
        ]
    }
};
 
// 打印最佳实践总结
console.log('📚 JavaScript性能优化最佳实践');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
 
Object.entries(PERFORMANCE_BEST_PRACTICES).forEach(([category, data]) => {
    console.log(`
${category.toUpperCase()}`);
    console.log(`原则: ${data.principle}`);
    console.log('实践:');
    data.practices.forEach((practice, index) => {
        console.log(`  ${index + 1}. ${practice}`);
    });
});
 
console.log('
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('记住:性能优化是一个持续的过程,不是一次性的任务!');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');

性能优化检查清单



// ========== 性能优化检查清单 ==========
 
const PERFORMANCE_CHECKLIST = {
    // 初始加载
    initialLoad: {
        category: "初始加载优化",
        items: [
            { task: "实施代码分割", priority: "高", status: "pending" },
            { task: "启用Tree Shaking", priority: "高", status: "pending" },
            { task: "压缩JavaScript和CSS", priority: "高", status: "pending" },
            { task: "优化图片(WebP、压缩)", priority: "高", status: "pending" },
            { task: "实施懒加载", priority: "中", status: "pending" },
            { task: "使用CDN", priority: "中", status: "pending" },
            { task: "启用Gzip/Brotli压缩", priority: "高", status: "pending" },
            { task: "实施HTTP缓存", priority: "高", status: "pending" }
        ]
    },
    
    // 运行时性能
    runtime: {
        category: "运行时性能优化",
        items: [
            { task: "优化循环和算法", priority: "中", status: "pending" },
            { task: "实施函数缓存", priority: "中", status: "pending" },
            { task: "使用防抖和节流", priority: "高", status: "pending" },
            { task: "避免内存泄漏", priority: "高", status: "pending" },
            { task: "优化事件处理", priority: "中", status: "pending" },
            { task: "使用Web Worker", priority: "低", status: "pending" }
        ]
    },
    
    // 渲染性能
    rendering: {
        category: "渲染性能优化",
        items: [
            { task: "减少DOM操作", priority: "高", status: "pending" },
            { task: "避免强制同步布局", priority: "高", status: "pending" },
            { task: "使用CSS动画", priority: "中", status: "pending" },
            { task: "启用GPU加速", priority: "中", status: "pending" },
            { task: "实施虚拟滚动", priority: "中", status: "pending" },
            { task: "优化CSS选择器", priority: "低", status: "pending" }
        ]
    },
    
    // 网络性能
    network: {
        category: "网络性能优化",
        items: [
            { task: "请求合并", priority: "中", status: "pending" },
            { task: "实施预加载", priority: "中", status: "pending" },
            { task: "使用Service Worker", priority: "低", status: "pending" },
            { task: "优化API响应", priority: "高", status: "pending" },
            { task: "实施请求缓存", priority: "高", status: "pending" }
        ]
    },
    
    // 监控
    monitoring: {
        category: "性能监控",
        items: [
            { task: "设置性能监控", priority: "高", status: "pending" },
            { task: "建立性能预算", priority: "高", status: "pending" },
            { task: "实施错误监控", priority: "高", status: "pending" },
            { task: "定期性能审计", priority: "中", status: "pending" }
        ]
    }
};
 
// 打印检查清单
function printChecklist() {
    console.log('✅ JavaScript性能优化检查清单');
    console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
    
    Object.values(PERFORMANCE_CHECKLIST).forEach(section => {
        console.log(`
📋 ${section.category}`);
        section.items.forEach((item, index) => {
            const icon = item.status === 'done' ? '✅' : '⬜';
            const priority = {
                '高': '🔴',
                '中': '🟡',
                '低': '🟢'
            }[item.priority];
            
            console.log(`${icon} ${index + 1}. ${item.task} ${priority}`);
        });
    });
    
    console.log('
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
}
 
printChecklist();

结语

性能优化是一个持续的过程,需要:

测量优先 – 先测量,再优化,用数据说话用户体验 – 始终以用户体验为中心平衡取舍 – 在性能、可维护性和开发效率之间找到平衡持续监控 – 建立监控系统,及时发现性能问题团队协作 – 性能优化需要整个团队的共同努力

记住:过早优化是万恶之源,但忽视性能同样危险。在正确的时机做正确的优化,才是最佳实践。


相关资源:

Web.dev – PerformanceMDN – PerformanceChrome DevTools – PerformanceLighthouseWebPageTest


💡 提示: 本文涵盖了JavaScript性能优化的方方面面,建议收藏后分章节学习,并在实际项目中逐步应用这些优化技巧。

© 版权声明

相关文章

暂无评论

none
暂无评论...