Faster Webpage Loading with Pjax

Preload subsequent pages, lazy load images, and use Pjax for faster webpage loading

// ==UserScript==
// @name         Faster Webpage Loading with Pjax
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  Preload subsequent pages, lazy load images, and use Pjax for faster webpage loading
// @author       Tae
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Lazy load images
    document.addEventListener("DOMContentLoaded", function() {
        let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
        if ("IntersectionObserver" in window) {
            let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        let lazyImage = entry.target;
                        lazyImage.src = lazyImage.dataset.src;
                        lazyImage.classList.remove("lazy");
                        lazyImageObserver.unobserve(lazyImage);
                    }
                });
            });
            lazyImages.forEach(function(lazyImage) {
                lazyImageObserver.observe(lazyImage);
            });
        } else {
            // Fallback for browsers without IntersectionObserver support
            let lazyLoad = function() {
                lazyImages.forEach(function(lazyImage) {
                    if (lazyImage.getBoundingClientRect().top < window.innerHeight && lazyImage.getBoundingClientRect().bottom > 0 && getComputedStyle(lazyImage).display !== "none") {
                        lazyImage.src = lazyImage.dataset.src;
                        lazyImage.classList.remove("lazy");
                    }
                });
                if (lazyImages.length === 0) {
                    document.removeEventListener("scroll", lazyLoad);
                    window.removeEventListener("resize", lazyLoad);
                    window.removeEventListener("orientationchange", lazyLoad);
                }
            };
            document.addEventListener("scroll", lazyLoad);
            window.addEventListener("resize", lazyLoad);
            window.addEventListener("orientationchange", lazyLoad);
        }
    });

    // Preload subsequent pages
    document.addEventListener("mouseover", function(event) {
        if (event.target.tagName === 'A' && event.target.href) {
            let link = event.target.href;
            if (link.includes('relevant-part')) { // Add condition to limit prefetching
                let prefetchLink = document.createElement('link');
                prefetchLink.rel = 'prefetch';
                prefetchLink.href = link;
                document.head.appendChild(prefetchLink);
            }
        }
    });

    // Ensure Pjax script is loaded
    if (typeof Pjax === 'undefined') {
        var script = document.createElement('script');
        script.src = 'https://cdnjs.cloudflare.com/ajax/libs/pjax/0.2.8/pjax.min.js';
        script.onload = initializePjax;
        document.head.appendChild(script);
    } else {
        initializePjax();
    }

    function initializePjax() {
        // Initialize Pjax
        var pjax = new Pjax({
            elements: "a", // Default is "a[href], form[action]"
            selectors: ["title", ".content"], // Elements to update
            cacheBust: false // Disable cache busting
        });

        // Optional: Add event listeners
        document.addEventListener("pjax:send", function() {
            console.log("Pjax request sent");
        });
        document.addEventListener("pjax:complete", function() {
            console.log("Pjax request completed");
        });
        // Prevent Pjax from causing issues like 503 errors or logging users out
        document.addEventListener("pjax:error", function(event) {
            console.error("Pjax error:", event);
            // Fallback to full page reload on error
            window.location.href = event.request.responseURL;
        });
    }
})();