// ==UserScript==
// @name Web性能综合优化工具箱
// @namespace http://tampermonkey.net/
// @version 3.2.1
// @description web浏览提速80%
// @author KiwiFruit
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
/**
* 生产级Web性能优化核心工具
* 设计理念:
* - 基于基类抽象减少重复代码
* - 显式依赖管理与生命周期控制
* - 分层错误处理(日志+UI反馈+事件通知)
* - 简化逻辑分支,提升可读性
*/
(function () {
'use strict';
// ========================
// 1. 基础工具与环境检测
// ========================
/**
* 环境检测工具(集中管理环境判断,避免重复计算)
* 作用:预计算浏览器特性、设备性能等环境信息,供各模块直接使用
*/
const Environment = {
// 浏览器特性支持
features: {
nativeLazyLoad: 'loading' in HTMLImageElement.prototype,
intersectionObserver: 'IntersectionObserver' in window,
webWorker: 'Worker' in window,
performanceObserver: 'PerformanceObserver' in window
},
// 设备性能等级(0-2:低-高)
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 Logger = {
debug: (module, msg) => {
if (Config.get('debug')) console.log(`[PerfOpt][${module}] DEBUG: ${msg}`);
},
info: (module, msg) => console.info(`[PerfOpt][${module}] INFO: ${msg}`),
warn: (module, msg) => console.warn(`[PerfOpt][${module}] WARN: ${msg}`),
error: (module, msg, error) => console.error(`[PerfOpt][${module}] ERROR: ${msg}`, error || '')
};
/**
* 配置中心(可控的状态管理)
* 改进:通过get/set方法封装配置,记录变更日志,避免直接修改
*/
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' },
webWorker: { enabled: true, customTask: null },
performanceMonitor: { enabled: false, metrics: ['fcp', 'lcp', 'cls'] }
};
return {
get(key) {
// 支持嵌套获取(如get('lazyLoad.enabled'))
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 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')));
}
}
},
// 安全解析data属性
safeGetData: (el, name, defaultValue) => {
try {
const value = el.dataset[name];
if (!value) return defaultValue;
if (value.match(/^[{[]/)) return JSON.parse(value); // 解析JSON
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. 基础类(抽象公共逻辑)
// ========================
/**
* 模块基类(统一生命周期管理)
* 解决:各模块init/destroy逻辑重复问题
*/
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() }
}));
}
}
/**
* 观察者基类(封装IntersectionObserver公共逻辑)
* 解决:LazyLoader、GpuAccelerator中观察者创建逻辑重复问题
*/
class BaseObserver extends BaseModule {
constructor(moduleName, configKey) {
super(moduleName);
this.observer = null; // 观察者实例
this.configKey = configKey; // 配置键(如'lazyLoad')
this.observers = []; // 存储所有观察者实例
}
// 创建观察者(子类实现handleIntersect回调)
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. 功能模块(基于基类实现)
// ========================
/**
* 智能懒加载模块(解决循环复杂度高、错误处理弱问题)
* 改进:用策略模式拆分元素处理逻辑,减少if-else
*/
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')) {
Logger.info(this.moduleName, '已禁用');
return;
}
// 根据环境选择加载方案
if (Environment.features.nativeLazyLoad && Config.get('lazyLoad.preferNative')) {
this.useNativeLazyLoad();
} else if (Environment.features.intersectionObserver) {
this.useObserverLazyLoad();
} else {
this.useFallbackLazyLoad();
}
}
// 原生懒加载方案
useNativeLazyLoad() {
Logger.info(this.moduleName, '使用原生懒加载方案');
document.querySelectorAll(Config.get('lazyLoad.selector')).forEach(el => {
if (['IMG', 'IFRAME'].includes(el.tagName)) {
el.loading = 'lazy';
this.loadElement(el); // 加载资源
} else {
this.loadNonMedia(el); // 非媒体元素用脚本加载
}
});
}
// Observer懒加载方案
useObserverLazyLoad() {
Logger.info(this.moduleName, '使用Observer懒加载方案');
this.createObserver(
() => {}, // handleIntersect由loadElement处理
Config.get('lazyLoad.rootMargin')
);
this.observeElements(Config.get('lazyLoad.selector'));
}
// 降级方案(滚动监听)
useFallbackLazyLoad() {
Logger.warn(this.moduleName, '使用滚动监听降级方案');
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);
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', '');
const strategy = this.loadStrategies[el.tagName]?.[src ? 'src' : 'href'];
if (strategy && (src || href)) {
strategy(el, src || href); // 执行对应策略
this.bindLoadEvents(el, src || href); // 绑定加载事件
} else {
Logger.warn(this.moduleName, `不支持的元素类型: ${el.tagName}`);
this.markFailed(el);
}
} catch (error) {
Logger.error(this.moduleName, '加载元素失败', error);
this.markFailed(el);
}
}
// 处理非媒体元素(如脚本)
loadNonMedia(el) {
const src = Utils.safeGetData(el, 'src', '');
if (el.tagName === 'SCRIPT' && src) {
const script = document.createElement('script');
script.src = src;
script.async = true;
script.onload = () => this.markLoaded(script);
script.onerror = (e) => this.markFailed(script, e);
el.parentNode.replaceChild(script, el);
}
}
// 绑定加载成功/失败事件
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 });
}
// 标记加载成功(UI反馈)
markLoaded(el) {
el.classList.add('loaded', 'lazy-loaded');
el.classList.remove('load-failed');
Logger.debug(this.moduleName, `加载成功: ${el.src || el.href}`);
}
// 标记加载失败(UI反馈)
markFailed(el, error) {
el.classList.add('load-failed');
el.classList.remove('loaded', 'lazy-loaded');
Logger.error(this.moduleName, `加载失败: ${el.src || el.href}`, error);
}
// 检查元素是否在视口(降级方案用)
isInViewport(el) {
const rect = el.getBoundingClientRect();
return rect.top <= window.innerHeight + 100 && rect.left <= window.innerWidth;
}
// 处理进入视口(Observer方案)
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;
}
}
}
/**
* 首屏关键CSS预加载模块(解决错误处理弱、结构混乱问题)
*/
class CriticalCSSLoader extends BaseModule {
constructor() {
super('CriticalCSSLoader');
this.loadedUrls = new Set(); // 已加载的CSS URL
}
init() {
super.init();
if (!Config.get('criticalCSS.enabled')) {
Logger.info(this.moduleName, '已禁用');
return;
}
const cssUrls = this.collectCriticalCSSUrls();
if (cssUrls.length === 0) {
Logger.info(this.moduleName, '未发现关键CSS资源');
return;
}
cssUrls.forEach(url => this.preloadCSS(url));
}
// 收集关键CSS URL(统一来源)
collectCriticalCSSUrls() {
const urls = new Set();
// 1. 从配置选择器收集
Config.get('criticalCSS.selectors').forEach(selector => {
document.querySelectorAll(selector).forEach(el => {
const url = Utils.safeGetData(el, 'href', '');
if (url) {
urls.add(url);
el.remove(); // 移除原元素避免重复加载
}
});
});
// 2. 从meta标签收集
const meta = document.querySelector('meta[name="critical-css"]');
if (meta) meta.content.split(',').forEach(url => url && urls.add(url.trim()));
return Array.from(urls);
}
// 预加载CSS(带超时和降级)
preloadCSS(url) {
if (this.loadedUrls.has(url)) return;
Logger.info(this.moduleName, `预加载关键CSS: ${url}`);
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)) {
Logger.error(this.moduleName, `预加载超时: ${url}`);
this.fallbackLoad(url); // 降级加载
}
}, Config.get('criticalCSS.preloadTimeout'));
// 加载成功
link.onload = () => {
clearTimeout(timeoutId);
link.rel = 'stylesheet';
this.loadedUrls.add(url);
this.emitEvent('loaded', { url });
document.body.classList.add('critical-css-loaded');
Logger.debug(this.moduleName, `预加载成功: ${url}`);
};
// 加载失败
link.onerror = () => {
clearTimeout(timeoutId);
this.fallbackLoad(url);
};
document.head.appendChild(link);
}
// 降级加载(直接作为样式表)
fallbackLoad(url) {
if (this.loadedUrls.has(url)) return;
Logger.warn(this.moduleName, `降级加载CSS: ${url}`);
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
link.onload = () => {
this.loadedUrls.add(url);
this.emitEvent('fallback-loaded', { url });
};
link.onerror = (e) => this.emitEvent('error', { url, error: e });
document.head.appendChild(link);
}
}
/**
* 事件优化模块(解决结构混乱、解耦问题)
*/
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);
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')) {
Logger.info(this.moduleName, '已禁用');
return;
}
// 低性能设备降低强度
if (Environment.isLowPerformance()) {
Logger.info(this.moduleName, '低性能设备,仅加速核心元素');
Config.set('hardwareAcceleration.selector', '.js-animate');
}
this.injectStyles();
this.createObserver(() => {}, '50px'); // 空回调,在handleIntersect处理
this.observeElements(Config.get('hardwareAcceleration.selector'));
}
// 注入硬件加速样式
injectStyles() {
this.styleEl = document.createElement('style');
this.styleEl.textContent = `
.gpu-accelerate { transform: translate3d(0,0,0); will-change: transform; }
.gpu-accelerate.inactive { will-change: auto; }
`;
document.head.appendChild(this.styleEl);
}
// 处理进入视口(启用加速)
handleIntersect(target) {
target.classList.add('gpu-accelerate');
target.classList.remove('inactive');
}
// 处理离开视口(降低强度)
handleLeave(target) {
target.classList.add('inactive');
}
destroy() {
super.destroy();
if (this.styleEl) this.styleEl.remove();
}
}
/**
* DOM变化监听模块(解决耦合问题)
*/
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 });
}
// 处理DOM变化
handleMutations(mutations) {
const addedEls = [];
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if (node.nodeType === 1) { // 元素节点
addedEls.push(node);
addedEls.push(...node.querySelectorAll('*')); // 包含子元素
}
});
});
// 通知其他模块处理新元素
if (this.lazyLoader && Config.get('lazyLoad.enabled')) {
this.lazyLoader.observeElements(Config.get('lazyLoad.selector'));
}
if (this.gpuAccelerator && Config.get('hardwareAcceleration.enabled')) {
this.gpuAccelerator.observeElements(Config.get('hardwareAcceleration.selector'));
}
}
destroy() {
super.destroy();
if (this.observer) this.observer.disconnect();
}
}
// ========================
// 4. 应用初始化(依赖管理)
// ========================
/**
* 应用控制器(解决模块依赖与初始化顺序问题)
*/
class AppController extends BaseModule {
constructor() {
super('AppController');
// 创建模块实例(显式依赖)
this.modules = {
criticalCSSLoader: new CriticalCSSLoader(),
lazyLoader: new LazyLoader(),
eventOptimizer: new EventOptimizer(),
gpuAccelerator: new GpuAccelerator(),
domObserver: new DomObserver(
this.modules.lazyLoader,
this.modules.gpuAccelerator
)
};
}
// 按依赖顺序初始化
init() {
super.init();
// 1. 关键CSS(优先级最高)
this.modules.criticalCSSLoader.init();
// 2. 懒加载与事件优化
this.modules.lazyLoader.init();
this.modules.eventOptimizer.init();
// 3. 硬件加速
this.modules.gpuAccelerator.init();
// 4. DOM观察者(最后初始化,监听其他模块)
this.modules.domObserver.init();
// 页面卸载时清理
window.addEventListener('beforeunload', () => this.destroy());
// SPA路由切换支持
window.addEventListener('spa:navigate', () => {
this.destroy();
this.init();
});
}
// 按相反顺序销毁
destroy() {
Object.values(this.modules).reverse().forEach(module => module.destroy());
super.destroy();
}
}
// ========================
// 启动应用
// ========================
function bootstrap() {
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;
}
}
// 对外API(统一暴露)
window.PerfUtils = {
getConfig: Config.getAll,
setConfig: Config.set,
throttle: Utils.throttle,
debounce: Utils.debounce,
loadWithRetry: Utils.loadWithRetry
};
bootstrap();
})();