Greasy Fork

Greasy Fork is available in English.

web综合优化脚本

Optimize rendering, event handling, resource loading, and more.

当前为 2025-06-13 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         web综合优化脚本
// @namespace    http://tampermonkey.net/
// @version      3.0.1
// @description  Optimize rendering, event handling, resource loading, and more.
// @author       KiwiFruit
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
    'use strict';

    // ========================
    // 配置中心
    // ========================
    const config = {
        debug: false,
        throttleDelay: 200,
        debounceDelay: 300,
        retryAttempts: 3,
        retryDelay: 1000,
        criticalCssPaths: {
            'example.com': '/styles/example-critical.css',
            'anotherwebsite.com': '/styles/anotherwebsite-critical.css',
            default: '/styles/default-critical.css'
        },
        lazyCssSelector: '.lazy-css',
        rootMarginFactor: 0.1,
        enableWebWorker: true,
        batchStyleUpdate: true
    };

    // ========================
    // 日志系统
    // ========================
    const logger = {
        debug: (msg) => {
            if (config.debug) console.log(`[DEBUG] ${msg}`);
        },
        warn: (msg) => console.warn(`[WARN] ${msg}`),
        error: (msg) => console.error(`[ERROR] ${msg}`)
    };

    // ========================
    // 工具函数
    // ========================
    const throttle = (func, delay) => {
        let lastCall = 0;
        return function (...args) {
            const now = Date.now();
            if (now - lastCall >= delay) {
                lastCall = now;
                func.apply(this, args);
            }
        };
    };

    const debounce = (func, delay) => {
        let timer;
        return function (...args) {
            clearTimeout(timer);
            timer = setTimeout(() => func.apply(this, args), delay);
        };
    };

    const calculateRootMargin = () => {
        const windowHeight = window.innerHeight;
        const marginBottom = Math.max(0, windowHeight * config.rootMarginFactor);
        return `0px 0px ${marginBottom}px 0px`;
    };

    // ========================
    // 样式批量更新系统
    // ========================
    class StyleBatchUpdater {
        static pendingUpdates = new Map();
        static updateScheduled = false;

        static batchUpdate(element, styles) {
            if (!config.batchStyleUpdate) {
                Object.assign(element.style, styles);
                return;
            }
            if (!this.pendingUpdates.has(element)) {
                this.pendingUpdates.set(element, {});
            }
            const currentUpdates = this.pendingUpdates.get(element);
            Object.assign(currentUpdates, styles);
            if (!this.updateScheduled) {
                this.updateScheduled = true;
                requestAnimationFrame(() => this.processBatch());
            }
        }

        static processBatch() {
            this.pendingUpdates.forEach((styles, element) => {
                Object.assign(element.style, styles);
            });
            this.pendingUpdates.clear();
            this.updateScheduled = false;
        }

        static batchAddClass(elements, className) {
            if (!Array.isArray(elements)) elements = [elements];
            if (!config.batchStyleUpdate) {
                elements.forEach(el => el.classList.add(className));
                return;
            }
            elements.forEach(element => {
                if (!this.pendingUpdates.has(element)) {
                    this.pendingUpdates.set(element, {});
                }
                const classList = this.pendingUpdates.get(element).classList || [];
                classList.push({ action: 'add', className });
                this.pendingUpdates.get(element).classList = classList;
            });
            if (!this.updateScheduled) {
                this.updateScheduled = true;
                requestAnimationFrame(() => this.processClassBatch());
            }
        }

        static batchRemoveClass(elements, className) {
            if (!Array.isArray(elements)) elements = [elements];
            if (!config.batchStyleUpdate) {
                elements.forEach(el => el.classList.remove(className));
                return;
            }
            elements.forEach(element => {
                if (!this.pendingUpdates.has(element)) {
                    this.pendingUpdates.set(element, {});
                }
                const classList = this.pendingUpdates.get(element).classList || [];
                classList.push({ action: 'remove', className });
                this.pendingUpdates.get(element).classList = classList;
            });
            if (!this.updateScheduled) {
                this.updateScheduled = true;
                requestAnimationFrame(() => this.processClassBatch());
            }
        }

        static processClassBatch() {
            this.pendingUpdates.forEach((operations, element) => {
                if (operations.classList) {
                    operations.classList.forEach(op => {
                        if (op.action === 'add') {
                            element.classList.add(op.className);
                        } else {
                            element.classList.remove(op.className);
                        }
                    });
                }
            });
            this.pendingUpdates.clear();
            this.updateScheduled = false;
        }
    }

    // ========================
    // 资源加载器
    // ========================
    class ResourceLoader {
        static loadResource(url, type) {
            return new Promise((resolve, reject) => {
                const element = document.createElement(type === 'script' ? 'script' : 'link');
                if (type === 'script') {
                    element.src = url;
                } else {
                    element.rel = 'stylesheet';
                    element.href = url;
                }
                element.onload = resolve;
                element.onerror = () => reject(new Error(`${type} loading failed: ${url}`));
                document.head.appendChild(element);
            });
        }

        static async loadWithRetry(loaderFn, maxRetries = config.retryAttempts, delay = config.retryDelay) {
            for (let i = 0; i < maxRetries; i++) {
                try {
                    return await loaderFn();
                } catch (error) {
                    if (i === maxRetries - 1) {
                        logger.error(`Resource load failed after ${maxRetries} attempts: ${error.message}`);
                        throw error;
                    }
                    logger.warn(`Retrying in ${delay / 1000}s...`);
                    await new Promise(resolve => setTimeout(resolve, delay));
                }
            }
        }

        static async loadStylesheet(href) {
            await this.loadWithRetry(() => this.loadResource(href, 'stylesheet'));
            logger.debug(`Stylesheet loaded: ${href}`);
        }

        static async loadScript(src) {
            await this.loadWithRetry(() => this.loadResource(src, 'script'));
            logger.debug(`Script loaded: ${src}`);
        }
    }

    // ========================
    // 硬件加速优化
    // ========================
    class HardwareAcceleration {
        static init() {
            const className = 'enable-hardware-acceleration';
            const styleSheet = `
                .${className} {
                    transform: translateZ(0) !important;
                    will-change: transform !important;
                }
            `;
            const styleElement = document.createElement('style');
            styleElement.type = 'text/css';
            styleElement.appendChild(document.createTextNode(styleSheet));
            document.head.appendChild(styleElement);

            const observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        StyleBatchUpdater.batchAddClass(entry.target, className);
                    } else {
                        StyleBatchUpdater.batchRemoveClass(entry.target, className);
                    }
                });
            }, { rootMargin: calculateRootMargin(), threshold: 0 });

            return observer;
        }
    }

    // ========================
    // 非首屏CSS懒加载
    // ========================
    class LazyCssLoader {
        static init() {
            if (!window.IntersectionObserver) {
                this.fallback();
                return;
            }
            const observer = new IntersectionObserver((entries, io) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const element = entry.target;
                        const href = element.getAttribute('data-lazy-css');
                        if (href) {
                            ResourceLoader.loadStylesheet(href).then(() => {
                                if (element.parentElement) {
                                    element.parentElement.removeChild(element);
                                }
                            });
                        }
                        io.unobserve(element);
                    }
                });
            }, { rootMargin: calculateRootMargin(), threshold: 0 });

            document.querySelectorAll(config.lazyCssSelector).forEach(el => observer.observe(el));
        }

        static fallback() {
            logger.warn('IntersectionObserver not supported, falling back to polling...');
            const checkVisible = () => {
                document.querySelectorAll(config.lazyCssSelector).forEach(element => {
                    const rect = element.getBoundingClientRect();
                    if (rect.top < window.innerHeight && rect.bottom > 0) {
                        const href = element.getAttribute('data-lazy-css');
                        ResourceLoader.loadStylesheet(href).then(() => {
                            if (element.parentElement) {
                                element.parentElement.removeChild(element);
                            }
                        });
                    }
                });
            };
            setInterval(checkVisible, 500);
        }
    }

    // ========================
    // Web Worker
    // ========================
    class WorkerManager {
        static init() {
            if (!config.enableWebWorker || !window.Worker) {
                logger.warn('Web Worker not available or disabled.');
                return;
            }
            const workerCode = `
                self.onmessage = function(e) {
                    const result = heavyProcessing(e.data);
                    self.postMessage(result);
                };
                function heavyProcessing(data) {
                    let sum = 0;
                    for (let i = 0; i < data; i++) {
                        sum += Math.sqrt(i);
                    }
                    return sum;
                }
            `;
            const blob = new Blob([workerCode], { type: 'application/javascript' });
            const url = URL.createObjectURL(blob);
            const worker = new Worker(url);
            worker.onmessage = function(e) {
                logger.debug('Worker result:', e.data);
            };
            worker.postMessage(1000000);
        }
    }

    // ========================
    // 事件绑定(节流/防抖)
    // ========================
    class EventManager {
        static init() {
            window.addEventListener('scroll', throttle(() => {
                logger.debug('Scroll event triggered (throttled)');
                this.handleScroll();
            }, config.throttleDelay));
            window.addEventListener('resize', debounce(() => {
                logger.debug('Resize event triggered (debounced)');
                this.handleResize();
            }, config.debounceDelay));
        }

        static handleScroll() {
            const elements = document.querySelectorAll('.scroll-affect');
            const scrollY = window.scrollY;
            StyleBatchUpdater.batchUpdate(document.documentElement, {
                '--scroll-position': `${scrollY}px`
            });
            elements.forEach(element => {
                const shouldUpdate = element.getBoundingClientRect().top < window.innerHeight * 0.8;
                if (shouldUpdate) {
                    StyleBatchUpdater.batchAddClass(element, 'scrolled');
                } else {
                    StyleBatchUpdater.batchRemoveClass(element, 'scrolled');
                }
            });
        }

        static handleResize() {
            const width = window.innerWidth;
            const breakpoint = 768;
            const elements = document.querySelectorAll('.responsive-element');
            if (width < breakpoint) {
                StyleBatchUpdater.batchAddClass(elements, 'mobile-view');
                StyleBatchUpdater.batchRemoveClass(elements, 'desktop-view');
            } else {
                StyleBatchUpdater.batchAddClass(elements, 'desktop-view');
                StyleBatchUpdater.batchRemoveClass(elements, 'mobile-view');
            }
        }
    }

    // ========================
    // DOM变化监听
    // ========================
    class DomMonitor {
        static init() {
            const observer = new MutationObserver(throttle(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1 && node.matches(config.lazyCssSelector)) {
                            LazyCssLoader.init();
                        }
                    });
                });
            }, 100));
            observer.observe(document.body, { childList: true, subtree: true });
        }
    }

    // ========================
    // 初始化流程
    // ========================
    class App {
        static async init() {
            const hostname = window.location.hostname;
            let criticalCssUrl;
            if (hostname.includes('example.com')) {
                criticalCssUrl = config.criticalCssPaths['example.com'];
            } else if (hostname.includes('anotherwebsite.com')) {
                criticalCssUrl = config.criticalCssPaths['anotherwebsite.com'];
            } else {
                criticalCssUrl = config.criticalCssPaths.default;
            }

            if (criticalCssUrl) {
                try {
                    await ResourceLoader.loadStylesheet(`${window.location.origin}${criticalCssUrl}`);
                } catch (error) {
                    logger.error(`Failed to load critical CSS: ${error.message}`);
                }
            }

            HardwareAcceleration.init();
            LazyCssLoader.init();
            DomMonitor.init();
            EventManager.init();
            WorkerManager.init();
            logger.debug('Optimization script initialized');
        }
    }

    // ========================
    // 页面生命周期管理
    // ========================
    document.addEventListener("DOMContentLoaded", () => {
        App.init().catch(error => logger.error(`Initialization failed: ${error.message}`));
    });

    window.addEventListener("beforeunload", () => {
        StyleBatchUpdater.pendingUpdates.clear();
        logger.debug('Page is unloading...');
    });

})();