Lazy Load Image

Apply lazy loading to all images.

  1. // ==UserScript==
  2. // @name Lazy Load Image
  3. // @namespace lazy-load-image
  4. // @version 2025-01-06
  5. // @description Apply lazy loading to all images.
  6. // @author Ace
  7. // @run-at document-end
  8. // @match *://*/*
  9. // @icon https://cdn-icons-png.flaticon.com/512/13159/13159509.png
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Debug mode: Set to true to enable logs
  18. const DEBUG = false;
  19.  
  20. // Debug logging function
  21. const log = (...args) => {
  22. if (DEBUG) {
  23. console.log('[LazyLoadImage]', ...args);
  24. }
  25. };
  26.  
  27. log('Script started');
  28.  
  29. // Process existing images
  30. document.querySelectorAll('img').forEach(img => {
  31. if (!img.loading || img.loading !== 'lazy') {
  32. img.loading = 'lazy';
  33. log('Processed existing img:', img.src);
  34. }
  35. });
  36.  
  37. // Debouncing logic with requestAnimationFrame
  38. let imgQueue = [];
  39. let isScheduled = false;
  40.  
  41. const processQueue = () => {
  42. log('Processing queued images:', imgQueue.length);
  43. imgQueue.forEach(img => {
  44. if (!img.loading || img.loading !== 'lazy') {
  45. img.loading = 'lazy'; // Apply lazy loading
  46. log('Applied lazy loading to new img:', img.src);
  47. }
  48. });
  49. imgQueue = []; // Clear the queue
  50. isScheduled = false; // Allow new frame scheduling
  51. };
  52.  
  53. // Observe dynamically added images
  54. const observer = new MutationObserver(mutations => {
  55. mutations.forEach(mutation => {
  56. mutation.addedNodes.forEach(node => {
  57. if (node.nodeType === 1 && node.tagName === 'IMG') {
  58. imgQueue.push(node); // Add image to the queue
  59. log('New img detected:', node.src || 'No src');
  60. }
  61. });
  62. });
  63.  
  64. // Schedule processing for the next frame if not already scheduled
  65. if (!isScheduled && imgQueue.length > 0) {
  66. isScheduled = true;
  67. requestAnimationFrame(processQueue);
  68. log('Scheduled processing for next frame');
  69. }
  70. });
  71.  
  72. // Start observing the DOM
  73. observer.observe(document.body, { childList: true, subtree: true });
  74. log('MutationObserver started');
  75.  
  76. })();