您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Optimize rendering, event handling, resource loading, and more.
// ==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...'); }); })();