Ultimate Web Optimizer

全面的网页性能优化方案(含懒加载/预加载/预连接)

// ==UserScript==
// @name         Ultimate Web Optimizer
// @namespace    https://gf.qytechs.cn/zh-CN/users/1474228-moyu001
// @version      1.0
// @description  全面的网页性能优化方案(含懒加载/预加载/预连接)
// @author       moyu001
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_log
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // ========================
    // 配置中心
    // ========================
    const config = {
        debug: false,  // 开启调试日志
        features: {
            lazyLoad: {  // 图片懒加载
                enabled: true,
                minSize: 100,     // 最小处理尺寸(px)
                rootMargin: '200px',  // 提前加载距离
                skipHidden: true  // 跳过隐藏图片
            },
            preconnect: {  // 智能预连接
                enabled: true,
                whitelist: [  // 白名单优化
                    'fonts.gstatic.com',
                    'cdnjs.cloudflare.com',
                    'unpkg.com',
                    'ajax.googleapis.com',
                    'maxcdn.bootstrapcdn.com',
                    'code.jquery.com',
                    'kit.fontawesome.com',
                    'fonts.googleapis.cn',
                    'fonts.loli.net',
                    'cdn.jsdelivr.net',
                    'cdn.bootcdn.net',
                    'cdn.bootcss.com',
                    'libs.baidu.com',
                    'cdn.staticfile.org',
                    'lf3-cdn-tos.bytecdntp.com',
                    'unpkg.zhimg.com',
                    'npm.elemecdn.com',
                    'g.alicdn.com'
                ],
                maxConnections: 5  // 最大预连接数
            },
            preload: {  // 资源预加载
                enabled: true,
                types: ['css', 'js', 'woff2'],  // 预加载类型
                maxPreloads: 5  // 最大预加载数
            },
            layout: {  // 布局稳定性
                stableImages: true,
                stableIframes: true
            }
        }
    };

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

    // 图片懒加载系统
    const initLazyLoad = () => {
        if (!config.features.lazyLoad.enabled) return;

        const isLazyCandidate = (img) => {
            if (img.loading === 'eager') return false;
            if (img.complete) return false;
            if (img.src.startsWith('data:')) return false;
            if (config.features.lazyLoad.skipHidden &&
                window.getComputedStyle(img).display === 'none') return false;

            const rect = img.getBoundingClientRect();
            return rect.width > config.features.lazyLoad.minSize &&
                   rect.height > config.features.lazyLoad.minSize;
        };

        const processImage = (img) => {
            if (!img.dataset.src && img.src) {
                img.dataset.src = img.src;
                img.removeAttribute('src');
            }
            if (img.srcset && !img.dataset.srcset) {
                img.dataset.srcset = img.srcset;
                img.removeAttribute('srcset');
            }
            return img;
        };

        // 现代浏览器实现
        if ('IntersectionObserver' in window) {
            const observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const img = entry.target;
                        if (img.dataset.src) img.src = img.dataset.src;
                        if (img.dataset.srcset) img.srcset = img.dataset.srcset;
                        observer.unobserve(img);
                    }
                });
            }, {
                rootMargin: config.features.lazyLoad.rootMargin,
                threshold: 0.01
            });

            // 初始图片
            document.querySelectorAll('img').forEach(img => {
                if (isLazyCandidate(img)) {
                    observer.observe(processImage(img));
                }
            });

            // 动态加载监听
            new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeName === 'IMG' && isLazyCandidate(node)) {
                            observer.observe(processImage(node));
                        }
                    });
                });
            }).observe(document.body, {
                childList: true,
                subtree: true
            });
        } else {
            // 兼容模式实现
            const checkVisible = throttle(() => {
                document.querySelectorAll('img').forEach(img => {
                    if (isLazyCandidate(img) && !img.src) {
                        const rect = img.getBoundingClientRect();
                        if (rect.top < window.innerHeight +
                            parseInt(config.features.lazyLoad.rootMargin)) {
                            if (img.dataset.src) img.src = img.dataset.src;
                            if (img.dataset.srcset) img.srcset = img.dataset.srcset;
                        }
                    }
                });
            }, 200);
            window.addEventListener('scroll', checkVisible);
            checkVisible();
        }
    };

    // 智能预连接系统
    const initSmartPreconnect = () => {
        if (!config.features.preconnect.enabled) return;

        const processed = new Set();
        const whitelist = config.features.preconnect.whitelist;

        const doPreconnect = (hostname) => {
            if (processed.size >= config.features.preconnect.maxConnections) return;
            if (processed.has(hostname)) return;

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

            if (config.debug) {
                console.log('[Preconnect] 已连接:', hostname);
            }
        };

        const scanResources = () => {
            const resources = [
                ...document.querySelectorAll('script[src], link[href], img[src]')
            ];

            resources.forEach(el => {
                try {
                    const url = new URL(el.src || el.href);
                    const matched = whitelist.find(domain =>
                        url.hostname.endsWith(domain)
                    );
                    if (matched) {
                        doPreconnect(url.hostname);
                    }
                } catch {}
            });
        };

        // 三级触发机制
        scanResources(); // 立即扫描
        setTimeout(scanResources, 2000); // 捕获异步资源
        new MutationObserver(() => {
            setTimeout(scanResources, 100);
        }).observe(document.body, {
            childList: true,
            subtree: true
        });
    };

    // 资源预加载系统
    const initResourcePreload = () => {
        if (!config.features.preload.enabled) return;

        const processed = new Set();
        const types = config.features.preload.types;
        const max = config.features.preload.maxPreloads;

        const shouldPreload = (url) => {
            const ext = url.split('.').pop().toLowerCase();
            return types.includes(ext);
        };

        const doPreload = (url, asType) => {
            if (processed.size >= max) return;
            if (processed.has(url)) return;

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

            // 添加type属性
            if (asType === 'font') {
                link.setAttribute('crossorigin', 'anonymous');
                if (url.includes('.woff2')) {
                    link.type = 'font/woff2';
                } else if (url.includes('.woff')) {
                    link.type = 'font/woff';
                }
            } else if (asType === 'script') {
                link.type = 'text/javascript';
            } else if (asType === 'style') {
                link.type = 'text/css';
            }

            document.head.appendChild(link);
            processed.add(url);

            if (config.debug) {
                console.log('[Preload] 已预加载:', url);
            }
        };

        const processFont = (cssUrl, fontUrl) => {
            try {
                const absoluteUrl = new URL(fontUrl, cssUrl).href;
                if (fontUrl.startsWith('data:')) return; // 跳过数据URI
                if (shouldPreload(absoluteUrl)) {
                    doPreload(absoluteUrl, 'font');
                }
            } catch (e) {
                if (config.debug) {
                    console.warn('[Preload] 字体解析失败:', fontUrl, e);
                }
            }
        };

        const scanResources = () => {
            // 处理CSS
            document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
                const cssUrl = link.href;
                if (cssUrl && shouldPreload(cssUrl)) {
                    doPreload(cssUrl, 'style');

                    // 解析CSS中的字体
                    fetch(cssUrl)
                        .then(res => res.text())
                        .then(text => {
                            const fontUrls = text.match(/url\(["']?([^)"']+\.woff2?)["']?\)/gi) || [];
                            fontUrls.forEach(fullUrl => {
                                const cleanUrl = fullUrl.replace(/url\(["']?|["']?\)/g, '');
                                processFont(cssUrl, cleanUrl);
                            });
                        })
                        .catch(e => {
                            if (config.debug) {
                                console.warn('[Preload] CSS获取失败:', cssUrl, e);
                            }
                        });
                }
            });

            // 处理JS
            document.querySelectorAll('script[src]').forEach(script => {
                const src = script.src;
                if (src && shouldPreload(src)) {
                    doPreload(src, 'script');
                }
            });
        };

        scanResources();
        new MutationObserver(() => {
            setTimeout(scanResources, 100);
        }).observe(document.body, {
            childList: true,
            subtree: true
        });
    };

    // 布局稳定性优化
    const initLayoutStabilization = () => {
        const styles = [];

        if (config.features.layout.stableImages) {
            styles.push(`
                img:not([width]):not([height]) {
                    min-height: 1px;
                }
                @supports (aspect-ratio: 1/1) {
                    img:not([width]):not([height]) {
                        aspect-ratio: attr(width) / attr(height);
                    }
                }
            `);
        }

        if (config.features.layout.stableIframes) {
            styles.push(`
                iframe:not([width]):not([height]) {
                    width: 100%;
                    height: auto;
                    aspect-ratio: 16/9;
                }
            `);
        }

        if (styles.length) {
            const style = document.createElement('style');
            style.textContent = styles.join('\n');
            document.head.appendChild(style);
        }
    };

    // ========================
    // 工具函数
    // ========================
    function throttle(func, limit) {
        let inThrottle;
        return function() {
            if (!inThrottle) {
                func.apply(this, arguments);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    // ========================
    // 初始化系统
    // ========================
    document.addEventListener('DOMContentLoaded', () => {
        initSmartPreconnect();
        initResourcePreload();
        initLazyLoad();
        initLayoutStabilization();

        if (config.debug) {
            console.groupCollapsed('[Optimizer] 初始化报告');
            console.log('激活功能:', Object.entries(config.features)
                .filter(([_, v]) => v.enabled !== false)
                .map(([k]) => k));
            console.log('预连接白名单:', config.features.preconnect.whitelist);
            console.log('预加载类型:', config.features.preload.types);
            console.groupEnd();
        }
    });
})();

QingJ © 2025

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