// ==UserScript==
// @name Ultimate Web Optimizer
// @namespace https://greasyfork.org/zh-CN/users/1474228-moyu001
// @version 1.1
// @description 全面的网页性能优化方案(含懒加载/预加载/预连接/资源回收/中国平台优化)
// @author moyu001
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_log
// @grant unsafeWindow
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// ========================
// 配置中心
// ========================
const config = {
debug: false, // 确保调试模式已开启
features: {
lazyLoad: {
enabled: true,
minSize: 100,
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',
// 中国CDN优化
'alicdn.com',
'bdstatic.com',
'sinaimg.cn',
'sogoucdn.com',
'bytedance.com',
'bytecdn.cn',
'pstatp.com',
'qpic.cn',
'hdslb.com',
'bilivideo.com',
'tencent-cloud.net',
'qcloud.com'
],
maxConnections: 8
},
preload: {
enabled: true,
types: ['css', 'js', 'woff2'],
maxPreloads: 6
},
layout: {
stableImages: true,
stableIframes: true,
stableVideos: true
},
captcha: {
enabled: true,
autoDetect: true,
safeMode: true
},
resourceRecycling: {
enabled: true,
memoryThreshold: 75,
scrollRecycleMargin: 500,
videoRecycleMargin: 1000,
monitorInterval: 5000,
maxBackgroundVideos: 2
},
videoRecycling: {
enabled: true,
protectPlaying: true,
protectVisible: true,
restoreOnScroll: true
}
},
networkAware: {
enabled: true,
connectionTypes: {
'slow-2g': {
preload: false,
lazyMargin: '500px'
},
'2g': {
preload: true,
maxPreloads: 3
},
'3g': {
preload: true,
maxPreloads: 4
},
'4g': {
preload: true,
maxPreloads: 8
}
}
},
chinaPlatforms: {
enabled: true,
platforms: {
taobao: ['taobao.com', 'tmall.com'],
jd: ['jd.com'],
douyin: ['douyin.com'],
bilibili: ['bilibili.com'],
baidu: ['baidu.com'],
weibo: ['weibo.com'],
tencent: ['qq.com'],
pinduoduo: ['pinduoduo.com'],
kuaishou: ['kuaishou.com']
}
}
};
// 公共API对象 - 用于暴露内部方法
const publicAPI = {
triggerRecycling: null
};
// 添加调试输出函数
const debugLog = (...args) => {
if (config.debug) {
console.log('[Optimizer]', ...args);
}
};
// 添加调试警告函数
const debugWarn = (...args) => {
if (config.debug) {
console.warn('[Optimizer]', ...args);
}
};
// ========================
// 控制台调试命令系统
// ========================
const initConsoleCommands = () => {
// 确保只初始化一次
if (unsafeWindow.__optimizerCommands) {
debugLog('控制台命令已初始化,跳过重复执行'); // 新增调试日志
return;
}
unsafeWindow.__optimizerCommands = true; // 修改:挂载到 unsafeWindow
// 优化状态查看
unsafeWindow.optimizerStatus = () => { // 修改:挂载到 unsafeWindow
const status = {
lazyLoad: {
enabled: config.features.lazyLoad.enabled,
images: document.querySelectorAll('img[data-src]').length
},
preconnect: {
enabled: config.features.preconnect.enabled,
connections: document.querySelectorAll('link[rel="preconnect"]').length
},
preload: {
enabled: config.features.preload.enabled,
resources: document.querySelectorAll('link[rel="preload"]').length
},
resourceRecycling: {
enabled: config.features.resourceRecycling.enabled,
recycled: document.querySelectorAll('img[data-src]:not([src]), video[data-recycled-state]').length
},
chinaPlatform: isChinaPlatform() || '未检测到'
};
console.groupCollapsed('[Optimizer] 当前状态');
console.table(status);
console.groupEnd();
return status;
};
// 中国平台检测
unsafeWindow.checkChinaPlatform = () => {
const platform = isChinaPlatform();
if (platform) {
console.log(`检测到中国平台: ${platform}`);
} else {
console.log('未检测到支持的中国平台');
}
return platform;
};
// 临时禁用优化器
unsafeWindow.disableOptimizer = () => {
Object.keys(config.features).forEach(key => {
config.features[key].enabled = false;
});
console.warn('优化器已临时禁用,刷新页面后恢复');
};
// 强制资源回收
unsafeWindow.forceRecycle = () => {
if (publicAPI.triggerRecycling) {
publicAPI.triggerRecycling();
console.log('资源回收已手动触发');
} else {
console.warn('资源回收功能未启用');
}
};
console.log('优化器控制台命令已启用: optimizerStatus(), checkChinaPlatform(), disableOptimizer(), forceRecycle()');
debugLog('控制台命令初始化完成'); // 新增调试日志
};
// 在脚本加载后立即初始化控制台命令
initConsoleCommands();
// ========================
// 工具函数
// ========================
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
function isElementInViewport(el, margin = 0) {
if (!el) return false;
const rect = el.getBoundingClientRect();
return (
rect.top <= (window.innerHeight + margin) &&
rect.left <= (window.innerWidth + margin) &&
rect.bottom >= -margin &&
rect.right >= -margin
);
}
const recyclingGuard = (() => {
let lastRecycleTime = 0;
const minRecycleInterval = 10000;
return {
canRecycle: () => {
const now = Date.now();
if (now - lastRecycleTime > minRecycleInterval) {
lastRecycleTime = now;
return true;
}
return false;
}
};
})();
// ========================
// 中国平台检测与优化
// ========================
const isChinaPlatform = () => {
const host = window.location.hostname;
const platforms = config.chinaPlatforms.platforms;
for (const platform in platforms) {
if (platforms[platform].some(domain => host.includes(domain))) {
debugLog(`检测到中国平台: ${platform}`);
return platform;
}
}
debugLog('未检测到中国平台');
return false;
};
const applyChinaPlatformOptimizations = () => {
if (!config.chinaPlatforms.enabled) {
debugLog('中国平台优化已禁用');
return;
}
const platform = isChinaPlatform();
if (!platform) return;
debugLog(`应用中国平台优化策略: ${platform}`);
// 平台特定优化
switch(platform) {
case 'taobao':
config.features.lazyLoad.rootMargin = '500px';
document.querySelectorAll('.J_ImgSwitcher, .detail-img').forEach(img => {
img.dataset.skipLazy = 'true';
});
debugLog('淘宝优化已应用');
break;
case 'jd':
config.features.preload.maxPreloads = 8;
document.querySelectorAll('#preview img').forEach(img => {
img.dataset.skipLazy = 'true';
});
debugLog('京东优化已应用');
break;
case 'douyin':
config.features.resourceRecycling.maxBackgroundVideos = 1;
const douyinPlayer = document.querySelector('.xgplayer-container video');
if (douyinPlayer) douyinPlayer.dataset.protected = 'true';
debugLog('抖音优化已应用');
break;
case 'bilibili':
const bilibiliPlayer = document.querySelector('.bpx-player-video-wrap video');
if (bilibiliPlayer) bilibiliPlayer.dataset.protected = 'true';
// 弹幕优化
const danmuContainer = document.querySelector('.bpx-player-dm-wrap');
if (danmuContainer) danmuContainer.dataset.optimizeLayout = 'true';
debugLog('哔哩哔哩优化已应用');
break;
case 'baidu':
document.querySelectorAll('.c-img').forEach(img => {
img.loading = 'eager';
});
debugLog('百度优化已应用');
break;
case 'weibo':
config.features.lazyLoad.rootMargin = '500px';
document.querySelectorAll('.avator, .avatar').forEach(img => {
img.dataset.skipLazy = 'true';
});
debugLog('微博优化已应用');
break;
case 'pinduoduo':
config.features.resourceRecycling.memoryThreshold = 70;
document.querySelectorAll('.goods-img').forEach(img => {
img.dataset.skipLazy = 'true';
});
debugLog('拼多多优化已应用');
break;
case 'kuaishou':
config.features.resourceRecycling.videoRecycleMargin = 1000;
const kuaishouPlayer = document.querySelector('.player-container video');
if (kuaishouPlayer) kuaishouPlayer.dataset.protected = 'true';
// 快手视频列表优化
const videoList = document.querySelector('.video-list');
if (videoList) {
videoList.dataset.optimizeLayout = 'true';
}
debugLog('快手优化已应用');
break;
case 'tencent':
// 腾讯视频优化
const tencentPlayer = document.querySelector('#txp_player video');
if (tencentPlayer) tencentPlayer.dataset.protected = 'true';
// 腾讯视频CDN预连接
config.features.preconnect.whitelist.push('qpic.cn', 'vpic.video.qq.com');
debugLog('腾讯优化已应用');
break;
}
// 通用中国平台优化
config.features.preconnect.maxConnections = 8;
config.features.preload.maxPreloads = 6;
config.features.resourceRecycling.memoryThreshold = 80;
debugLog('通用中国平台优化已应用');
};
// ========================
// 核心优化模块
// ========================
// 图片懒加载系统
const initLazyLoad = () => {
if (!config.features.lazyLoad.enabled) {
debugLog('图片懒加载已禁用');
return;
}
debugLog('初始化图片懒加载系统');
const isLazyCandidate = (img) => {
if (img.loading === 'eager') return false;
if (img.complete) return false;
if (img.src.startsWith('data:')) return false;
if (img.classList.contains('captcha-image')) return false;
if (img.dataset.skipLazy === 'true') 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;
if (img.crossOrigin) {
img.dataset.crossOrigin = img.crossOrigin;
}
img.removeAttribute('src');
}
if (img.srcset && !img.dataset.srcset) {
img.dataset.srcset = img.srcset;
img.removeAttribute('srcset');
}
return img;
};
// 现代浏览器实现
if ('IntersectionObserver' in window) {
debugLog('使用IntersectionObserver实现懒加载');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
if (img.dataset.crossOrigin) {
img.crossOrigin = img.dataset.crossOrigin;
}
img.src = img.dataset.src;
debugLog(`懒加载图片: ${img.dataset.src}`);
}
if (img.dataset.srcset) {
img.srcset = img.dataset.srcset;
debugLog(`懒加载图片集: ${img.dataset.srcset}`);
}
observer.unobserve(img);
}
});
}, {
rootMargin: config.features.lazyLoad.rootMargin,
threshold: 0.01
});
// 初始图片
const images = document.querySelectorAll('img');
debugLog(`发现${images.length}张图片,正在筛选懒加载候选`);
let lazyCount = 0;
images.forEach(img => {
if (isLazyCandidate(img)) {
observer.observe(processImage(img));
lazyCount++;
}
});
debugLog(`已启用${lazyCount}张图片的懒加载`);
// 动态加载监听
const mutationObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeName === 'IMG' && isLazyCandidate(node)) {
observer.observe(processImage(node));
debugLog('动态添加的图片已启用懒加载');
}
});
});
});
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
debugLog('已启动动态图片监听');
// 清理钩子
window.addEventListener('beforeunload', () => {
observer.disconnect();
mutationObserver.disconnect();
debugLog('懒加载系统已清理');
});
} else {
debugLog('使用兼容模式实现懒加载');
// 兼容模式实现
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) {
if (img.dataset.crossOrigin) {
img.crossOrigin = img.dataset.crossOrigin;
}
img.src = img.dataset.src;
debugLog(`兼容模式加载图片: ${img.dataset.src}`);
}
if (img.dataset.srcset) {
img.srcset = img.dataset.srcset;
debugLog(`兼容模式加载图片集: ${img.dataset.srcset}`);
}
}
}
});
}, 200);
// 添加动态图片监听
const mutationObserver = new MutationObserver(() => checkVisible());
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
window.addEventListener('scroll', checkVisible);
window.addEventListener('resize', checkVisible);
checkVisible();
debugLog('兼容模式懒加载已启动');
}
};
// 智能预连接系统
const initSmartPreconnect = () => {
if (!config.features.preconnect.enabled) {
debugLog('预连接系统已禁用');
return;
}
debugLog('初始化智能预连接系统');
const processed = new Set();
const whitelist = config.features.preconnect.whitelist;
const doPreconnect = (hostname) => {
if (processed.size >= config.features.preconnect.maxConnections) {
debugWarn(`已达到最大预连接数 (${config.features.preconnect.maxConnections})`);
return;
}
if (processed.has(hostname)) {
debugLog(`已存在预连接: ${hostname}`);
return;
}
const link = document.createElement('link');
link.rel = 'preconnect';
link.href = `//${hostname}`;
document.head.appendChild(link);
processed.add(hostname);
debugLog(`已创建预连接: ${hostname}`);
};
const scanResources = () => {
debugLog('扫描资源进行预连接');
const resources = [
...document.querySelectorAll('script[src], link[href], img[src]')
];
let found = 0;
resources.forEach(el => {
try {
const url = new URL(el.src || el.href, window.location.href);
const hostname = url.hostname;
const matched = whitelist.find(domain =>
hostname.endsWith(domain)
);
if (matched) {
found++;
doPreconnect(hostname);
}
} catch (e) {
debugWarn('资源URL解析失败', e);
}
});
debugLog(`扫描完成,发现${found}个可预连接资源`);
};
// 三级触发机制
scanResources();
setTimeout(scanResources, 2000);
const mutationObserver = new MutationObserver(() => {
setTimeout(scanResources, 100);
});
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
debugLog('已启动资源变化监听');
};
// 资源预加载系统
const initResourcePreload = () => {
if (!config.features.preload.enabled) {
debugLog('资源预加载已禁用');
return;
}
debugLog('初始化资源预加载系统');
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) {
debugWarn(`已达到最大预加载数 (${max})`);
return;
}
if (processed.has(url)) {
debugLog(`资源已预加载: ${url}`);
return;
}
const link = document.createElement('link');
link.rel = 'preload';
link.as = asType;
link.href = url;
// 跨域资源处理
try {
const parsedUrl = new URL(url, window.location.href);
if (parsedUrl.origin !== window.location.origin) {
if (asType === 'font') {
link.setAttribute('crossorigin', 'anonymous');
} else if (asType === 'script' || asType === 'style') {
link.crossOrigin = 'anonymous';
}
debugLog(`跨域资源处理: ${url}`);
}
} catch (e) {
debugWarn('URL解析失败', e);
}
document.head.appendChild(link);
processed.add(url);
debugLog(`已预加载资源: ${url} (类型: ${asType})`);
};
const processFont = (cssUrl, fontUrl) => {
try {
const absoluteUrl = new URL(fontUrl, cssUrl).href;
if (fontUrl.startsWith('data:')) return;
if (shouldPreload(absoluteUrl)) {
doPreload(absoluteUrl, 'font');
}
} catch (e) {
debugWarn(`字体解析失败: ${fontUrl}`, e);
}
};
const scanResources = () => {
debugLog('扫描资源进行预加载');
let preloadCount = 0;
// 处理CSS
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
const cssUrl = link.href;
if (cssUrl && shouldPreload(cssUrl)) {
preloadCount++;
doPreload(cssUrl, 'style');
// 解析CSS中的字体
if (types.includes('woff2')) {
fetch(cssUrl, { mode: 'cors' })
.then(res => res.text())
.then(text => {
const fontUrls = text.match(/url$["']?([^)"']+\.woff2?)["']?$/gi) || [];
debugLog(`在CSS中发现${fontUrls.length}个字体资源`);
fontUrls.forEach(fullUrl => {
const cleanUrl = fullUrl.replace(/url$["']?|["']?$/g, '');
processFont(cssUrl, cleanUrl);
});
})
.catch(e => {
debugWarn(`CSS获取失败: ${cssUrl}`, e);
});
}
}
});
// 处理JS
document.querySelectorAll('script[src]').forEach(script => {
const src = script.src;
if (src && shouldPreload(src)) {
preloadCount++;
doPreload(src, 'script');
}
});
debugLog(`扫描完成,预加载了${preloadCount}个资源`);
};
scanResources();
const mutationObserver = new MutationObserver(() => {
setTimeout(scanResources, 100);
});
mutationObserver.observe(document.body, {
childList: true,
subtree: true
});
debugLog('已启动资源变化监听');
};
// 布局稳定性优化
const initLayoutStabilization = () => {
debugLog('初始化布局稳定性优化');
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);
}
}
`);
debugLog('已添加图片布局稳定性规则');
}
if (config.features.layout.stableIframes) {
styles.push(`
iframe:not([width]):not([height]) {
width: 100%;
height: auto;
aspect-ratio: 16/9;
}
`);
debugLog('已添加iframe布局稳定性规则');
}
if (config.features.layout.stableVideos) {
styles.push(`
video:not([width]):not([height]) {
max-width: 100%;
aspect-ratio: 16/9;
}
`);
debugLog('已添加视频布局稳定性规则');
}
if (styles.length) {
const style = document.createElement('style');
style.textContent = styles.join('\n');
document.head.appendChild(style);
debugLog('布局稳定性样式已注入');
} else {
debugLog('未添加任何布局稳定性规则');
}
};
// CAPTCHA 保护系统
const initCaptchaProtection = () => {
if (!config.features.captcha.enabled) {
debugLog('验证码保护系统已禁用');
return;
}
debugLog('初始化验证码保护系统');
// 常见验证码特征库
const CAPTCHA_FINGERPRINTS = [
/recaptcha\/api\.js/i,
/recaptcha\/enterprise\.js/i,
/gstatic\.com\/recaptcha/,
/recaptcha\/anchor\?/,
/hcaptcha\.com\/1\/api\.js/,
/hcaptcha\.com\/challenge\.css/,
/challenges\.cloudflare\.com\/turnstile/,
/challenges\.cloudflare\.com\/style/,
/\/captcha\.(js|css)/i,
/verify\.(png|jpg|gif)\?/i
];
// 检测当前页面是否有验证码
const hasCaptcha = () => {
const htmlContent = document.documentElement.innerHTML;
const scripts = Array.from(document.scripts);
const found = CAPTCHA_FINGERPRINTS.some(pattern =>
htmlContent.match(pattern) ||
scripts.some(script => script.src && script.src.match(pattern))
);
if (found) {
debugLog('检测到验证码系统');
} else {
debugLog('未检测到验证码系统');
}
return found;
};
// 暂停可能干扰验证码的功能
const disableRiskyFeatures = () => {
if (config.features.captcha.safeMode) {
const originalLazyLoad = config.features.lazyLoad.enabled;
const originalPreload = config.features.preload.enabled;
config.features.lazyLoad.enabled = false;
config.features.preload.enabled = false;
debugWarn('验证码保护模式激活,已禁用懒加载和预加载');
// 恢复原始状态(在页面卸载时)
window.addEventListener('beforeunload', () => {
config.features.lazyLoad.enabled = originalLazyLoad;
config.features.preload.enabled = originalPreload;
debugLog('验证码保护模式已解除');
});
}
};
// 恢复验证码 iframe 的默认样式
const restoreCaptchaFrames = () => {
const frames = document.querySelectorAll('iframe');
let restoredCount = 0;
frames.forEach(frame => {
if (frame.src && CAPTCHA_FINGERPRINTS.some(p => frame.src.match(p))) {
frame.style.aspectRatio = '';
frame.style.minHeight = '';
frame.classList.add('captcha-protected');
restoredCount++;
}
});
if (restoredCount > 0) {
debugLog(`已恢复${restoredCount}个验证码框架的默认样式`);
}
};
if (hasCaptcha()) {
disableRiskyFeatures();
restoreCaptchaFrames();
}
};
// 资源回收系统
const initResourceRecycling = () => {
if (!config.features.resourceRecycling.enabled) return;
debugLog('初始化资源回收系统');
let memoryMonitor;
const resourceMap = new WeakMap();
const recycleThreshold = config.features.resourceRecycling.memoryThreshold;
// 视频资源回收策略
const videoRecycling = {
recycle: (video) => {
video.dataset.recycledState = JSON.stringify({
currentTime: video.currentTime,
volume: video.volume,
playbackRate: video.playbackRate,
paused: video.paused,
crossOrigin: video.crossOrigin,
credentials: video.getAttribute('crossorigin')
});
video.pause();
video.removeAttribute('src');
video.load();
debugLog(`视频资源已卸载: ${video.id || video.dataset.src || '匿名视频'}`);
},
condition: (video) => {
if (video.dataset.protected === 'true') {
debugLog(`视频受保护,跳过回收: ${video.id || video.dataset.src || '匿名视频'}`);
return false;
}
if (config.features.videoRecycling.protectPlaying && !video.paused) {
debugLog(`视频正在播放,跳过回收: ${video.id || video.dataset.src || '匿名视频'}`);
return false;
}
if (video.webkitDisplayingFullscreen ||
video === document.pictureInPictureElement) {
debugLog(`视频全屏/PiP模式,跳过回收: ${video.id || video.dataset.src || '匿名视频'}`);
return false;
}
if (video.dataset.userActivated === 'true') {
debugLog(`视频用户激活,跳过回收: ${video.id || video.dataset.src || '匿名视频'}`);
return false;
}
const inViewport = isElementInViewport(video, config.features.resourceRecycling.videoRecycleMargin);
if (inViewport) {
debugLog(`视频在可视区域内,跳过回收: ${video.id || video.dataset.src || '匿名视频'}`);
return false;
}
debugLog(`视频符合回收条件: ${video.id || video.dataset.src || '匿名视频'}`);
return true;
},
restore: (video) => {
if (video.dataset.src) {
video.src = video.dataset.src;
video.load();
if (video.dataset.recycledState) {
const state = JSON.parse(video.dataset.recycledState);
video.currentTime = state.currentTime;
video.volume = state.volume;
video.playbackRate = state.playbackRate;
if (state.crossOrigin) {
video.crossOrigin = state.crossOrigin;
}
if (state.credentials) {
video.setAttribute('crossorigin', state.credentials);
}
if (!state.paused) {
video.play().catch(e => {
debugWarn(`视频自动播放失败: ${e.message}`);
});
}
}
delete video.dataset.recycledState;
debugLog(`视频资源已恢复: ${video.id || video.src || '匿名视频'}`);
}
}
};
// 图片资源回收策略
const imageRecycling = {
recycle: (img) => {
if (img.dataset.src && img.src) {
img.removeAttribute('src');
if (img.dataset.srcset) {
img.removeAttribute('srcset');
}
debugLog(`图片资源已卸载: ${img.dataset.src}`);
}
},
condition: (img) => {
if (img.classList.contains('captcha-image') ||
img.closest('.captcha-container')) {
debugLog('验证码图片,跳过回收');
return false;
}
if (img.dataset.skipRecycle === 'true') {
debugLog('图片标记为不可回收');
return false;
}
const rect = img.getBoundingClientRect();
const shouldRecycle = rect.bottom < -config.features.resourceRecycling.scrollRecycleMargin ||
rect.top > window.innerHeight + config.features.resourceRecycling.scrollRecycleMargin;
if (shouldRecycle) {
debugLog(`图片符合回收条件: ${img.dataset.src || img.src}`);
}
return shouldRecycle;
}
};
// 启动内存监控
const startMemoryMonitor = () => {
if (window.performance && performance.memory) {
debugLog('启动内存监控');
memoryMonitor = setInterval(() => {
const usedJSHeap = performance.memory.usedJSHeapSize;
const totalJSHeap = performance.memory.totalJSHeapSize;
if (totalJSHeap > 0) {
const usagePercent = (usedJSHeap / totalJSHeap) * 100;
if (usagePercent > recycleThreshold) {
debugWarn(`内存使用率过高: ${usagePercent.toFixed(1)}% > ${recycleThreshold}%,触发资源回收`);
triggerRecycling();
}
}
}, config.features.resourceRecycling.monitorInterval);
} else {
debugWarn('浏览器不支持performance.memory,内存监控不可用');
}
};
// 触发资源回收
publicAPI.triggerRecycling = () => {
if (!recyclingGuard.canRecycle()) {
return;
}
debugLog('开始资源回收');
let recycledCount = 0;
// 图片资源回收
document.querySelectorAll('img[data-src]').forEach(img => {
if (imageRecycling.condition(img)) {
imageRecycling.recycle(img);
recycledCount++;
}
});
// 视频资源回收
if (config.features.videoRecycling.enabled) {
const videos = Array.from(document.querySelectorAll('video'));
// 按可见性排序(从最不可见到最可见)
videos.sort((a, b) => {
const rectA = a.getBoundingClientRect();
const rectB = b.getBoundingClientRect();
const distanceA = Math.min(
Math.abs(rectA.top - window.innerHeight),
Math.abs(rectA.bottom)
);
const distanceB = Math.min(
Math.abs(rectB.top - window.innerHeight),
Math.abs(rectB.bottom)
);
return distanceB - distanceA; // 降序排序
});
// 回收超出最大限制的视频
const maxVideos = config.features.resourceRecycling.maxBackgroundVideos;
for (let i = maxVideos; i < videos.length; i++) {
const video = videos[i];
if (videoRecycling.condition(video)) {
videoRecycling.recycle(video);
recycledCount++;
}
}
}
// 强制垃圾回收
if (window.gc) {
window.gc();
debugLog('已执行强制垃圾回收');
}
debugLog(`资源回收完成,释放了${recycledCount}个资源`);
};
// 集成到懒加载系统
const patchLazyLoad = () => {
if (!('IntersectionObserver' in window)) {
debugLog('浏览器不支持IntersectionObserver,跳过懒加载补丁');
return;
}
debugLog('修补懒加载系统以支持资源回收');
const originalObserve = IntersectionObserver.prototype.observe;
IntersectionObserver.prototype.observe = function(element) {
resourceMap.set(element, this);
originalObserve.call(this, element);
};
IntersectionObserver.prototype.unobserveAndRecycle = function(element) {
if (imageRecycling.condition(element)) {
imageRecycling.recycle(element);
}
this.unobserve(element);
};
};
// 视频恢复系统
const initVideoRestoration = () => {
if (!config.features.videoRecycling.restoreOnScroll) {
debugLog('滚动恢复视频功能已禁用');
return;
}
debugLog('初始化视频滚动恢复系统');
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const video = entry.target;
if (video.dataset.recycledState) {
videoRecycling.restore(video);
videoObserver.unobserve(video);
}
}
});
}, { rootMargin: '200px' });
const videos = document.querySelectorAll('video[data-recycled-state]');
videos.forEach(video => {
videoObserver.observe(video);
});
debugLog(`已监控${videos.length}个回收的视频`);
};
// 关键视频保护
const protectKeyVideos = () => {
const players = document.querySelectorAll('.video-player, .player-container');
let protectedCount = 0;
players.forEach(container => {
const video = container.querySelector('video');
if (video) {
video.dataset.protected = 'true';
protectedCount++;
}
});
document.addEventListener('play', (e) => {
if (e.target.tagName === 'VIDEO') {
e.target.dataset.userActivated = 'true';
debugLog(`视频用户激活: ${e.target.id || e.target.src || '匿名视频'}`);
}
}, true);
debugLog(`已保护${protectedCount}个关键视频播放器`);
};
// 初始化
startMemoryMonitor();
patchLazyLoad();
initVideoRestoration();
protectKeyVideos();
// 清理钩子
window.addEventListener('beforeunload', () => {
if (memoryMonitor) clearInterval(memoryMonitor);
debugLog('资源回收系统已清理');
});
};
// ========================
// 网络感知配置应用
// ========================
const applyNetworkAwareConfig = () => {
if (!config.networkAware.enabled) {
debugLog('网络感知配置已禁用');
return;
}
if (!navigator.connection) {
debugWarn('浏览器不支持网络连接API');
return;
}
debugLog('应用网络感知配置');
const connection = navigator.connection;
const effectiveType = connection.effectiveType;
const connectionConfig = config.networkAware.connectionTypes[effectiveType];
if (connectionConfig) {
if (connectionConfig.preload !== undefined) {
const original = config.features.preload.enabled;
config.features.preload.enabled = connectionConfig.preload;
debugLog(`网络类型 ${effectiveType}: 预加载 ${original} -> ${connectionConfig.preload}`);
}
if (connectionConfig.lazyMargin) {
const original = config.features.lazyLoad.rootMargin;
config.features.lazyLoad.rootMargin = connectionConfig.lazyMargin;
debugLog(`网络类型 ${effectiveType}: 懒加载边距 ${original} -> ${connectionConfig.lazyMargin}`);
}
if (connectionConfig.maxPreloads) {
const original = config.features.preload.maxPreloads;
config.features.preload.maxPreloads = connectionConfig.maxPreloads;
debugLog(`网络类型 ${effectiveType}: 最大预加载数 ${original} -> ${connectionConfig.maxPreloads}`);
}
}
// 节省数据模式
if (connection.saveData) {
const preloadOriginal = config.features.preload.enabled;
const preconnectOriginal = config.features.preconnect.enabled;
config.features.preload.enabled = false;
config.features.preconnect.enabled = false;
debugLog(`节省数据模式激活: 预加载 ${preloadOriginal} -> false, 预连接 ${preconnectOriginal} -> false`);
}
};
// ========================
// 错误处理
// ========================
const initErrorHandling = () => {
debugLog('初始化错误处理系统');
// 全局错误捕获
window.addEventListener('error', (event) => {
if (event.message && event.message.includes('cross-origin')) {
debugWarn(`跨域资源加载错误: ${event.message}`, event.filename);
// 尝试修复常见CORS问题
if (event.target && event.target.tagName === 'IMG') {
event.target.crossOrigin = 'anonymous';
event.target.src = event.target.src + '?retry=' + Date.now();
debugLog(`尝试修复CORS问题: ${event.target.src}`);
}
}
}, true);
// 脚本执行错误
window.addEventListener('error', (event) => {
debugError(`脚本执行错误: ${event.message}`, event.filename, event.lineno);
});
// Promise未捕获错误
window.addEventListener('unhandledrejection', (event) => {
debugError(`未处理的Promise拒绝: ${event.reason}`);
});
};
// ========================
// CSP兼容性检测
// ========================
const checkCSPCompatibility = () => {
debugLog('检测CSP兼容性');
try {
const testScript = document.createElement('script');
testScript.textContent = 'window._cspTest = true;';
document.head.appendChild(testScript);
const isRestricted = !window._cspTest;
delete window._cspTest;
if (isRestricted) {
debugWarn('页面有严格的CSP策略,禁用部分优化');
}
return isRestricted;
} catch (e) {
debugWarn('CSP检测失败', e);
return true;
}
};
// ========================
// 中国平台后处理
// ========================
const applyChinaPlatformPostProcessing = () => {
const platform = isChinaPlatform();
if (!platform) return;
debugLog(`执行中国平台后处理: ${platform}`);
// 平台特定后处理
switch(platform) {
case 'taobao':
// 轮播图优化
const gallery = document.querySelector('.J_TModule');
if (gallery) {
gallery.dataset.optimizeLayout = 'true';
debugLog('淘宝轮播图优化已应用');
}
break;
case 'jd':
// 预加载核心资源
const jdLogo = '//img11.360buyimg.com/jdphoto/jfs/t1/123246/36/2096/17041/5ec2a9c6E0d7a4ff0/6d1e8d1e3e5b3b7f.png';
if (!document.querySelector(`link[href="${jdLogo}"]`)) {
const link = document.createElement('link');
link.rel = 'preload';
link.href = jdLogo;
link.as = 'image';
document.head.appendChild(link);
debugLog('京东Logo已预加载');
}
break;
case 'douyin':
// 短视频列表优化
const videoList = document.querySelector('.video-list');
if (videoList) {
videoList.dataset.optimizeLayout = 'true';
debugLog('抖音视频列表优化已应用');
}
break;
case 'bilibili':
// 弹幕优化
const danmu = document.querySelector('.bpx-player-dm-wrap');
if (danmu) {
danmu.dataset.optimizeLayout = 'true';
debugLog('哔哩哔哩弹幕优化已应用');
}
break;
case 'kuaishou':
// 直播流优化
const liveStream = document.querySelector('.live-player');
if (liveStream) {
liveStream.dataset.optimizeLayout = 'true';
debugLog('快手直播流优化已应用');
}
break;
case 'tencent':
// 腾讯视频广告优化
const adContainer = document.querySelector('.txp_ad');
if (adContainer) {
adContainer.dataset.optimizeLayout = 'true';
debugLog('腾讯视频广告优化已应用');
}
break;
}
};
// ========================
// 初始化系统
// ========================
document.addEventListener('DOMContentLoaded', () => {
// 调试日志初始化
if (config.debug) {
console.log('[Optimizer] 脚本初始化开始');
}
debugLog('DOMContentLoaded - 开始初始化');
// 1. 错误处理
initErrorHandling();
// 2. 中国平台优化(最先执行)
if (config.chinaPlatforms.enabled) {
applyChinaPlatformOptimizations();
}
// 3. 网络感知配置
applyNetworkAwareConfig();
// 4. CSP检测
const isStrictCSP = checkCSPCompatibility();
// 5. 验证码保护
initCaptchaProtection();
// 6. 主优化模块
if (!isStrictCSP) {
initSmartPreconnect();
initResourcePreload();
}
// 7. 其他优化
initLazyLoad();
initLayoutStabilization();
// 8. 资源回收系统
if (config.features.resourceRecycling.enabled) {
initResourceRecycling();
}
// 9. 中国平台后处理
if (config.chinaPlatforms.enabled && isChinaPlatform()) {
setTimeout(applyChinaPlatformPostProcessing, 2000);
}
// 10. 添加控制台调试命令
if (config.debug) {
console.log('[Optimizer] 脚本初始化完成');
console.log('控制台命令: optimizerStatus(), checkChinaPlatform(), disableOptimizer(), forceRecycle()');
} });
// ========================
// 控制台调试命令
// ========================
const addConsoleCommands = () => {
debugLog('添加控制台调试命令');
// 优化状态查看
window.optimizerStatus = () => {
const status = {
lazyLoad: {
enabled: config.features.lazyLoad.enabled,
images: document.querySelectorAll('img[data-src]').length
},
preconnect: {
enabled: config.features.preconnect.enabled,
connections: document.querySelectorAll('link[rel="preconnect"]').length
},
preload: {
enabled: config.features.preload.enabled,
resources: document.querySelectorAll('link[rel="preload"]').length
},
resourceRecycling: {
enabled: config.features.resourceRecycling.enabled,
recycled: document.querySelectorAll('img[data-src]:not([src]), video[data-recycled-state]').length
},
chinaPlatform: isChinaPlatform() || '未检测到'
};
console.groupCollapsed('[Optimizer] 当前状态');
console.table(status);
console.groupEnd();
return status;
};
// 中国平台检测
window.checkChinaPlatform = () => {
const platform = isChinaPlatform();
if (platform) {
console.log(`检测到中国平台: ${platform}`);
} else {
console.log('未检测到支持的中国平台');
}
return platform;
};
// 临时禁用优化器
window.disableOptimizer = () => {
Object.keys(config.features).forEach(key => {
config.features[key].enabled = false;
});
console.warn('优化器已临时禁用,刷新页面后恢复');
};
// 强制资源回收
window.forceRecycle = () => {
if (config.features.resourceRecycling.enabled) {
triggerRecycling();
} else {
console.warn('资源回收功能未启用');
}
};
console.log('可用命令: optimizerStatus(), checkChinaPlatform(), disableOptimizer(), forceRecycle()');
};
// 添加调试错误函数
const debugError = (...args) => {
if (config.debug) {
console.error('[Optimizer]', ...args);
}
};
})();