Greasy Fork

Webp加载优化(解决图片加载的所有痛点)

Optimize resource loading by adding lazy loading, WebP support, and concurrent requests for images and scripts.

// ==UserScript==
// @name         Webp加载优化(解决图片加载的所有痛点)
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Optimize resource loading by adding lazy loading, WebP support, and concurrent requests for images and scripts.
// @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,UklGRi4AAABXRUJQVlA4TCEAAAAvAUAAEB8wAiMw' +
            'AgSSNtse/cXjxyCCmrYNWPwmHRH9jwMA';
        webP.onload = webP.onerror = () => callback(webP.height === 2);
    }

    // 替换图片元素的src属性为对应的WebP版本
    function replaceWithWebP(imageElement, src) {
        supportsWebP((supports) => {
            if (supports) {
                const webpSrc = src.replace(/\.(jpg|jpeg|png)$/, '.webp');
                fetch(webpSrc)
                    .then(response => {
                        if (response.ok) {
                            imageElement.src = webpSrc;
                        } else {
                            imageElement.src = src;
                        }
                    })
                    .catch(() => {
                        imageElement.src = src;
                    });
            } else {
                imageElement.src = src;
            }
        });
    }

    // 加载图片
    function fetchImage(url) {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.src = url;
            img.onload = () => resolve(img);
            img.onerror = () => reject(new Error(`Failed to load image: ${url}`));
        });
    }

    // 加载脚本
    function loadScript(url) {
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = url;
            script.onload = () => resolve(script);
            script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
            document.head.appendChild(script);
        });
    }

    // 并发加载一组资源
    async function loadResources(resources) {
        const promises = resources.map(resource => {
            if (resource.type === 'image') {
                return fetchImage(resource.url);
            } else if (resource.type === 'script') {
                return loadScript(resource.url);
            }
        });

        const results = await Promise.allSettled(promises);

        results.forEach(result => {
            if (result.status === 'fulfilled') {
                console.log('Resource loaded successfully:', result.value);
            } else {
                console.error('Failed to load resource:', result.reason);
            }
        });
    }

    // 设置动态加载机制
    function setupDynamicLoading(resources) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const resource = entry.target;
                    observer.unobserve(resource);

                    if (resource.dataset.type === 'image') {
                        replaceWithWebP(resource, resource.dataset.src);
                    } else if (resource.dataset.type === 'script') {
                        loadScript(resource.dataset.src);
                    }
                }
            });
        }, { threshold: 0.1 });

        resources.forEach(resource => observer.observe(resource));
    }

    // 预加载首屏可见区域内的资源
    function preloadFirstScreenResources(resources) {
        const visibleResources = Array.from(resources).filter(resource => {
            const rect = resource.getBoundingClientRect();
            return rect.top >= 0 && rect.bottom <= window.innerHeight;
        });

        visibleResources.forEach(resource => {
            if (resource.dataset.type === 'image') {
                replaceWithWebP(resource, resource.dataset.src);
            } else if (resource.dataset.type === 'script') {
                loadScript(resource.dataset.src);
            }
        });

        setupDynamicLoading(resources);
    }

    // 监听DOMContentLoaded事件确保DOM完全构建后再执行
    document.addEventListener('DOMContentLoaded', () => {
        const resources = document.querySelectorAll('[data-src]');
        if (resources.length > 0) {
            preloadFirstScreenResources(resources);
        }
    });
})();