Greasy Fork is available in English.
Optimize image loading by adding lazy loading, WebP support, and concurrent requests.
当前为
// ==UserScript==
// @name Webp图片加载优化
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Optimize image loading by adding lazy loading, WebP support, and concurrent requests.
// @author KiwiFruit
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 检查浏览器是否支持WebP
function supportsWebP(callback) {
const webP = new Image();
webP.src = 'data:image/webp;base64,UklGRi4AAABXRUJQVlA4TCEAAAAvAUAAEB8wAiMwMAAgH8JeYW5kZXI=';
webP.onload = webP.onerror = function () {
callback(webP.height === 2);
};
}
// 动态替换为WebP图片(如果有)
function replaceWithWebP(imageElement, src) {
const webPSrc = src.replace(/\.(jpg|jpeg|png)$/, '.webp');
const img = new Image();
img.src = webPSrc;
img.onload = function() {
imageElement.src = webPSrc;
};
img.onerror = function() {
imageElement.src = src;
console.log(`WebP version not found for ${src}, using original.`);
};
}
// 并发加载图片
function loadImages(imageUrls) {
return Promise.all(imageUrls.map(url => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = url;
img.onload = resolve;
img.onerror = reject;
});
}));
}
// 使用IntersectionObserver动态加载图片
function setupDynamicLoading(images) {
const viewportHeight = window.innerHeight;
const rootMarginBottom = `${viewportHeight / 2}px`; // 设置rootMargin为视口高度的50%
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute('data-src');
if (src) {
supportsWebP((isSupported) => {
if (isSupported) {
replaceWithWebP(img, src);
} else {
img.src = src;
}
});
observer.unobserve(img); // 停止观察已加载的图片
}
}
});
}, { root: null, rootMargin: `0px 0px ${rootMarginBottom} 0px` }); // 只增加底部的rootMargin
images.forEach(img => {
if (!img.getAttribute('data-src')) {
img.setAttribute('data-src', img.src);
img.src = ''; // 清空src以防止立即加载
}
observer.observe(img);
});
}
// 预加载首屏图片
function preloadFirstScreenImages(images) {
const viewportHeight = window.innerHeight;
const firstScreenImages = Array.from(images).filter(img => {
const rect = img.getBoundingClientRect();
return rect.top <= viewportHeight && rect.bottom >= 0;
}).map(img => img.getAttribute('data-src'));
if (firstScreenImages.length > 0) {
loadImages(firstScreenImages).then(() => {
console.log('首屏图片已预加载');
}).catch(error => {
console.error('首屏图片预加载失败:', error);
});
}
}
// 确保DOM完全加载后再执行动态加载和首屏图片预加载
window.addEventListener('load', () => {
const images = document.querySelectorAll('img');
preloadFirstScreenImages(images); // 首屏图片预加载
setupDynamicLoading(images); // 动态加载所有图片
});
// 监听DOM变化,确保动态加载的内容也能被优化
const mutationObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1) {
const images = node.querySelectorAll('img');
if (images.length > 0) {
preloadFirstScreenImages(images); // 对新添加的图片进行首屏预加载
setupDynamicLoading(images); // 对新添加的图片进行动态加载
}
}
});
});
});
mutationObserver.observe(document.body, { childList: true, subtree: true });
})();