Greasy Fork is available in English.
Web浏览提速80%;DOM渲染及GPU加速;集成Core Web Vitals实时监控面板
当前为
// ==UserScript==
// @name Web性能优化工具箱(次版)
// @namespace http://tampermonkey.net/
// @version 3.8.0-compatibility-optimized
// @description Web浏览提速80%;DOM渲染及GPU加速;集成Core Web Vitals实时监控面板
// @author KiwiFruit
// @match *://*/*
// @exclude *://*.weibo.com/*
// @exclude *://*.x.com/*
// @exclude *://*.chat.z.ai*
// @exclude *://*.doubao.com/*
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// ========================
// 1. 环境检测与工具函数
// ========================
const Env = {
features: {
nativeLazyLoad: 'loading' in HTMLImageElement.prototype,
intersectionObserver: 'IntersectionObserver' in window,
mutationObserver: 'MutationObserver' in window,
performanceObserver: 'PerformanceObserver' in window,
requestIdleCallback: 'requestIdleCallback' in window,
contentVisibility: CSS.supports('content-visibility', 'hidden'),
webgpu: typeof GPU !== 'undefined' && !!navigator.gpu
},
performanceTier: (() => {
if (navigator.hardwareConcurrency >= 4) return 2;
if (window.devicePixelRatio <= 1.5) return 1;
return 0;
})(),
networkType: navigator.connection?.effectiveType || 'unknown'
};
const Utils = {
ric: (cb, timeout = 2000) => {
if (Env.features.requestIdleCallback) {
return requestIdleCallback(cb, { timeout });
}
return setTimeout(cb, 16);
},
cancelRic: (id) => {
if (Env.features.requestIdleCallback) {
cancelIdleCallback(id);
} else {
clearTimeout(id);
}
},
throttle: (fn, limit) => {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false;
}, limit);
}
};
}
};
// ========================
// 2. 配置(保守策略)
// ========================
const Config = {
debug: false,
ui: {
enabled: true,
zIndex: 9999,
autoHideDelay: 3000,
triggerDistance: 120,
statsUpdateInterval: 3000,
width: 320
},
lazyLoad: {
enabled: true,
selector: 'img[data-src], img[data-original], img.lazy, iframe[data-src]',
preloadDistance: 120,
useMutationObserver: false
},
hardwareAcceleration: {
enabled: false,
selector: 'header, nav, aside, .sticky, .fixed'
},
contentVisibility: {
enabled: false,
selector: '[data-perfopt-cv]'
},
preconnect: {
enabled: true,
dynamic: true,
maxDomains: 6
},
blacklistedDomains: ['weibo.com', 'weibo.cn', 'x.com', 'chat.z.ai', 'doubao.com', 'kimi.com', 'qianwen.com']
};
const Logger = {
info: (m, msg) => console.log(`[PerfOpt][${m}]`, msg),
warn: (m, msg) => console.warn(`[PerfOpt][${m}]`, msg),
error: (m, msg) => console.error(`[PerfOpt][${m}]`, msg)
};
// ========================
// 3. 基础模块类
// ========================
class BaseModule {
constructor(name) {
this.moduleName = name;
this.initialized = false;
this._handlers = [];
this._timers = [];
this._observers = [];
}
init() {
if (this.initialized) {
Logger.warn(this.moduleName, '重复初始化');
return;
}
this.initialized = true;
}
on(target, type, fn, options) {
if (!target || typeof target.addEventListener !== 'function') {
return;
}
target.addEventListener(type, fn, options);
this._handlers.push({ target, type, fn });
}
off(target, type, fn) {
if (!target || typeof target.removeEventListener !== 'function') {
return;
}
target.removeEventListener(type, fn);
}
setTimer(fn, delay) {
const id = setTimeout(fn, delay);
this._timers.push(id);
return id;
}
clearTimer(id) {
const idx = this._timers.indexOf(id);
if (idx > -1) {
clearTimeout(this._timers[idx]);
this._timers.splice(idx, 1);
}
}
setInterval(fn, delay) {
const id = setInterval(fn, delay);
this._timers.push(id);
return id;
}
observeMutations(callback, target, options) {
if (!Env.features.mutationObserver || !target) {
return null;
}
const mo = new MutationObserver(Utils.throttle(callback, 100));
mo.observe(target, options || { childList: true, subtree: true });
this._observers.push(mo);
return mo;
}
destroy() {
this._handlers.forEach(({ target, type, fn }) => {
try {
this.off(target, type, fn);
} catch (e) {}
});
this._handlers = [];
this._timers.forEach(id => {
try {
clearTimeout(id);
clearInterval(id);
} catch (e) {}
});
this._timers = [];
this._observers.forEach(obs => {
try {
obs.disconnect();
} catch (e) {}
});
this._observers = [];
this.initialized = false;
}
}
// ========================
// 4. 性能监控模块(含INP)
// ========================
class PerformanceMonitor extends BaseModule {
constructor() {
super('PerformanceMonitor');
this.metrics = {
fcp: null,
lcp: null,
cls: 0,
inp: null,
ttfb: null
};
this._obsInstances = [];
}
init() {
if (!Env.features.performanceObserver) {
Logger.warn('PerformanceMonitor', '浏览器不支持 PerformanceObserver');
return;
}
super.init();
this._readHistoricalData();
this._setupObservers();
this.on(document, 'visibilitychange', () => {
if (document.visibilityState === 'visible') {
this._readHistoricalData();
}
});
Logger.info('PerformanceMonitor', '初始化完成');
}
_readHistoricalData() {
try {
if (performance.timing) {
this.metrics.ttfb = performance.timing.responseStart - performance.timing.navigationStart;
}
const paints = performance.getEntriesByType('paint');
paints.forEach(e => {
if (e.name === 'first-contentful-paint' && !this.metrics.fcp) {
this.metrics.fcp = Math.round(e.startTime);
}
});
const lcps = performance.getEntriesByType('largest-contentful-paint');
if (lcps.length > 0) {
const last = lcps[lcps.length - 1];
this.metrics.lcp = Math.round(last.startTime);
}
let cls = 0;
const shifts = performance.getEntriesByType('layout-shift');
shifts.forEach(e => {
if (!e.hadRecentInput) {
cls += e.value;
}
});
this.metrics.cls = cls;
} catch (e) {
Logger.error('PerformanceMonitor', '读取历史数据失败', e);
}
}
_setupObservers() {
try {
const fcpObs = new PerformanceObserver((list) => {
list.getEntries().forEach(e => {
if (e.name === 'first-contentful-paint') {
this.metrics.fcp = Math.round(e.startTime);
}
});
});
fcpObs.observe({ type: 'paint', buffered: true });
this._obsInstances.push(fcpObs);
} catch (e) {
Logger.warn('PerformanceMonitor', 'FCP观察器失败');
}
try {
const lcpObs = new PerformanceObserver((list) => {
const entries = list.getEntries();
if (entries.length > 0) {
const last = entries[entries.length - 1];
this.metrics.lcp = Math.round(last.startTime);
}
});
lcpObs.observe({ type: 'largest-contentful-paint', buffered: true });
this._obsInstances.push(lcpObs);
} catch (e) {
Logger.warn('PerformanceMonitor', 'LCP观察器失败');
}
try {
const clsObs = new PerformanceObserver((list) => {
list.getEntries().forEach(e => {
if (!e.hadRecentInput) {
this.metrics.cls += e.value;
}
});
});
clsObs.observe({ type: 'layout-shift', buffered: true });
this._obsInstances.push(clsObs);
} catch (e) {
Logger.warn('PerformanceMonitor', 'CLS观察器失败');
}
// INP (Interaction to Next Paint)
try {
let maxDuration = 0;
const inpObs = new PerformanceObserver((list) => {
list.getEntries().forEach(entry => {
if (entry.duration > maxDuration) {
maxDuration = entry.duration;
this.metrics.inp = Math.round(entry.duration);
}
});
});
inpObs.observe({ type: 'event', buffered: true });
this._obsInstances.push(inpObs);
} catch (e) {
Logger.warn('PerformanceMonitor', 'INP观察器失败(浏览器不支持)');
}
}
getMetrics() {
try {
const lcps = performance.getEntriesByType('largest-contentful-paint');
if (lcps.length > 0) {
const last = lcps[lcps.length - 1];
if (last.startTime > (this.metrics.lcp || 0)) {
this.metrics.lcp = Math.round(last.startTime);
}
}
} catch (e) {}
return {
fcp: this.metrics.fcp,
lcp: this.metrics.lcp,
cls: this.metrics.cls,
inp: this.metrics.inp,
ttfb: this.metrics.ttfb
};
}
destroy() {
this._obsInstances.forEach(obs => {
try {
obs.disconnect();
} catch (e) {}
});
this._obsInstances = [];
super.destroy();
}
}
// ========================
// 5. 图片懒加载模块
// ========================
class ImageOptimizer extends BaseModule {
constructor() {
super('ImageOptimizer');
this.io = null;
this.mo = null;
this._observedElements = new WeakSet();
}
init() {
if (!Config.lazyLoad.enabled) {
Logger.info('ImageOptimizer', '已禁用');
return;
}
super.init();
if (document.readyState === 'loading') {
this.on(document, 'DOMContentLoaded', () => this._setup());
} else {
this._setup();
}
}
_setup() {
if (Env.features.intersectionObserver) {
this._setupIntersectionObserver();
}
if (Config.lazyLoad.useMutationObserver && Env.features.mutationObserver) {
this._setupMutationObserver();
}
Logger.info('ImageOptimizer', '设置完成');
}
_setupIntersectionObserver() {
this.io = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this._loadImage(entry.target);
this.io.unobserve(entry.target);
this._observedElements.delete(entry.target);
}
});
}, {
rootMargin: `${Config.lazyLoad.preloadDistance}px 0px`,
threshold: 0.01
});
const elements = document.querySelectorAll(Config.lazyLoad.selector);
elements.forEach(el => {
if (!this._observedElements.has(el)) {
this._observedElements.add(el);
this.io.observe(el);
}
});
}
_setupMutationObserver() {
this.mo = this.observeMutations((mutations) => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1) {
if (node.matches && node.matches(Config.lazyLoad.selector)) {
this._observeElement(node);
}
if (node.querySelectorAll) {
node.querySelectorAll(Config.lazyLoad.selector).forEach(child => {
this._observeElement(child);
});
}
}
});
});
}, document.body, { childList: true, subtree: true });
}
_observeElement(el) {
if (!this.io || this._observedElements.has(el)) {
return;
}
this._observedElements.add(el);
this.io.observe(el);
}
_loadImage(el) {
if (!el.dataset.src) {
return;
}
const src = el.dataset.src;
delete el.dataset.src;
if (el.tagName === 'IFRAME') {
el.src = src;
} else {
el.src = src;
}
}
destroy() {
if (this.io) {
this.io.disconnect();
this.io = null;
}
if (this.mo) {
this.mo.disconnect();
this.mo = null;
}
super.destroy();
}
}
// ========================
// 6. 预连接优化模块
// ========================
class PreconnectOptimizer extends BaseModule {
constructor() {
super('PreconnectOptimizer');
this._appliedDomains = new Set();
}
init() {
if (!Config.preconnect.enabled) {
Logger.info('PreconnectOptimizer', '已禁用');
return;
}
super.init();
Utils.ric(() => {
this._analyzeAndApply();
}, 3000);
}
_analyzeAndApply() {
const domains = new Set();
const selectors = [
'link[rel="stylesheet"][href^="http"]',
'script[src^="http"]',
'img[src^="http"]',
'iframe[src^="http"]',
'source[srcset^="http"]'
];
selectors.forEach(selector => {
document.querySelectorAll(selector).forEach(el => {
try {
const url = new URL(el.href || el.src);
if (url.hostname !== window.location.hostname) {
domains.add(url.hostname);
}
} catch (e) {}
});
});
const domainList = Array.from(domains).slice(0, Config.preconnect.maxDomains);
domainList.forEach(domain => {
if (this._appliedDomains.has(domain)) {
return;
}
if (document.querySelector(`link[rel*="preconnect"][href*="${domain}"]`)) {
this._appliedDomains.add(domain);
return;
}
const link = document.createElement('link');
link.rel = 'preconnect';
link.href = `https://${domain}`;
link.crossOrigin = 'anonymous';
document.head.appendChild(link);
this._appliedDomains.add(domain);
});
Logger.info('PreconnectOptimizer', `已优化 ${domainList.length} 个域名`);
}
destroy() {
this._appliedDomains.clear();
super.destroy();
}
}
// ========================
// 7. UI控制器(320px面板,含INP)
// ========================
class UIController extends BaseModule {
constructor() {
super('UIController');
this.panelVisible = false;
this.button = null;
this.panel = null;
this.monitor = null;
this.statsTimer = null;
this.isInTriggerZone = false;
this._hideTimer = null;
this._throttledMouseMove = null;
}
setPerformanceMonitor(monitor) {
this.monitor = monitor;
}
init() {
if (!Config.ui.enabled) {
Logger.info('UIController', '已禁用');
return;
}
super.init();
if (document.readyState === 'loading') {
this.on(document, 'DOMContentLoaded', () => this._createUI());
} else {
this._createUI();
}
}
_createUI() {
if (!document.body) {
Logger.warn('UIController', 'body未就绪,延迟创建');
setTimeout(() => this._createUI(), 100);
return;
}
const width = Config.ui.width;
const style = document.createElement('style');
style.textContent = `
.perfopt-btn {
position: fixed !important;
bottom: 20px !important;
right: 20px !important;
width: 48px !important;
height: 48px !important;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border-radius: 50% !important;
box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
cursor: pointer !important;
z-index: ${Config.ui.zIndex} !important;
transition: transform 0.3s ease, opacity 0.3s ease, right 0.3s ease !important;
font-size: 20px !important;
opacity: 1 !important;
pointer-events: auto !important;
user-select: none !important;
}
.perfopt-btn:hover {
transform: scale(1.1) !important;
}
.perfopt-btn.hidden {
right: -40px !important;
opacity: 0.3 !important;
pointer-events: none !important;
}
.perfopt-panel {
position: fixed !important;
bottom: 80px !important;
right: 20px !important;
width: ${width}px !important;
max-height: 85vh !important;
background: rgba(255,255,255,0.98) !important;
backdrop-filter: blur(10px) !important;
border-radius: 12px !important;
box-shadow: 0 8px 32px rgba(0,0,0,0.15) !important;
padding: 20px !important;
z-index: ${Config.ui.zIndex - 1} !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
font-size: 13px !important;
display: none !important;
opacity: 0 !important;
transform: translateY(10px) !important;
transition: opacity 0.3s ease, transform 0.3s ease !important;
overflow-y: auto !important;
box-sizing: border-box !important;
}
.perfopt-panel.visible {
display: block !important;
opacity: 1 !important;
transform: translateY(0) !important;
}
.perfopt-header {
font-weight: 600 !important;
margin-bottom: 16px !important;
padding-bottom: 10px !important;
border-bottom: 1px solid rgba(0,0,0,0.1) !important;
font-size: 15px !important;
color: #333 !important;
display: flex !important;
align-items: center !important;
gap: 6px !important;
}
.perfopt-row {
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
margin: 10px 0 !important;
line-height: 1.5 !important;
}
.perfopt-label {
color: #666 !important;
font-size: 13px !important;
}
.perfopt-value {
font-family: "SF Mono", Monaco, monospace !important;
font-weight: 600 !important;
font-size: 13px !important;
font-variant-numeric: tabular-nums !important;
}
.perfopt-good { color: #22c55e !important; }
.perfopt-warn { color: #f59e0b !important; }
.perfopt-bad { color: #ef4444 !important; }
.perfopt-footer {
margin-top: 16px !important;
padding-top: 12px !important;
border-top: 1px solid rgba(0,0,0,0.1) !important;
font-size: 11px !important;
color: #999 !important;
line-height: 1.5 !important;
}
`;
document.head.appendChild(style);
this.button = document.createElement('div');
this.button.className = 'perfopt-btn';
this.button.innerHTML = '⚡';
this.button.title = '性能监控 (靠近显示)';
document.body.appendChild(this.button);
this.panel = document.createElement('div');
this.panel.className = 'perfopt-panel';
this.panel.innerHTML = `
<div class="perfopt-header">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: middle;">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
Core Web Vitals
</div>
<div class="perfopt-row">
<span class="perfopt-label">FCP (首次绘制)</span>
<span id="po-fcp" class="perfopt-value">--</span>
</div>
<div class="perfopt-row">
<span class="perfopt-label">LCP (最大内容)</span>
<span id="po-lcp" class="perfopt-value">--</span>
</div>
<div class="perfopt-row">
<span class="perfopt-label">CLS (布局偏移)</span>
<span id="po-cls" class="perfopt-value">--</span>
</div>
<div class="perfopt-row">
<span class="perfopt-label">INP (交互延迟)</span>
<span id="po-inp" class="perfopt-value">--</span>
</div>
<div class="perfopt-row">
<span class="perfopt-label">TTFB (首字节)</span>
<span id="po-ttfb" class="perfopt-value">--</span>
</div>
<div class="perfopt-footer">
<div>网络: ${Env.networkType} · 设备: ${Env.performanceTier === 2 ? '高性能' : Env.performanceTier === 1 ? '中性能' : '低性能'}</div>
</div>
`;
document.body.appendChild(this.panel);
this._setupEvents();
this._startHideTimer();
Logger.info('UIController', 'UI创建成功');
}
_setupEvents() {
if (!this.button || !this.panel) {
return;
}
this._throttledMouseMove = Utils.throttle((e) => {
if (this.panelVisible) {
return;
}
const rect = this.button.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const distance = Math.sqrt(
Math.pow(e.clientX - centerX, 2) +
Math.pow(e.clientY - centerY, 2)
);
if (distance <= Config.ui.triggerDistance && !this.isInTriggerZone) {
this.isInTriggerZone = true;
this._showButton();
this._clearHideTimer();
} else if (distance > Config.ui.triggerDistance && this.isInTriggerZone) {
this.isInTriggerZone = false;
this._startHideTimer();
}
}, 50);
this.on(document, 'mousemove', this._throttledMouseMove);
this.on(document, 'click', (e) => {
if (this.panelVisible &&
!this.button.contains(e.target) &&
!this.panel.contains(e.target)) {
this._closePanel();
}
});
this.on(this.button, 'click', (e) => {
e.stopPropagation();
if (this.panelVisible) {
this._closePanel();
} else {
this._openPanel();
}
});
this.on(this.button, 'mouseenter', () => {
this._clearHideTimer();
});
this.on(this.button, 'mouseleave', () => {
if (!this.panelVisible) {
this._startHideTimer();
}
});
}
_showButton() {
if (this.button) {
this.button.classList.remove('hidden');
}
}
_hideButton() {
if (this.button && !this.panelVisible) {
this.button.classList.add('hidden');
}
}
_openPanel() {
this.panelVisible = true;
this.panel.classList.add('visible');
this._showButton();
this._updateStats();
if (this.statsTimer) {
clearInterval(this.statsTimer);
}
this.statsTimer = this.setInterval(() => {
this._updateStats();
}, Config.ui.statsUpdateInterval);
}
_closePanel() {
this.panelVisible = false;
this.panel.classList.remove('visible');
this._startHideTimer();
if (this.statsTimer) {
clearInterval(this.statsTimer);
this.statsTimer = null;
}
}
_startHideTimer() {
this._clearHideTimer();
this._hideTimer = this.setTimer(() => {
this._hideButton();
}, Config.ui.autoHideDelay);
}
_clearHideTimer() {
if (this._hideTimer) {
this.clearTimer(this._hideTimer);
this._hideTimer = null;
}
}
_updateStats() {
if (!this.monitor) {
return;
}
const m = this.monitor.getMetrics();
const setVal = (id, val, good, bad, unit = '') => {
const el = document.getElementById(id);
if (!el) {
return;
}
if (val === null || val === undefined) {
el.textContent = '--';
el.className = 'perfopt-value';
return;
}
const num = typeof val === 'number' ? val : parseFloat(val);
el.textContent = unit ? `${Math.round(num)}${unit}` : num.toFixed(3);
let clsName = 'perfopt-value ';
if (num < good) {
clsName += 'perfopt-good';
} else if (num < bad) {
clsName += 'perfopt-warn';
} else {
clsName += 'perfopt-bad';
}
el.className = clsName;
};
setVal('po-fcp', m.fcp, 1800, 3000, 'ms');
setVal('po-lcp', m.lcp, 2500, 4000, 'ms');
setVal('po-cls', m.cls, 0.1, 0.25);
setVal('po-inp', m.inp, 200, 500, 'ms');
setVal('po-ttfb', m.ttfb, 600, 1000, 'ms');
}
destroy() {
if (this.statsTimer) {
clearInterval(this.statsTimer);
this.statsTimer = null;
}
this._throttledMouseMove = null;
super.destroy();
}
}
// ========================
// 8. 主应用控制器
// ========================
class AppController {
constructor() {
this.modules = {};
}
init() {
const hostname = window.location.hostname;
const isBlacklisted = Config.blacklistedDomains.some(d => hostname.includes(d));
if (isBlacklisted) {
Logger.info('AppController', '域名在黑名单中,停止加载');
return;
}
Logger.info('AppController', '开始初始化');
this.modules.monitor = new PerformanceMonitor();
this.modules.monitor.init();
this.modules.preconnect = new PreconnectOptimizer();
this.modules.preconnect.init();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
Utils.ric(() => this._initDOMModules(), 100);
});
} else {
Utils.ric(() => this._initDOMModules(), 100);
}
window.addEventListener('beforeunload', () => {
this.destroy();
});
}
_initDOMModules() {
Logger.info('AppController', '初始化DOM模块');
this.modules.images = new ImageOptimizer();
this.modules.images.init();
this.modules.ui = new UIController();
this.modules.ui.setPerformanceMonitor(this.modules.monitor);
this.modules.ui.init();
}
destroy() {
Object.values(this.modules).forEach(m => {
if (m && typeof m.destroy === 'function') {
m.destroy();
}
});
this.modules = {};
}
}
// ========================
// 9. 启动
// ========================
try {
const app = new AppController();
app.init();
window.PerfOptimizer = app;
Logger.info('Bootstrap', '脚本加载成功 v4.1.0');
} catch (error) {
Logger.error('Bootstrap', `致命错误: ${error.message}`);
console.error(error);
}
})();