Greasy Fork is available in English.
一个更安全、更灵活的性能优化脚本,包含懒加载、事件节流等实用功能。
当前为
// ==UserScript==
// @name 现代Web性能优化工具箱
// @namespace http://tampermonkey.net/
// @version 3.1.2
// @description 一个更安全、更灵活的性能优化脚本,包含懒加载、事件节流等实用功能。
// @author KiwiFruit
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// ========================
// 配置中心 - 简化并明确作用域
// ========================
const config = {
debug: false,
// 事件节流/防抖延迟
throttleDelay: 200,
debounceDelay: 300,
// 重试配置
retryAttempts: 3,
retryDelay: 1000,
// 懒加载配置
lazyLoad: {
enabled: true,
// 用于标记懒加载元素的通用类名
selector: '.js-lazy-load',
// 根边距,提前触发加载
rootMargin: '100px 0px'
},
// 硬件加速配置
hardwareAcceleration: {
enabled: true,
// 需要硬件加速的元素选择器
selector: '.js-animate, .js-transform'
},
// Web Worker 配置
webWorker: {
enabled: true,
// 自定义计算函数的占位符
customTask: null // 可由用户在外部定义
}
};
// ========================
// 日志系统 - 保持简洁
// ========================
const logger = {
debug: (msg) => { if (config.debug) console.log(`[Optimize] DEBUG: ${msg}`); },
info: (msg) => console.info(`[Optimize] INFO: ${msg}`),
warn: (msg) => console.warn(`[Optimize] WARN: ${msg}`),
error: (msg) => console.error(`[Optimize] ERROR: ${msg}`)
};
// ========================
// 工具函数 - 通用且无副作用
// ========================
const utils = {
/**
* 节流函数
* @param {Function} func - 要节流的函数
* @param {number} delay - 延迟时间(毫秒)
* @returns {Function} 节流后的函数
*/
throttle: (func, delay) => {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func.apply(this, args);
}
};
},
/**
* 防抖函数
* @param {Function} func - 要防抖的函数
* @param {number} delay - 延迟时间(毫秒)
* @returns {Function} 防抖后的函数
*/
debounce: (func, delay) => {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
},
/**
* 带重试机制的资源加载
* @param {Function} loaderFn - 返回Promise的加载函数
* @param {number} maxRetries - 最大重试次数
* @param {number} delay - 重试间隔(毫秒)
* @returns {Promise} 加载结果
*/
loadWithRetry: async (loaderFn, maxRetries = config.retryAttempts, delay = config.retryDelay) => {
for (let i = 0; i < maxRetries; i++) {
try {
return await loaderFn();
} catch (error) {
if (i === maxRetries - 1) {
throw error;
}
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
};
// ========================
// 模块1: 非首屏资源懒加载
// ========================
class LazyLoader {
static init() {
if (!config.lazyLoad.enabled) return;
if (!window.IntersectionObserver) {
logger.warn('IntersectionObserver not supported. Lazy loading disabled.');
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadElement(entry.target);
observer.unobserve(entry.target);
}
});
}, {
rootMargin: config.lazyLoad.rootMargin,
threshold: 0.01 // 只要有一小部分可见就触发
});
// 观察所有标记为懒加载的元素
document.querySelectorAll(config.lazyLoad.selector).forEach(el => observer.observe(el));
}
/**
* 根据元素类型加载其资源
* @param {Element} element - 要加载的DOM元素
*/
static loadElement(element) {
const src = element.dataset.src || element.dataset.lazySrc;
const href = element.dataset.href || element.dataset.lazyHref;
if (src) {
// 处理图片、脚本等
if (element.tagName === 'IMG') {
element.src = src;
} else if (element.tagName === 'SCRIPT') {
element.src = src;
element.async = true;
}
// 可以扩展更多类型
} else if (href) {
// 处理样式表
if (element.tagName === 'LINK' && element.rel === 'stylesheet') {
element.href = href;
}
}
// 加载完成后,可以添加一个类名表示已加载
element.classList.add('loaded');
logger.debug(`Lazy loaded: ${src || href}`);
}
}
// ========================
// 模块2: 事件处理器优化
// ========================
class EventOptimizer {
static init() {
// 优化滚动事件
window.addEventListener('scroll', utils.throttle(() => {
logger.debug('Throttled scroll event');
// 在这里可以触发滚动相关的逻辑,例如视差效果、吸顶导航等
// 但避免在此处进行复杂的DOM操作
}, config.throttleDelay));
// 优化窗口大小变化事件
window.addEventListener('resize', utils.debounce(() => {
logger.debug('Debounced resize event');
// 响应式布局调整
}, config.debounceDelay));
}
}
// ========================
// 模块3: 硬件加速优化 (谨慎使用)
// ========================
class GpuAccelerator {
static init() {
if (!config.hardwareAcceleration.enabled) return;
if (!window.IntersectionObserver) {
logger.warn('GPU Acceleration requires IntersectionObserver.');
return;
}
const className = 'gpu-accelerate';
const style = document.createElement('style');
style.textContent = `
.${className} {
/* 使用 translate3d 而非 translateZ(0) 是更常见的做法 */
transform: translate3d(0, 0, 0);
/* will-change 是提示,应动态添加 */
/* will-change: transform; */
}
`;
document.head.appendChild(style);
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const target = entry.target;
if (entry.isIntersecting) {
// 元素进入视口,添加硬件加速类和 will-change
target.classList.add(className);
target.style.willChange = 'transform';
} else {
// 元素离开视口,移除 will-change 以释放资源
target.style.willChange = 'auto';
// 保留类名以防它很快回来,或根据需要移除
// target.classList.remove(className);
}
});
}, {
rootMargin: '50px', // 在视口外50px就开始准备
threshold: 0
});
document.querySelectorAll(config.hardwareAcceleration.selector).forEach(el => observer.observe(el));
}
}
// ========================
// 模块4: Web Worker 管理器 (可选)
// ========================
class WorkerManager {
static init() {
if (!config.webWorker.enabled || !window.Worker) {
logger.warn('Web Worker is disabled or not supported.');
return;
}
// 如果用户没有提供自定义任务,则不创建Worker
if (typeof config.webWorker.customTask !== 'function') {
logger.info('No custom task provided for Web Worker.');
return;
}
// 将自定义任务的字符串表示形式注入Worker
const workerCode = `
self.onmessage = function(e) {
const result = (${config.webWorker.customTask.toString()})(e.data);
self.postMessage(result);
};
`;
try {
const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = (e) => {
logger.info('Web Worker result:', e.data);
// 在这里处理结果,例如更新UI
};
worker.onerror = (error) => {
logger.error('Web Worker error:', error);
};
// 示例:发送一个任务
// worker.postMessage(1000000);
// 将worker实例暴露,以便外部可以使用
window.PerformanceWorker = worker;
} catch (error) {
logger.error('Failed to create Web Worker:', error);
}
}
}
// ========================
// 模块5: DOM变化监听器
// ========================
class DomObserver {
static init() {
const observer = new MutationObserver(utils.throttle(() => {
// 当有新元素被添加时,重新初始化懒加载和GPU加速,以覆盖动态内容
if (config.lazyLoad.enabled) {
document.querySelectorAll(config.lazyLoad.selector)
.forEach(el => {
if (!el.dataset.observed) {
LazyLoader.init();
el.dataset.observed = 'true';
}
});
}
if (config.hardwareAcceleration.enabled) {
document.querySelectorAll(config.hardwareAcceleration.selector)
.forEach(el => {
if (!el.dataset.observed) {
GpuAccelerator.init();
el.dataset.observed = 'true';
}
});
}
}, 200)); // 避免过于频繁地触发
observer.observe(document.body, {
childList: true,
subtree: true
});
}
}
// ========================
// 主应用 - 初始化所有模块
// ========================
class App {
static init() {
logger.info('Performance Optimization Toolkit initialized.');
// 按需初始化各个模块
LazyLoader.init();
EventOptimizer.init();
GpuAccelerator.init();
WorkerManager.init();
DomObserver.init(); // 必须在最后,以监听其他模块创建的元素
// 清理
window.addEventListener('beforeunload', () => {
logger.debug('Cleaning up...');
if (window.PerformanceWorker) {
window.PerformanceWorker.terminate();
}
});
}
}
// ========================
// 启动应用
// ========================
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', App.init);
} else {
App.init();
}
// ========================
// 对外API - 允许外部调用
// ========================
// 将核心工具暴露到全局,方便在页面其他脚本中使用
window.PerformanceUtils = {
throttle: utils.throttle,
debounce: utils.debounce,
loadWithRetry: utils.loadWithRetry
};
})();