Greasy Fork

Greasy Fork is available in English.

Ultimate Web Optimizer

全面的网页性能优化方案- 懒加载/预加载/预连接/布局优化

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Ultimate Web Optimizer
// @namespace    http://greasyfork.icu/zh-CN/users/1474228-moyu001
// @version      2.1
// @description  全面的网页性能优化方案- 懒加载/预加载/预连接/布局优化
// @author       moyu001
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_log
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ========================
    // 工具函数 - 提前定义
    // ========================

    /**
     * 防抖函数
     * @param {Function} fn 要防抖的函数
     * @param {number} delay 延迟时间
     * @returns {Function} 防抖后的函数
     */
    function debounce(fn, delay) {
        let timer = null;
        return function(...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    }

    /**
     * 节流函数
     * @param {Function} func 要节流的函数
     * @param {number} limit 限制时间
     * @returns {Function} 节流后的函数
     */
    function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
            if (!inThrottle) {
                func.apply(this, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    /**
     * 安全的 URL 解析
     * @param {string} url URL 字符串
     * @param {string} base 基准 URL
     * @returns {URL|null} URL 对象或 null
     */
    function safeParseURL(url, base) {
        try {
            return new URL(url, base);
        } catch {
            return null;
        }
    }

    /**
     * 检查元素是否可见
     * @param {Element} element 要检查的元素
     * @returns {boolean} 是否可见
     */
    function isElementVisible(element) {
        if (!element) return false;
        const style = window.getComputedStyle(element);
        return style.display !== 'none' &&
               style.visibility !== 'hidden' &&
               style.opacity !== '0';
    }

    /**
     * 深度合并对象
     * @param {Object} target 目标对象
     * @param {Object} source 源对象
     * @returns {Object} 合并后的对象
     */
    function deepMerge(target, source) {
        const result = { ...target };

        for (const key in source) {
            if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
                result[key] = deepMerge(result[key] || {}, source[key]);
            } else {
                result[key] = source[key];
            }
        }

        return result;
    }

    /**
     * 检查是否为 HTML 图片元素 - 增强类型检查
     * @param {Node} node DOM 节点
     * @returns {boolean} 是否为图片元素
     */
    function isImageElement(node) {
        return node instanceof HTMLImageElement;
    }

    /**
     * 延迟函数
     * @param {number} ms 延迟毫秒数
     * @returns {Promise} Promise 对象
     */
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * 简单的 LRU 缓存实现
     */
    class LRUCache {
        constructor(maxSize = 100) {
            this.maxSize = maxSize;
            this.cache = new Map();
        }

        get(key) {
            if (this.cache.has(key)) {
                const value = this.cache.get(key);
                this.cache.delete(key);
                this.cache.set(key, value);
                return value;
            }
            return null;
        }

        set(key, value) {
            if (this.cache.has(key)) {
                this.cache.delete(key);
            } else if (this.cache.size >= this.maxSize) {
                const firstKey = this.cache.keys().next().value;
                this.cache.delete(firstKey);
            }
            this.cache.set(key, value);
        }

        has(key) {
            return this.cache.has(key);
        }

        clear() {
            this.cache.clear();
        }

        get size() {
            return this.cache.size;
        }
    }

    /**
     * 重试操作工具类 - 新增错误重试机制
     */
    class RetryableOperation {
        /**
         * 执行带重试的操作
         * @param {Function} operation 要执行的操作
         * @param {number} maxRetries 最大重试次数
         * @param {number} baseDelay 基础延迟时间
         * @returns {Promise} 操作结果
         */
        static async executeWithRetry(operation, maxRetries = 3, baseDelay = 1000) {
            for (let i = 0; i < maxRetries; i++) {
                try {
                    return await operation();
                } catch (e) {
                    if (i === maxRetries - 1) throw e;
                    await delay(baseDelay * (i + 1));
                }
            }
        }
    }

    /**
     * 性能监控器
     */
    class PerformanceMonitor {
        constructor(debug = false) {
            this.debug = debug;
            this.metrics = new Map();
            this.counters = new Map();
        }

        start(name) {
            if (this.debug) {
                this.metrics.set(name, performance.now());
            }
        }

        end(name) {
            if (this.debug && this.metrics.has(name)) {
                const duration = performance.now() - this.metrics.get(name);
                console.log(`[性能] ${name}: ${duration.toFixed(2)}ms`);
                this.metrics.delete(name);
                return duration;
            }
            return 0;
        }

        count(name) {
            if (this.debug) {
                this.counters.set(name, (this.counters.get(name) || 0) + 1);
            }
        }

        getCounter(name) {
            return this.counters.get(name) || 0;
        }

        profile(name, fn) {
            if (!this.debug) return fn();

            const start = performance.now();
            const result = fn();
            const end = performance.now();
            console.log(`[性能] ${name}: ${(end - start).toFixed(2)}ms`);
            return result;
        }

        log(message, ...args) {
            if (this.debug) {
                console.log(`[优化器] ${message}`, ...args);
            }
        }

        warn(message, ...args) {
            if (this.debug) {
                console.warn(`[优化器] ${message}`, ...args);
            }
        }

        error(message, ...args) {
            if (this.debug) {
                console.error(`[优化器] ${message}`, ...args);
            }
        }
    }

    // ========================
    // 配置管理系统
    // ========================

    /**
     * 配置管理器 - 使用深度合并
     */
    class ConfigManager {
        constructor() {
            this.defaultConfig = {
                debug: false,

                // 全局黑名单
                globalBlacklist: [
                    // 可以添加需要完全跳过优化的域名
                ],

                // 懒加载配置
                lazyLoad: {
                    enabled: true,
                    minSize: 100,
                    rootMargin: '200px',
                    threshold: 0.01,
                    skipHidden: true,
                    batchSize: 32,
                    blacklist: []
                },

                // 预连接配置
                preconnect: {
                    enabled: true,
                    maxConnections: 5,
                    whitelist: [
                        // CDN 和字体服务
                        'fonts.gstatic.com',
                        'fonts.googleapis.com',
                        'fonts.googleapis.cn',
                        'fonts.loli.net',

                        // 常用 CDN
                        'cdnjs.cloudflare.com',
                        'cdn.jsdelivr.net',
                        'unpkg.com',
                        'cdn.bootcdn.net',
                        'cdn.bootcss.com',
                        'libs.baidu.com',
                        'cdn.staticfile.org',

                        // 其他常用服务
                        'ajax.googleapis.com',
                        'code.jquery.com',
                        'maxcdn.bootstrapcdn.com',
                        'kit.fontawesome.com',
                        'lf3-cdn-tos.bytecdntp.com',
                        'unpkg.zhimg.com',
                        'npm.elemecdn.com',
                        'g.alicdn.com'
                    ],
                    blacklist: []
                },

                // 预加载配置
                preload: {
                    enabled: true,
                    maxPreloads: 5,
                    types: ['css', 'js', 'woff2', 'woff'],
                    fetchTimeout: 5000,
                    retryAttempts: 3,
                    blacklist: []
                },

                // 布局稳定性配置
                layout: {
                    enabled: true,
                    stableImages: true,
                    stableIframes: true,
                    blacklist: []
                }
            };

            this.config = this.loadConfig();
            this.validateConfig();
        }

        loadConfig() {
            try {
                const saved = GM_getValue('optimizer_config_v2', null);
                if (saved) {
                    // 使用深度合并替代浅合并
                    return deepMerge(this.defaultConfig, JSON.parse(saved));
                }
            } catch (e) {
                console.warn('[配置] 加载用户配置失败,使用默认配置', e);
            }
            return deepMerge({}, this.defaultConfig);
        }

        saveConfig() {
            try {
                GM_setValue('optimizer_config_v2', JSON.stringify(this.config));
            } catch (e) {
                console.warn('[配置] 保存配置失败', e);
            }
        }

        validateConfig() {
            // 基本类型验证
            if (typeof this.config.debug !== 'boolean') {
                this.config.debug = this.defaultConfig.debug;
            }

            // 确保数组类型配置正确
            ['globalBlacklist'].forEach(key => {
                if (!Array.isArray(this.config[key])) {
                    this.config[key] = [...this.defaultConfig[key]];
                }
            });

            // 验证子配置
            ['lazyLoad', 'preconnect', 'preload', 'layout'].forEach(module => {
                if (!this.config[module] || typeof this.config[module] !== 'object') {
                    this.config[module] = deepMerge({}, this.defaultConfig[module]);
                }
            });
        }

        get(path) {
            const keys = path.split('.');
            let value = this.config;
            for (const key of keys) {
                value = value?.[key];
                if (value === undefined) break;
            }
            return value;
        }

        set(path, value) {
            const keys = path.split('.');
            const lastKey = keys.pop();
            let target = this.config;

            for (const key of keys) {
                if (!target[key] || typeof target[key] !== 'object') {
                    target[key] = {};
                }
                target = target[key];
            }

            target[lastKey] = value;
            this.saveConfig();
        }

        isBlacklisted(hostname, module = null) {
            // 检查全局黑名单
            if (this.config.globalBlacklist.some(domain => hostname.includes(domain))) {
                return true;
            }

            // 检查模块特定黑名单
            if (module && this.config[module]?.blacklist) {
                return this.config[module].blacklist.some(domain => hostname.includes(domain));
            }

            return false;
        }
    }

    // ========================
    // 核心优化模块
    // ========================

    /**
     * 懒加载管理器 - 增强类型检查
     */
    class LazyLoadManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.observer = null;
            this.mutationObserver = null;
            this.processedImages = new Set();
            this.pendingImages = [];
            this.batchScheduled = false;
            this.processedElements = new WeakSet(); // 避免重复处理
        }

        init() {
            if (!this.config.get('lazyLoad.enabled')) {
                this.monitor.log('懒加载功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'lazyLoad')) {
                this.monitor.log('当前站点在懒加载黑名单中');
                return;
            }

            this.monitor.start('lazyLoad-init');
            this.setupIntersectionObserver();
            this.processExistingImages();
            this.setupMutationObserver();
            this.monitor.end('lazyLoad-init');
        }

        setupIntersectionObserver() {
            if (!('IntersectionObserver' in window)) {
                this.monitor.warn('浏览器不支持 IntersectionObserver,使用兼容模式');
                this.setupFallbackMode();
                return;
            }

            this.observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        this.restoreImage(entry.target);
                        this.observer.unobserve(entry.target);
                        this.monitor.count('lazy-loaded-images');
                    }
                });
            }, {
                rootMargin: this.config.get('lazyLoad.rootMargin'),
                threshold: this.config.get('lazyLoad.threshold')
            });
        }

        setupFallbackMode() {
            const checkVisible = throttle(() => {
                const images = document.querySelectorAll('img[data-lazy-src]');
                const margin = parseInt(this.config.get('lazyLoad.rootMargin')) || 200;

                images.forEach(img => {
                    const rect = img.getBoundingClientRect();
                    if (rect.top < window.innerHeight + margin) {
                        this.restoreImage(img);
                    }
                });
            }, 200);

            window.addEventListener('scroll', checkVisible, { passive: true });
            window.addEventListener('resize', checkVisible, { passive: true });
            checkVisible();
        }

        isLazyCandidate(img) {
            // 基本检查 - 使用更严格的类型检查
            if (!isImageElement(img)) return false;
            if (this.processedElements.has(img)) return false;
            if (img.hasAttribute('data-lazy-processed')) return false;
            if (img.loading === 'eager') return false;
            if (img.complete && img.src) return false;
            if (img.src && img.src.startsWith('data:')) return false;

            // 跳过已有懒加载的图片
            if (img.hasAttribute('data-src') || img.hasAttribute('data-srcset')) return false;

            // 尺寸检查
            const minSize = this.config.get('lazyLoad.minSize');
            const rect = img.getBoundingClientRect();
            if (rect.width < minSize || rect.height < minSize) return false;

            // 可见性检查
            if (this.config.get('lazyLoad.skipHidden') && !isElementVisible(img)) {
                return false;
            }

            return true;
        }

        processImage(img) {
            if (!this.isLazyCandidate(img)) return false;

            // 标记为已处理
            this.processedElements.add(img);
            img.setAttribute('data-lazy-processed', 'true');

            // 设置原生懒加载(如果支持)
            if ('loading' in HTMLImageElement.prototype) {
                img.loading = 'lazy';
            }

            // 保存原始 src
            if (img.src) {
                img.setAttribute('data-lazy-src', img.src);
                img.removeAttribute('src');
            }
            if (img.srcset) {
                img.setAttribute('data-lazy-srcset', img.srcset);
                img.removeAttribute('srcset');
            }

            // 添加到观察者
            if (this.observer) {
                this.observer.observe(img);
            }

            this.processedImages.add(img);
            this.monitor.count('processed-images');
            return true;
        }

        restoreImage(img) {
            const src = img.getAttribute('data-lazy-src');
            const srcset = img.getAttribute('data-lazy-srcset');

            if (src) {
                img.src = src;
                img.removeAttribute('data-lazy-src');
            }
            if (srcset) {
                img.srcset = srcset;
                img.removeAttribute('data-lazy-srcset');
            }

            this.processedImages.delete(img);
        }

        batchProcess(images) {
            const batchSize = this.config.get('lazyLoad.batchSize');
            let processed = 0;

            const processBatch = () => {
                const end = Math.min(processed + batchSize, images.length);

                for (let i = processed; i < end; i++) {
                    this.processImage(images[i]);
                }

                processed = end;

                if (processed < images.length) {
                    (window.requestIdleCallback || window.requestAnimationFrame)(processBatch);
                } else {
                    this.monitor.log(`懒加载处理完成,共处理 ${processed} 张图片`);
                }
            };

            processBatch();
        }

        processExistingImages() {
            const images = Array.from(document.querySelectorAll('img'));
            this.monitor.log(`发现 ${images.length} 张图片,开始批量处理`);
            this.batchProcess(images);
        }

        // 改进的批处理调度 - 更好的并发控制
        scheduleBatchProcess() {
            if (this.batchScheduled || this.pendingImages.length === 0) return;

            this.batchScheduled = true;
            (window.requestIdleCallback || window.requestAnimationFrame)(() => {
                const images = [...this.pendingImages];
                this.pendingImages = [];
                this.batchScheduled = false;

                let processedCount = 0;
                images.forEach(img => {
                    if (this.processImage(img)) {
                        processedCount++;
                    }
                });

                if (processedCount > 0) {
                    this.monitor.log(`动态处理 ${processedCount} 张新图片`);
                }
            });
        }

        setupMutationObserver() {
            let pendingMutations = [];
            let processingScheduled = false;

            const processMutations = () => {
                const mutations = [...pendingMutations];
                pendingMutations = [];
                processingScheduled = false;

                mutations.forEach(mutation => {
                    // 处理新增节点
                    mutation.addedNodes.forEach(node => {
                        if (isImageElement(node)) {
                            this.pendingImages.push(node);
                        } else if (node.querySelectorAll) {
                            const images = node.querySelectorAll('img');
                            this.pendingImages.push(...Array.from(images));
                        }
                    });

                    // 清理移除的节点
                    mutation.removedNodes.forEach(node => {
                        if (isImageElement(node) && this.observer) {
                            this.observer.unobserve(node);
                            this.processedImages.delete(node);
                            this.processedElements.delete && this.processedElements.delete(node);
                        }
                    });
                });

                this.scheduleBatchProcess();
            };

            this.mutationObserver = new MutationObserver((mutations) => {
                pendingMutations.push(...mutations);

                if (!processingScheduled) {
                    processingScheduled = true;
                    (window.requestIdleCallback || window.requestAnimationFrame)(processMutations);
                }
            });

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.observer) {
                this.observer.disconnect();
                this.observer = null;
            }
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }

            // 恢复所有处理过的图片
            this.processedImages.forEach(img => this.restoreImage(img));
            this.processedImages.clear();
        }
    }

    /**
     * 预加载管理器 - 改进异步处理
     */
    class PreloadManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.preloaded = new LRUCache(this.config.get('preload.maxPreloads'));
            this.cssCache = new LRUCache(50);
            this.mutationObserver = null;
        }

        async init() {
            if (!this.config.get('preload.enabled')) {
                this.monitor.log('预加载功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'preload')) {
                this.monitor.log('当前站点在预加载黑名单中');
                return;
            }

            this.monitor.start('preload-init');
            await this.scanExistingResources(); // 改为异步
            this.setupMutationObserver();
            this.monitor.end('preload-init');
        }

        getResourceType(url) {
            const ext = url.split('.').pop()?.toLowerCase();
            const types = this.config.get('preload.types');

            if (!types.includes(ext)) return null;

            switch (ext) {
                case 'css': return 'style';
                case 'js': return 'script';
                case 'woff':
                case 'woff2':
                case 'ttf':
                case 'otf': return 'font';
                default: return null;
            }
        }

        doPreload(url, asType) {
            if (this.preloaded.has(url) || this.preloaded.size >= this.config.get('preload.maxPreloads')) {
                return false;
            }

            try {
                const link = document.createElement('link');
                link.rel = 'preload';
                link.as = asType;
                link.href = url;

                if (asType === 'font') {
                    link.crossOrigin = 'anonymous';
                    // 设置正确的 MIME 类型
                    if (url.includes('.woff2')) link.type = 'font/woff2';
                    else if (url.includes('.woff')) link.type = 'font/woff';
                    else if (url.includes('.ttf')) link.type = 'font/ttf';
                    else if (url.includes('.otf')) link.type = 'font/otf';
                }

                document.head.appendChild(link);
                this.preloaded.set(url, true);
                this.monitor.log(`预加载 ${asType}: ${url}`);
                this.monitor.count('preloaded-resources');
                return true;
            } catch (e) {
                this.monitor.warn(`预加载失败: ${url}`, e);
                return false;
            }
        }

        async extractFontsFromCSS(cssUrl) {
            if (this.cssCache.has(cssUrl)) {
                return this.cssCache.get(cssUrl);
            }

            const operation = async () => {
                const controller = new AbortController();
                const timeoutId = setTimeout(() => controller.abort(), this.config.get('preload.fetchTimeout'));

                try {
                    const response = await fetch(cssUrl, {
                        signal: controller.signal,
                        mode: 'cors',
                        credentials: 'omit'
                    });

                    clearTimeout(timeoutId);

                    if (!response.ok) throw new Error(`HTTP ${response.status}`);

                    const text = await response.text();
                    const fontUrls = [];
                    const fontRegex = /url\(["']?([^")']+\.(woff2?|ttf|otf))["']?\)/gi;
                    let match;

                    while ((match = fontRegex.exec(text)) !== null) {
                        const fontUrl = safeParseURL(match[1], cssUrl);
                        if (fontUrl) {
                            fontUrls.push(fontUrl.href);
                        }
                    }

                    this.cssCache.set(cssUrl, fontUrls);
                    return fontUrls;
                } finally {
                    clearTimeout(timeoutId);
                }
            };

            try {
                // 使用重试机制
                return await RetryableOperation.executeWithRetry(
                    operation,
                    this.config.get('preload.retryAttempts')
                );
            } catch (e) {
                this.monitor.warn(`提取字体失败: ${cssUrl}`, e.message);
                this.cssCache.set(cssUrl, []);
                return [];
            }
        }

        // 改进的异步资源扫描 - 更好的并发控制
        async scanExistingResources() {
            // 处理 CSS 文件
            const cssLinks = Array.from(document.querySelectorAll('link[rel="stylesheet"][href]'));
            const jsScripts = Array.from(document.querySelectorAll('script[src]'));

            // 处理 CSS 文件的 Promise 数组
            const cssPromises = cssLinks.map(async link => {
                const cssUrl = link.href;
                const asType = this.getResourceType(cssUrl);

                if (asType === 'style') {
                    this.doPreload(cssUrl, asType);

                    // 异步提取和预加载字体
                    try {
                        const fontUrls = await this.extractFontsFromCSS(cssUrl);
                        fontUrls.forEach(fontUrl => {
                            const fontType = this.getResourceType(fontUrl);
                            if (fontType === 'font') {
                                this.doPreload(fontUrl, fontType);
                            }
                        });
                    } catch (e) {
                        // 忽略字体提取错误,不影响主流程
                        this.monitor.warn(`CSS处理失败: ${cssUrl}`, e);
                    }
                }
            });

            // 处理 JS 文件
            jsScripts.forEach(script => {
                const asType = this.getResourceType(script.src);
                if (asType === 'script') {
                    this.doPreload(script.src, asType);
                }
            });

            // 等待所有 CSS 处理完成,但不阻塞初始化
            try {
                await Promise.allSettled(cssPromises);
                this.monitor.log(`资源扫描完成,处理了 ${cssLinks.length} 个CSS文件和 ${jsScripts.length} 个JS文件`);
            } catch (e) {
                this.monitor.warn('资源扫描过程中出现错误', e);
            }
        }

        setupMutationObserver() {
            this.mutationObserver = new MutationObserver(debounce(async (mutations) => {
                const newCSSLinks = [];
                const newJSScripts = [];

                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.tagName === 'LINK' && node.rel === 'stylesheet' && node.href) {
                            newCSSLinks.push(node);
                        } else if (node.tagName === 'SCRIPT' && node.src) {
                            newJSScripts.push(node);
                        }
                    });
                });

                // 异步处理新添加的资源
                if (newCSSLinks.length > 0 || newJSScripts.length > 0) {
                    const promises = newCSSLinks.map(async node => {
                        const asType = this.getResourceType(node.href);
                        if (asType === 'style') {
                            this.doPreload(node.href, asType);

                            // 异步处理字体
                            try {
                                const fontUrls = await this.extractFontsFromCSS(node.href);
                                fontUrls.forEach(fontUrl => {
                                    const fontType = this.getResourceType(fontUrl);
                                    if (fontType === 'font') {
                                        this.doPreload(fontUrl, fontType);
                                    }
                                });
                            } catch (e) {
                                // 忽略错误
                            }
                        }
                    });

                    newJSScripts.forEach(node => {
                        const asType = this.getResourceType(node.src);
                        if (asType === 'script') {
                            this.doPreload(node.src, asType);
                        }
                    });

                    // 不等待 Promise 完成,避免阻塞
                    Promise.allSettled(promises).then(() => {
                        this.monitor.log(`动态处理了 ${newCSSLinks.length} 个CSS和 ${newJSScripts.length} 个JS`);
                    });
                }
            }, 200));

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }
            this.preloaded.clear();
            this.cssCache.clear();
        }
    }

    // 其他管理器类保持不变,仅引用已改进的配置和监控器
    class PreconnectManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.connected = new LRUCache(this.config.get('preconnect.maxConnections'));
            this.mutationObserver = null;
        }

        init() {
            if (!this.config.get('preconnect.enabled')) {
                this.monitor.log('预连接功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'preconnect')) {
                this.monitor.log('当前站点在预连接黑名单中');
                return;
            }

            this.monitor.start('preconnect-init');
            this.scanExistingResources();
            this.setupMutationObserver();
            this.monitor.end('preconnect-init');
        }

        shouldPreconnect(hostname) {
            if (!hostname || hostname === location.hostname) return false;
            if (this.connected.has(hostname)) return false;

            const whitelist = this.config.get('preconnect.whitelist');
            return whitelist.some(domain => hostname.endsWith(domain));
        }

        doPreconnect(hostname) {
            if (!this.shouldPreconnect(hostname)) return false;

            try {
                const link = document.createElement('link');
                link.rel = 'preconnect';
                link.href = `https://${hostname}`;
                link.crossOrigin = 'anonymous';
                document.head.appendChild(link);

                this.connected.set(hostname, true);
                this.monitor.log(`预连接: ${hostname}`);
                this.monitor.count('preconnected-domains');
                return true;
            } catch (e) {
                this.monitor.warn(`预连接失败: ${hostname}`, e);
                return false;
            }
        }

        extractHostnames(elements) {
            const hostnames = new Set();

            elements.forEach(el => {
                const url = safeParseURL(el.src || el.href);
                if (url && url.hostname !== location.hostname) {
                    hostnames.add(url.hostname);
                }
            });

            return Array.from(hostnames);
        }

        scanExistingResources() {
            const selectors = [
                'script[src]',
                'link[href]',
                'img[src]',
                'audio[src]',
                'video[src]',
                'source[src]'
            ];

            const elements = document.querySelectorAll(selectors.join(','));
            const hostnames = this.extractHostnames(elements);

            let connected = 0;
            hostnames.forEach(hostname => {
                if (this.doPreconnect(hostname)) {
                    connected++;
                }
            });

            this.monitor.log(`扫描完成,预连接 ${connected} 个域名`);
        }

        setupMutationObserver() {
            this.mutationObserver = new MutationObserver(debounce((mutations) => {
                const newElements = [];

                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.src || node.href) {
                            newElements.push(node);
                        } else if (node.querySelectorAll) {
                            const elements = node.querySelectorAll('script[src], link[href], img[src]');
                            newElements.push(...elements);
                        }
                    });
                });

                if (newElements.length > 0) {
                    const hostnames = this.extractHostnames(newElements);
                    hostnames.forEach(hostname => this.doPreconnect(hostname));
                }
            }, 200));

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }
            this.connected.clear();
        }
    }

    class LayoutStabilizer {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.injectedStyle = null;
        }

        init() {
            if (!this.config.get('layout.enabled')) {
                this.monitor.log('布局优化功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'layout')) {
                this.monitor.log('当前站点在布局优化黑名单中');
                return;
            }

            this.monitor.start('layout-init');
            this.injectStabilizationStyles();
            this.monitor.end('layout-init');
        }

        generateCSS() {
            const styles = [];

            if (this.config.get('layout.stableImages')) {
                styles.push(`
                    /* 图片布局稳定性优化 */
                    img:not([width]):not([height]):not([style*="width"]):not([style*="height"]) {
                        min-height: 1px;
                        // max-width: 100%;
                        // height: auto;
                    }

                    /* 现代浏览器的 aspect-ratio 支持 */
                    @supports (aspect-ratio: 1/1) {
                        img[width][height]:not([style*="aspect-ratio"]) {
                            aspect-ratio: attr(width) / attr(height);
                        }
                    }
                `);
            }

            if (this.config.get('layout.stableIframes')) {
                styles.push(`
                    /* iframe 布局稳定性优化 */
                    iframe:not([width]):not([height]):not([style*="width"]):not([style*="height"]) {
                        // width: 100%;
                        // height: auto;
                        min-height: 1px;
                    }

                    @supports (aspect-ratio: 16/9) {
                        iframe:not([style*="aspect-ratio"]) {
                            aspect-ratio: 16/9;
                        }
                    }
                `);
            }

            return styles.join('\n');
        }

        injectStabilizationStyles() {
            const css = this.generateCSS().trim();
            if (!css) return;

            try {
                this.injectedStyle = document.createElement('style');
                this.injectedStyle.setAttribute('data-optimizer', 'layout-stabilizer');
                this.injectedStyle.textContent = css;

                // 优先插入到 head,如果不存在则插入到 document
                const target = document.head || document.documentElement;
                target.appendChild(this.injectedStyle);

                this.monitor.log('布局稳定性样式已注入');
            } catch (e) {
                this.monitor.warn('注入布局样式失败', e);
            }
        }

        destroy() {
            if (this.injectedStyle && this.injectedStyle.parentNode) {
                this.injectedStyle.parentNode.removeChild(this.injectedStyle);
                this.injectedStyle = null;
                this.monitor.log('布局样式已移除');
            }
        }
    }

    // ========================
    // 主优化器
    // ========================

    /**
     * 主优化器类 - v2.0
     */
    class WebOptimizer {
        constructor() {
            this.config = new ConfigManager();
            this.monitor = new PerformanceMonitor(this.config.get('debug'));

            // 优化模块
            this.modules = {
                lazyLoad: new LazyLoadManager(this.config, this.monitor),
                preconnect: new PreconnectManager(this.config, this.monitor),
                preload: new PreloadManager(this.config, this.monitor),
                layout: new LayoutStabilizer(this.config, this.monitor)
            };

            this.initialized = false;
            this.cleanupTasks = [];
        }

        async init() {
            if (this.initialized) return;

            this.monitor.start('total-init');
            this.monitor.log('Web Optimizer Enhanced v2.0 开始初始化');

            // 检查全局黑名单
            if (this.config.isBlacklisted(location.hostname)) {
                this.monitor.log('当前站点在全局黑名单中,跳过所有优化');
                return;
            }

            try {
                // 等待 DOM 基本可用
                if (document.readyState === 'loading') {
                    await new Promise(resolve => {
                        document.addEventListener('DOMContentLoaded', resolve, { once: true });
                    });
                }

                // 初始化各个模块 - 改进的错误隔离
                const initPromises = Object.entries(this.modules).map(async ([name, module]) => {
                    try {
                        this.monitor.start(`init-${name}`);
                        await module.init();
                        this.monitor.end(`init-${name}`);
                        return { name, success: true };
                    } catch (e) {
                        this.monitor.error(`模块 ${name} 初始化失败`, e);
                        return { name, success: false, error: e };
                    }
                });

                const results = await Promise.allSettled(initPromises);
                const successCount = results.filter(r => r.status === 'fulfilled' && r.value.success).length;
                this.monitor.log(`模块初始化完成,成功: ${successCount}/${Object.keys(this.modules).length}`);

                // 设置清理任务
                this.setupCleanupTasks();

                this.initialized = true;
                this.monitor.end('total-init');
                this.monitor.log('Web Optimizer Enhanced v2.0 初始化完成');

                // 显示初始化报告
                this.showInitReport();

            } catch (e) {
                this.monitor.error('初始化失败', e);
            }
        }

        setupCleanupTasks() {
            // 定期清理缓存
            const cleanupInterval = setInterval(() => {
                Object.values(this.modules).forEach(module => {
                    if (module.cssCache) module.cssCache.clear();
                    if (module.connected) module.connected.clear();
                    if (module.preloaded) module.preloaded.clear();
                });
                this.monitor.log('定期清理完成');
            }, 10 * 60 * 1000); // 10分钟

            this.cleanupTasks.push(() => clearInterval(cleanupInterval));

            // 页面卸载时清理
            const cleanup = () => {
                this.destroy();
            };

            window.addEventListener('beforeunload', cleanup);
            this.cleanupTasks.push(() => {
                window.removeEventListener('beforeunload', cleanup);
            });
        }

        showInitReport() {
            if (!this.config.get('debug')) return;

            console.groupCollapsed('[Web Optimizer Enhanced v2.0] 初始化报告');
            console.log('版本: 2.0');
            console.log('当前域名:', location.hostname);
            console.log('启用的功能:', Object.entries(this.config.config)
                .filter(([key, value]) => typeof value === 'object' && value.enabled)
                .map(([key]) => key)
            );

            // 显示性能计数器
            console.log('性能计数:', {
                'processed-images': this.monitor.getCounter('processed-images'),
                'lazy-loaded-images': this.monitor.getCounter('lazy-loaded-images'),
                'preconnected-domains': this.monitor.getCounter('preconnected-domains'),
                'preloaded-resources': this.monitor.getCounter('preloaded-resources')
            });

            console.log('配置详情:', this.config.config);
            console.groupEnd();
        }

        destroy() {
            if (!this.initialized) return;

            this.monitor.log('开始清理资源');

            // 清理各个模块
            Object.values(this.modules).forEach(module => {
                if (module.destroy) {
                    try {
                        module.destroy();
                    } catch (e) {
                        this.monitor.warn('模块清理失败', e);
                    }
                }
            });

            // 执行清理任务
            this.cleanupTasks.forEach(task => {
                try {
                    task();
                } catch (e) {
                    this.monitor.warn('清理任务执行失败', e);
                }
            });
            this.cleanupTasks = [];

            this.initialized = false;
            this.monitor.log('资源清理完成');
        }

        // 公共 API - 增强版
        updateConfig(path, value) {
            this.config.set(path, value);
            this.monitor.log(`配置已更新: ${path} = ${value}`);

            // 如果是调试模式变更,更新监控器
            if (path === 'debug') {
                this.monitor.debug = value;
            }
        }

        getStats() {
            return {
                initialized: this.initialized,
                version: '2.0',
                hostname: location.hostname,
                config: this.config.config,
                modules: Object.keys(this.modules),
                counters: {
                    'processed-images': this.monitor.getCounter('processed-images'),
                    'lazy-loaded-images': this.monitor.getCounter('lazy-loaded-images'),
                    'preconnected-domains': this.monitor.getCounter('preconnected-domains'),
                    'preloaded-resources': this.monitor.getCounter('preloaded-resources')
                }
            };
        }

        // 新增:性能报告
        getPerformanceReport() {
            const stats = this.getStats();
            const imageStats = {
                total: document.querySelectorAll('img').length,
                processed: stats.counters['processed-images'],
                lazyLoaded: stats.counters['lazy-loaded-images']
            };

            return {
                ...stats,
                performance: {
                    images: imageStats,
                    domains: stats.counters['preconnected-domains'],
                    resources: stats.counters['preloaded-resources'],
                    efficiency: imageStats.total > 0 ? (imageStats.processed / imageStats.total * 100).toFixed(1) + '%' : '0%'
                }
            };
        }
    }

    // ========================
    // 全局初始化
    // ========================

    // 创建全局实例
    const optimizer = new WebOptimizer();

    // 暴露到全局作用域(调试用)
    if (typeof window !== 'undefined') {
        window.WebOptimizer = optimizer;

        // v2.0 新增:暴露工具函数供调试使用
        window.WebOptimizerUtils = {
            debounce,
            throttle,
            safeParseURL,
            isElementVisible,
            deepMerge,
            delay,
            RetryableOperation
        };
    }

    // 启动优化器
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => optimizer.init());
    } else {
        // 延迟一点时间,确保页面基本稳定
        setTimeout(() => optimizer.init(), 100);
    }

})();