Web性能综合优化工具箱(增强版)

web浏览提速80% + 全面性能优化

// ==UserScript==
// @name         Web性能综合优化工具箱(增强版)
// @namespace    http://tampermonkey.net/
// @version      3.4.0-enhanced
// @description  web浏览提速80% + 全面性能优化
// @author       KiwiFruit
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
    'use strict';
    // ========================
    // 0. 启用开关
    // ========================
    if (!localStorage.getItem('PerfOptEnabled')) {
        console.log('[PerfOpt] 未启用。执行:localStorage.setItem("PerfOptEnabled", "1"); location.reload();');
        return;
    }

    // ========================
    // 1. 基础工具与环境检测
    // ========================
    const Environment = {
        features: {
            nativeLazyLoad: 'loading' in HTMLImageElement.prototype,
            intersectionObserver: 'IntersectionObserver' in window,
            webWorker: 'Worker' in window,
            performanceObserver: 'PerformanceObserver' in window
        },
        performanceTier: (() => {
            if (navigator.hardwareConcurrency >= 4) return 2;
            if (window.devicePixelRatio <= 1.5) return 1;
            return 0;
        })(),
        networkType: navigator.connection?.effectiveType || 'unknown',
        isLowPerformance() {
            return this.performanceTier === 0 || this.networkType === '2g';
        }
    };

    const Config = (() => {
        const config = {
            debug: false,
            throttleDelay: 200,
            debounceDelay: 300,
            retryAttempts: 3,
            retryDelay: 1000,
            lazyLoad: { enabled: true, selector: '.js-lazy-load', rootMargin: '100px 0px', preferNative: true },
            criticalCSS: { enabled: true, selectors: ['.js-critical-css'], preloadTimeout: 5000 },
            hardwareAcceleration: { enabled: true, selector: '.js-animate, .js-transform, .js-fade' },
            webWorker: { enabled: true, customTask: null },
            performanceMonitor: { enabled: false, metrics: ['fcp', 'lcp', 'cls'] },
            domAnalyzer: { enabled: true, maxDepth: 12 },
            contentVisibility: { enabled: true, selector: '.js-section' }
        };
        return {
            get(key) {
                const keys = key.split('.');
                return keys.reduce((obj, k) => obj?.[k], config);
            },
            set(key, value) {
                const keys = key.split('.');
                const lastKey = keys.pop();
                const target = keys.reduce((obj, k) => obj?.[k], config);
                if (target && typeof target[lastKey] !== 'undefined') {
                    const oldValue = target[lastKey];
                    target[lastKey] = value;
                    Logger.info('Config', `更新配置: ${key}=${value}(旧值: ${oldValue})`);
                    return true;
                }
                Logger.error('Config', `配置键不存在: ${key}`);
                return false;
            },
            getAll() { return { ...config }; }
        };
    })();

    const Logger = {
        debug: (module, msg) => {
            if (Config.get('debug')) console.log(`[PerfOpt][${module}] DEBUG: ${msg}`);
        },
        info: (module, msg) => {
            if (Config.get('debug')) console.info(`[PerfOpt][${module}] INFO: ${msg}`);
        },
        warn: (module, msg) => {
            if (Config.get('debug')) console.warn(`[PerfOpt][${module}] WARN: ${msg}`);
        },
        error: (module, msg, error) => {
            if (Config.get('debug')) console.error(`[PerfOpt][${module}] ERROR: ${msg}`, error || '');
        }
    };

    // === 开发模式:布局抖动检测 ===
    if (Config.get('debug')) {
        const layoutProps = ['offsetTop', 'offsetLeft', 'offsetWidth', 'offsetHeight', 'clientWidth', 'clientHeight', 'scrollHeight', 'scrollWidth'];
        layoutProps.forEach(prop => {
            const original = Object.getOwnPropertyDescriptor(Element.prototype, prop);
            if (original && original.get) {
                Object.defineProperty(Element.prototype, prop, {
                    get() {
                        console.warn(`[PerfOpt][LayoutThrashing] 检测到布局读取: ${prop}`, this);
                        return original.get.call(this);
                    }
                });
            }
        });
    }

    function isSameOrigin(url) {
        try {
            return new URL(url, window.location.href).origin === window.location.origin;
        } catch (e) {
            return false;
        }
    }

    function prefetchDomain(url) {
        try {
            const origin = new URL(url, window.location.href).origin;
            if (!document.querySelector(`link[href="${origin}"]`)) {
                const link = document.createElement('link');
                link.rel = 'dns-prefetch preconnect';
                link.href = origin;
                document.head.appendChild(link);
            }
        } catch (e) {
            Logger.warn('Utils', '预连接失败', e);
        }
    }

    const Utils = {
        throttle: (func, delay) => {
            let lastCall = 0;
            return function (...args) {
                const now = Date.now();
                if (now - lastCall >= delay) {
                    lastCall = now;
                    func.apply(this, args);
                }
            };
        },
        debounce: (func, delay) => {
            let timer;
            return function (...args) {
                clearTimeout(timer);
                timer = setTimeout(() => func.apply(this, args), delay);
            };
        },
        loadWithRetry: async (loaderFn, moduleName) => {
            for (let i = 0; i < Config.get('retryAttempts'); i++) {
                try {
                    return await loaderFn();
                } catch (error) {
                    const isLastAttempt = i === Config.get('retryAttempts') - 1;
                    if (isLastAttempt) {
                        Logger.error(moduleName, `加载失败(已达最大重试次数)`, error);
                        throw error;
                    }
                    Logger.warn(moduleName, `加载失败,${Config.get('retryDelay')}ms后重试(${i + 1}/${Config.get('retryAttempts')})`);
                    await new Promise(resolve => setTimeout(resolve, Config.get('retryDelay')));
                }
            }
        },
        safeGetData: (el, name, defaultValue) => {
            try {
                const value = el.dataset[name];
                if (!value) return defaultValue;
                if (value.match(/^[{[]/)) return JSON.parse(value);
                if (value.toLowerCase() === 'true') return true;
                if (value.toLowerCase() === 'false') return false;
                const num = Number(value);
                return !isNaN(num) ? num : value;
            } catch (e) {
                Logger.warn('Utils', `解析data-${name}失败`, e);
                return defaultValue;
            }
        },
        is: {
            func: v => typeof v === 'function',
            elem: v => v instanceof Element,
            str: v => typeof v === 'string',
            num: v => typeof v === 'number' && !isNaN(v)
        }
    };

    // ========================
    // 2. 基础类
    // ========================
    class BaseModule {
        constructor(moduleName) {
            this.moduleName = moduleName;
            this.initialized = false;
        }
        init() {
            if (this.initialized) {
                Logger.warn(this.moduleName, '已初始化');
                return;
            }
            this.initialized = true;
            Logger.info(this.moduleName, '初始化开始');
        }
        destroy() {
            if (!this.initialized) return;
            this.initialized = false;
            Logger.info(this.moduleName, '销毁完成');
        }
        emitEvent(eventName, detail = {}) {
            window.dispatchEvent(new CustomEvent(`perfopt:${this.moduleName}:${eventName}`, {
                detail: { ...detail, module: this.moduleName, timestamp: Date.now() }
            }));
        }
    }

    class BaseObserver extends BaseModule {
        constructor(moduleName, configKey) {
            super(moduleName);
            this.observer = null;
            this.configKey = configKey;
            this.observers = [];
        }
        createObserver(handleIntersect, rootMargin = '0px') {
            if (!Environment.features.intersectionObserver) {
                Logger.warn(this.moduleName, '不支持IntersectionObserver');
                return null;
            }
            const observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        this.handleIntersect(entry.target);
                    } else {
                        this.handleLeave(entry.target);
                    }
                });
            }, { rootMargin, threshold: 0.01 });
            this.observers.push(observer);
            return observer;
        }
        observeElements(selector) {
            if (!selector || !this.observers.length) return;
            document.querySelectorAll(selector).forEach(el => {
                if (!el.dataset[this.moduleName + 'Observed']) {
                    this.observers[0].observe(el);
                    el.dataset[this.moduleName + 'Observed'] = 'true';
                }
            });
        }
        handleIntersect(target) { throw new Error('子类需实现handleIntersect方法'); }
        handleLeave(target) {}
        destroy() {
            super.destroy();
            this.observers.forEach(observer => observer.disconnect());
            this.observers = [];
        }
    }

    // ========================
    // 3. 新增模块
    // ========================
    class DomDepthAnalyzer extends BaseModule {
        constructor() {
            super('DomDepthAnalyzer');
        }
        init() {
            super.init();
            if (!Config.get('domAnalyzer.enabled') || Environment.isLowPerformance()) {
                Logger.info(this.moduleName, '已禁用或低性能设备跳过');
                return;
            }
            const run = () => {
                const allElements = document.querySelectorAll('*');
                const maxDepth = Config.get('domAnalyzer.maxDepth');
                let deepCount = 0;
                for (let el of allElements) {
                    let depth = 0;
                    let parent = el;
                    while (parent && parent !== document) {
                        depth++;
                        parent = parent.parentNode;
                        if (depth > maxDepth) break;
                    }
                    if (depth > maxDepth) {
                        deepCount++;
                        Logger.warn(this.moduleName, `深度过大(${depth})`, el);
                        if (Config.get('debug')) {
                            el.style.outline = '2px solid orange';
                            el.title = `DOM深度: ${depth}`;
                        }
                    }
                }
                if (deepCount > 0) {
                    Logger.warn(this.moduleName, `共发现 ${deepCount} 个过深节点`);
                }
            };
            if (window.requestIdleCallback) {
                requestIdleCallback(() => run(), { timeout: 3000 });
            } else {
                setTimeout(run, 2000);
            }
        }
    }

    class StyleComplexityMonitor extends BaseModule {
        constructor() {
            super('StyleComplexityMonitor');
            this.observer = null;
        }
        init() {
            super.init();
            if (!Environment.features.performanceObserver || !Config.get('performanceMonitor.enabled')) {
                Logger.info(this.moduleName, '未启用或不支持');
                return;
            }
            try {
                this.observer = new PerformanceObserver((list) => {
                    list.getEntries().forEach(entry => {
                        if (entry.name === 'styleRecalculation' && entry.duration > 10) {
                            Logger.warn(this.moduleName, `高成本样式重计算: ${entry.duration.toFixed(2)}ms`);
                        }
                    });
                });
                this.observer.observe({ entryTypes: ['styleRecalculation'] });
            } catch (e) {
                Logger.warn(this.moduleName, '不支持 styleRecalculation', e);
            }
        }
        destroy() {
            super.destroy();
            if (this.observer) this.observer.disconnect();
        }
    }

    class ContentVisibilityOptimizer extends BaseModule {
        constructor() {
            super('ContentVisibilityOptimizer');
        }
        init() {
            super.init();
            if (!Config.get('contentVisibility.enabled')) return;
            const selector = Config.get('contentVisibility.selector');
            if (!selector) return;
            document.querySelectorAll(selector).forEach(el => {
                if (!el.style.contentVisibility) {
                    el.style.contentVisibility = 'auto';
                    el.style.containIntrinsicSize = '1px 1000px';
                }
            });
        }
    }

    // ========================
    // 4. 原有模块增强
    // ========================
    class LazyLoader extends BaseObserver {
        constructor() {
            super('LazyLoader', 'lazyLoad');
            this.scrollHandler = null;
            this.loadStrategies = {
                IMG: { src: (el, src) => { el.src = src; } },
                SCRIPT: { src: (el, src) => { el.src = src; el.async = true; } },
                LINK: { href: (el, href) => { el.href = href; } }
            };
        }
        init() {
            super.init();
            if (!Config.get('lazyLoad.enabled')) return;
            if (Environment.features.nativeLazyLoad && Config.get('lazyLoad.preferNative')) {
                this.useNativeLazyLoad();
            } else if (Environment.features.intersectionObserver) {
                this.useObserverLazyLoad();
            } else {
                this.useFallbackLazyLoad();
            }
        }
        useNativeLazyLoad() {
            document.querySelectorAll(Config.get('lazyLoad.selector')).forEach(el => {
                if (['IMG', 'IFRAME'].includes(el.tagName)) {
                    el.loading = 'lazy';
                    const src = el.src || el.dataset.src;
                    if (src) prefetchDomain(src);
                }
                this.loadElement(el);
            });
        }
        useObserverLazyLoad() {
            this.createObserver(() => {}, Config.get('lazyLoad.rootMargin'));
            this.observeElements(Config.get('lazyLoad.selector'));
        }
        useFallbackLazyLoad() {
            this.scrollHandler = Utils.throttle(() => {
                document.querySelectorAll(Config.get('lazyLoad.selector')).forEach(el => {
                    if (!el.classList.contains('loaded') && this.isInViewport(el)) {
                        this.loadElement(el);
                    }
                });
            }, Config.get('throttleDelay'));
            window.addEventListener('scroll', this.scrollHandler, { passive: true });
            this.scrollHandler();
        }
        loadElement(el) {
            if (!Utils.is.elem(el) || el.classList.contains('loaded')) return;
            try {
                const src = Utils.safeGetData(el, 'src', '') || Utils.safeGetData(el, 'lazySrc', '');
                const href = Utils.safeGetData(el, 'href', '') || Utils.safeGetData(el, 'lazyHref', '');
                if (src) prefetchDomain(src);
                if (href) prefetchDomain(href);
                const strategy = this.loadStrategies[el.tagName]?.[src ? 'src' : 'href'];
                if (strategy && (src || href)) {
                    strategy(el, src || href);
                    this.bindLoadEvents(el, src || href);
                } else {
                    this.markFailed(el);
                }
            } catch (error) {
                this.markFailed(el);
                Logger.error(this.moduleName, '加载失败', error);
            }
        }
        // ... 其余方法保持不变(bindLoadEvents, markLoaded, markFailed, isInViewport, handleIntersect, destroy)
        bindLoadEvents(el, url) {
            el.addEventListener('load', () => {
                this.markLoaded(el);
                this.emitEvent('loaded', { url, tag: el.tagName });
            }, { once: true });
            el.addEventListener('error', (e) => {
                this.markFailed(el, e);
                this.emitEvent('error', { url, tag: el.tagName, error: e });
            }, { once: true });
        }
        markLoaded(el) {
            el.classList.add('loaded', 'lazy-loaded');
            el.classList.remove('load-failed');
        }
        markFailed(el, error) {
            el.classList.add('load-failed');
            el.classList.remove('loaded', 'lazy-loaded');
        }
        isInViewport(el) {
            const rect = el.getBoundingClientRect();
            return rect.top <= window.innerHeight + 100 && rect.left <= window.innerWidth;
        }
        handleIntersect(target) {
            this.loadElement(target);
            this.observers.forEach(observer => observer.unobserve(target));
        }
        destroy() {
            super.destroy();
            if (this.scrollHandler) {
                window.removeEventListener('scroll', this.scrollHandler);
                this.scrollHandler = null;
            }
        }
    }

    class EventOptimizer extends BaseModule {
        constructor() {
            super('EventOptimizer');
            this.handlers = {
                scroll: Utils.throttle(() => this.emitEvent('scroll'), Config.get('throttleDelay')),
                resize: Utils.debounce(() => this.emitEvent('resize'), Config.get('debounceDelay'))
            };
        }
        init() {
            super.init();
            window.addEventListener('scroll', this.handlers.scroll, { passive: true });
            window.addEventListener('resize', this.handlers.resize);
        }
        destroy() {
            super.destroy();
            window.removeEventListener('scroll', this.handlers.scroll);
            window.removeEventListener('resize', this.handlers.resize);
        }
    }

    class GpuAccelerator extends BaseObserver {
        constructor() {
            super('GpuAccelerator', 'hardwareAcceleration');
            this.styleEl = null;
        }
        init() {
            super.init();
            if (!Config.get('hardwareAcceleration.enabled')) return;
            if (Environment.isLowPerformance()) {
                Config.set('hardwareAcceleration.selector', '.js-animate');
            }
            this.injectStyles();
            this.createObserver(() => {}, '50px');
            this.observeElements(Config.get('hardwareAcceleration.selector'));
        }
        injectStyles() {
            this.styleEl = document.createElement('style');
            this.styleEl.textContent = `
                .gpu-accelerate {
                    transform: translateZ(0);
                    opacity: 1;
                    will-change: transform, opacity;
                }
                .gpu-accelerate.inactive {
                    will-change: auto;
                }
            `;
            document.head.appendChild(this.styleEl);
        }
        handleIntersect(target) {
            target.classList.add('gpu-accelerate');
            target.classList.remove('inactive');
            // 确保样式生效
            target.style.transform = 'translateZ(0)';
        }
        handleLeave(target) {
            target.classList.add('inactive');
            // 精确回收:移除 transform 避免层爆炸
            if (!target.matches('.js-persist-gpu')) {
                target.style.transform = '';
            }
        }
        destroy() {
            super.destroy();
            if (this.styleEl) this.styleEl.remove();
        }
    }

    class CriticalCSSLoader extends BaseModule {
        constructor() {
            super('CriticalCSSLoader');
            this.loadedUrls = new Set();
        }
        init() {
            super.init();
            if (!Config.get('criticalCSS.enabled')) return;
            const cssUrls = this.collectCriticalCSSUrls();
            if (cssUrls.length === 0) return;
            cssUrls.forEach(url => this.preloadCSS(url));
        }
        collectCriticalCSSUrls() {
            const urls = new Set();
            Config.get('criticalCSS.selectors').forEach(selector => {
                document.querySelectorAll(selector).forEach(el => {
                    const url = Utils.safeGetData(el, 'href', '');
                    if (url) {
                        urls.add(url);
                        el.remove();
                    }
                });
            });
            const meta = document.querySelector('meta[name="critical-css"]');
            if (meta) meta.content.split(',').forEach(url => url && urls.add(url.trim()));
            return Array.from(urls);
        }
        preloadCSS(url) {
            if (this.loadedUrls.has(url)) return;
            const link = document.createElement('link');
            link.rel = 'preload';
            link.as = 'style';
            link.href = url;
            link.crossOrigin = 'anonymous';
            const timeoutId = setTimeout(() => {
                if (!this.loadedUrls.has(url)) {
                    this.fallbackLoad(url);
                }
            }, Config.get('criticalCSS.preloadTimeout'));
            link.onload = () => {
                clearTimeout(timeoutId);
                link.rel = 'stylesheet';
                this.loadedUrls.add(url);
                document.body.classList.add('critical-css-loaded');
            };
            link.onerror = () => {
                clearTimeout(timeoutId);
                this.fallbackLoad(url);
            };
            document.head.appendChild(link);
        }
        fallbackLoad(url) {
            if (this.loadedUrls.has(url)) return;
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = url;
            link.onload = () => this.loadedUrls.add(url);
            link.onerror = (e) => this.emitEvent('error', { url, error: e });
            document.head.appendChild(link);
        }
    }

    class DomObserver extends BaseModule {
        constructor(lazyLoader, gpuAccelerator) {
            super('DomObserver');
            this.lazyLoader = lazyLoader;
            this.gpuAccelerator = gpuAccelerator;
            this.observer = null;
        }
        init() {
            super.init();
            this.observer = new MutationObserver(Utils.throttle((mutations) => {
                this.handleMutations(mutations);
            }, 200));
            this.observer.observe(document.body, { childList: true, subtree: true });
        }
        handleMutations(mutations) {
            mutations.forEach(m => {
                m.addedNodes.forEach(node => {
                    if (node.nodeType === 1) {
                        if (this.lazyLoader?.initialized && Config.get('lazyLoad.enabled')) {
                            const lazyEls = node.matches?.(Config.get('lazyLoad.selector'))
                                ? [node]
                                : Array.from(node.querySelectorAll?.(Config.get('lazyLoad.selector')) || []);
                            lazyEls.forEach(el => {
                                if (!el.dataset.LazyLoaderObserved) {
                                    this.lazyLoader.loadElement(el);
                                }
                            });
                        }
                        if (this.gpuAccelerator?.initialized && Config.get('hardwareAcceleration.enabled')) {
                            const accelEls = node.matches?.(Config.get('hardwareAcceleration.selector'))
                                ? [node]
                                : Array.from(node.querySelectorAll?.(Config.get('hardwareAcceleration.selector')) || []);
                            accelEls.forEach(el => {
                                if (!el.dataset.GpuAcceleratorObserved) {
                                    this.gpuAccelerator.handleIntersect(el);
                                }
                            });
                        }
                    }
                });
            });
        }
        destroy() {
            super.destroy();
            if (this.observer) this.observer.disconnect();
        }
    }

    // ========================
    // 5. 应用控制器(含新模块)
    // ========================
    class AppController extends BaseModule {
        constructor() {
            super('AppController');
            this.modules = {};
        }
        init() {
            super.init();
            try {
                this.modules.criticalCSSLoader = new CriticalCSSLoader();
                this.modules.criticalCSSLoader.init();

                this.modules.lazyLoader = new LazyLoader();
                this.modules.lazyLoader.init();

                this.modules.eventOptimizer = new EventOptimizer();
                this.modules.eventOptimizer.init();

                this.modules.gpuAccelerator = new GpuAccelerator();
                this.modules.gpuAccelerator.init();

                this.modules.domDepthAnalyzer = new DomDepthAnalyzer();
                this.modules.domDepthAnalyzer.init();

                this.modules.styleComplexityMonitor = new StyleComplexityMonitor();
                this.modules.styleComplexityMonitor.init();

                this.modules.contentVisibilityOptimizer = new ContentVisibilityOptimizer();
                this.modules.contentVisibilityOptimizer.init();

                this.modules.domObserver = new DomObserver(
                    this.modules.lazyLoader,
                    this.modules.gpuAccelerator
                );
                this.modules.domObserver.init();

                window.addEventListener('beforeunload', () => this.destroy());
                window.addEventListener('spa:navigate', () => {
                    this.destroy();
                    this.init();
                });
            } catch (error) {
                Logger.error('AppController', '初始化错误', error);
                this.destroy();
            }
        }
        destroy() {
            Object.values(this.modules).reverse().forEach(module => {
                if (module && typeof module.destroy === 'function') {
                    try {
                        module.destroy();
                    } catch (e) {
                        Logger.error('AppController', `模块${module.moduleName}销毁失败`, e);
                    }
                }
            });
            super.destroy();
        }
    }

    // ========================
    // 启动
    // ========================
    function bootstrap() {
        try {
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', () => {
                    const app = new AppController();
                    app.init();
                    window.PerfOptimizer = app;
                });
            } else {
                const app = new AppController();
                app.init();
                window.PerfOptimizer = app;
            }
        } catch (error) {
            console.error('[PerfOpt] 启动失败', error);
        }
    }

    window.PerfUtils = {
        getConfig: Config.getAll,
        setConfig: Config.set,
        throttle: Utils.throttle,
        debounce: Utils.debounce,
        loadWithRetry: Utils.loadWithRetry
    };

    bootstrap();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址