// ==UserScript==
// @name Ultimate Web Optimizer
// @namespace https://gf.qytechs.cn/zh-CN/users/1474228-moyu001
// @version 1.0
// @description 全面的网页性能优化方案(含懒加载/预加载/预连接)
// @author moyu001
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_log
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ========================
// 配置中心
// ========================
const config = {
debug: false, // 开启调试日志
features: {
lazyLoad: { // 图片懒加载
enabled: true,
minSize: 100, // 最小处理尺寸(px)
rootMargin: '200px', // 提前加载距离
skipHidden: true // 跳过隐藏图片
},
preconnect: { // 智能预连接
enabled: true,
whitelist: [ // 白名单优化
'fonts.gstatic.com',
'cdnjs.cloudflare.com',
'unpkg.com',
'ajax.googleapis.com',
'maxcdn.bootstrapcdn.com',
'code.jquery.com',
'kit.fontawesome.com',
'fonts.googleapis.cn',
'fonts.loli.net',
'cdn.jsdelivr.net',
'cdn.bootcdn.net',
'cdn.bootcss.com',
'libs.baidu.com',
'cdn.staticfile.org',
'lf3-cdn-tos.bytecdntp.com',
'unpkg.zhimg.com',
'npm.elemecdn.com',
'g.alicdn.com'
],
maxConnections: 5 // 最大预连接数
},
preload: { // 资源预加载
enabled: true,
types: ['css', 'js', 'woff2'], // 预加载类型
maxPreloads: 5 // 最大预加载数
},
layout: { // 布局稳定性
stableImages: true,
stableIframes: true
}
}
};
// ========================
// 核心优化模块
// ========================
// 图片懒加载系统
const initLazyLoad = () => {
if (!config.features.lazyLoad.enabled) return;
const isLazyCandidate = (img) => {
if (img.loading === 'eager') return false;
if (img.complete) return false;
if (img.src.startsWith('data:')) return false;
if (config.features.lazyLoad.skipHidden &&
window.getComputedStyle(img).display === 'none') return false;
const rect = img.getBoundingClientRect();
return rect.width > config.features.lazyLoad.minSize &&
rect.height > config.features.lazyLoad.minSize;
};
const processImage = (img) => {
if (!img.dataset.src && img.src) {
img.dataset.src = img.src;
img.removeAttribute('src');
}
if (img.srcset && !img.dataset.srcset) {
img.dataset.srcset = img.srcset;
img.removeAttribute('srcset');
}
return img;
};
// 现代浏览器实现
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) img.src = img.dataset.src;
if (img.dataset.srcset) img.srcset = img.dataset.srcset;
observer.unobserve(img);
}
});
}, {
rootMargin: config.features.lazyLoad.rootMargin,
threshold: 0.01
});
// 初始图片
document.querySelectorAll('img').forEach(img => {
if (isLazyCandidate(img)) {
observer.observe(processImage(img));
}
});
// 动态加载监听
new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeName === 'IMG' && isLazyCandidate(node)) {
observer.observe(processImage(node));
}
});
});
}).observe(document.body, {
childList: true,
subtree: true
});
} else {
// 兼容模式实现
const checkVisible = throttle(() => {
document.querySelectorAll('img').forEach(img => {
if (isLazyCandidate(img) && !img.src) {
const rect = img.getBoundingClientRect();
if (rect.top < window.innerHeight +
parseInt(config.features.lazyLoad.rootMargin)) {
if (img.dataset.src) img.src = img.dataset.src;
if (img.dataset.srcset) img.srcset = img.dataset.srcset;
}
}
});
}, 200);
window.addEventListener('scroll', checkVisible);
checkVisible();
}
};
// 智能预连接系统
const initSmartPreconnect = () => {
if (!config.features.preconnect.enabled) return;
const processed = new Set();
const whitelist = config.features.preconnect.whitelist;
const doPreconnect = (hostname) => {
if (processed.size >= config.features.preconnect.maxConnections) return;
if (processed.has(hostname)) return;
const link = document.createElement('link');
link.rel = 'preconnect';
link.href = `https://${hostname}`;
document.head.appendChild(link);
processed.add(hostname);
if (config.debug) {
console.log('[Preconnect] 已连接:', hostname);
}
};
const scanResources = () => {
const resources = [
...document.querySelectorAll('script[src], link[href], img[src]')
];
resources.forEach(el => {
try {
const url = new URL(el.src || el.href);
const matched = whitelist.find(domain =>
url.hostname.endsWith(domain)
);
if (matched) {
doPreconnect(url.hostname);
}
} catch {}
});
};
// 三级触发机制
scanResources(); // 立即扫描
setTimeout(scanResources, 2000); // 捕获异步资源
new MutationObserver(() => {
setTimeout(scanResources, 100);
}).observe(document.body, {
childList: true,
subtree: true
});
};
// 资源预加载系统
const initResourcePreload = () => {
if (!config.features.preload.enabled) return;
const processed = new Set();
const types = config.features.preload.types;
const max = config.features.preload.maxPreloads;
const shouldPreload = (url) => {
const ext = url.split('.').pop().toLowerCase();
return types.includes(ext);
};
const doPreload = (url, asType) => {
if (processed.size >= max) return;
if (processed.has(url)) return;
const link = document.createElement('link');
link.rel = 'preload';
link.as = asType;
link.href = url;
// 添加type属性
if (asType === 'font') {
link.setAttribute('crossorigin', 'anonymous');
if (url.includes('.woff2')) {
link.type = 'font/woff2';
} else if (url.includes('.woff')) {
link.type = 'font/woff';
}
} else if (asType === 'script') {
link.type = 'text/javascript';
} else if (asType === 'style') {
link.type = 'text/css';
}
document.head.appendChild(link);
processed.add(url);
if (config.debug) {
console.log('[Preload] 已预加载:', url);
}
};
const processFont = (cssUrl, fontUrl) => {
try {
const absoluteUrl = new URL(fontUrl, cssUrl).href;
if (fontUrl.startsWith('data:')) return; // 跳过数据URI
if (shouldPreload(absoluteUrl)) {
doPreload(absoluteUrl, 'font');
}
} catch (e) {
if (config.debug) {
console.warn('[Preload] 字体解析失败:', fontUrl, e);
}
}
};
const scanResources = () => {
// 处理CSS
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
const cssUrl = link.href;
if (cssUrl && shouldPreload(cssUrl)) {
doPreload(cssUrl, 'style');
// 解析CSS中的字体
fetch(cssUrl)
.then(res => res.text())
.then(text => {
const fontUrls = text.match(/url\(["']?([^)"']+\.woff2?)["']?\)/gi) || [];
fontUrls.forEach(fullUrl => {
const cleanUrl = fullUrl.replace(/url\(["']?|["']?\)/g, '');
processFont(cssUrl, cleanUrl);
});
})
.catch(e => {
if (config.debug) {
console.warn('[Preload] CSS获取失败:', cssUrl, e);
}
});
}
});
// 处理JS
document.querySelectorAll('script[src]').forEach(script => {
const src = script.src;
if (src && shouldPreload(src)) {
doPreload(src, 'script');
}
});
};
scanResources();
new MutationObserver(() => {
setTimeout(scanResources, 100);
}).observe(document.body, {
childList: true,
subtree: true
});
};
// 布局稳定性优化
const initLayoutStabilization = () => {
const styles = [];
if (config.features.layout.stableImages) {
styles.push(`
img:not([width]):not([height]) {
min-height: 1px;
}
@supports (aspect-ratio: 1/1) {
img:not([width]):not([height]) {
aspect-ratio: attr(width) / attr(height);
}
}
`);
}
if (config.features.layout.stableIframes) {
styles.push(`
iframe:not([width]):not([height]) {
width: 100%;
height: auto;
aspect-ratio: 16/9;
}
`);
}
if (styles.length) {
const style = document.createElement('style');
style.textContent = styles.join('\n');
document.head.appendChild(style);
}
};
// ========================
// 工具函数
// ========================
function throttle(func, limit) {
let inThrottle;
return function() {
if (!inThrottle) {
func.apply(this, arguments);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// ========================
// 初始化系统
// ========================
document.addEventListener('DOMContentLoaded', () => {
initSmartPreconnect();
initResourcePreload();
initLazyLoad();
initLayoutStabilization();
if (config.debug) {
console.groupCollapsed('[Optimizer] 初始化报告');
console.log('激活功能:', Object.entries(config.features)
.filter(([_, v]) => v.enabled !== false)
.map(([k]) => k));
console.log('预连接白名单:', config.features.preconnect.whitelist);
console.log('预加载类型:', config.features.preload.types);
console.groupEnd();
}
});
})();