Web Comprehensive Optimization Script(web综合优化脚本)

Optimize non-first screen CSS and image lazy loading, hardware acceleration, and more.

目前為 2025-03-13 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Web Comprehensive Optimization Script(web综合优化脚本)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.4
  5. // @description Optimize non-first screen CSS and image lazy loading, hardware acceleration, and more.
  6. // @author KiwiFruit
  7. // @match *://*/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. document.addEventListener("DOMContentLoaded", function() {
  13. 'use strict';
  14.  
  15. // Function to dynamically load a script
  16. function loadScript(url) {
  17. return new Promise((resolve, reject) => {
  18. const script = document.createElement('script');
  19. script.src = url;
  20. script.onload = resolve;
  21. script.onerror = reject;
  22. document.head.appendChild(script);
  23. });
  24. }
  25.  
  26. // Function to dynamically load a stylesheet
  27. function loadStylesheet(href) {
  28. return new Promise((resolve, reject) => {
  29. const link = document.createElement('link');
  30. link.rel = 'stylesheet';
  31. link.href = href;
  32. link.onload = resolve;
  33. link.onerror = reject;
  34. document.head.appendChild(link);
  35. });
  36. }
  37.  
  38. // Define hardware acceleration-related CSS class
  39. const hardwareAccelerationClassName = 'enable-hardware-acceleration';
  40. const styleSheet = `
  41. .${hardwareAccelerationClassName} {
  42. transform: translateZ(0);
  43. will-change: transform;
  44. }
  45. `;
  46. const styleElement = document.createElement('style');
  47. styleElement.type = 'text/css';
  48. styleElement.appendChild(document.createTextNode(styleSheet));
  49. document.head.appendChild(styleElement);
  50.  
  51. // IntersectionObserver to handle hardware acceleration for visible elements
  52. const hardwareAccelerationObserver = new IntersectionObserver((entries, observer) => {
  53. entries.forEach(entry => {
  54. if (entry.isIntersecting) {
  55. entry.target.classList.add(hardwareAccelerationClassName);
  56. } else {
  57. entry.target.classList.remove(hardwareAccelerationClassName);
  58. }
  59. });
  60. }, {
  61. rootMargin: '0px 0px ${rootMarginBottom} 0px',
  62. threshold: 0
  63. });
  64.  
  65. // Initialize lozad.js image lazy loading
  66. loadScript('https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.15.0/lozad.min.js').then(() => {
  67. const observer = lozad(); // lazy loads elements with default selector as '.lozad'
  68. observer.observe();
  69. });
  70.  
  71. // Initialize non-first screen CSS lazy loading
  72. const lazyCssElements = document.querySelectorAll('.lazy-css');
  73. lazyCssElements.forEach(element => {
  74. const cssHref = element.getAttribute('data-lazy-css');
  75. if (cssHref) {
  76. loadStylesheet(cssHref).then(() => {
  77. element.parentElement.removeChild(element); // Remove placeholder element
  78. });
  79. }
  80. });
  81.  
  82. // Listen to click events using requestAnimationFrame
  83. document.addEventListener('click', () => {
  84. requestAnimationFrame(enableHardwareAccelerationForVisibleElements);
  85. });
  86.  
  87. // Listen to media play events using IntersectionObserver
  88. const mediaElements = document.querySelectorAll('audio, video');
  89. mediaElements.forEach(element => {
  90. const mediaObserver = new IntersectionObserver((entries, observer) => {
  91. entries.forEach(entry => {
  92. if (entry.isIntersecting) {
  93. element.play();
  94. } else {
  95. element.pause();
  96. }
  97. });
  98. }, {
  99. rootMargin: '0px',
  100. threshold: 0
  101. });
  102. mediaObserver.observe(element);
  103. });
  104.  
  105. // Listen to image load events using IntersectionObserver
  106. const imageElements = document.querySelectorAll('img[data-src]');
  107. imageElements.forEach(element => {
  108. const imageObserver = new IntersectionObserver((entries, observer) => {
  109. entries.forEach(entry => {
  110. if (entry.isIntersecting) {
  111. element.src = element.getAttribute('data-src');
  112. observer.unobserve(element);
  113. }
  114. });
  115. }, {
  116. rootMargin: '0px 0px ${rootMarginBottom} 0px', // Trigger when element is 30% away from the viewport bottom
  117. threshold: 0 // Trigger as soon as any part of the element is visible
  118. });
  119. imageObserver.observe(element);
  120. });
  121.  
  122. // Initialize check for hardware acceleration
  123. enableHardwareAccelerationForVisibleElements();
  124.  
  125. // MutationObserver to listen for DOM changes and ensure new elements trigger lazy loading and hardware acceleration
  126. const mutationObserver = new MutationObserver(mutations => {
  127. mutations.forEach(mutation => {
  128. mutation.addedNodes.forEach(node => {
  129. if (node.nodeType === 1) {
  130. if (node.tagName === 'IMG' && node.hasAttribute('data-src')) {
  131. const imageObserver = new IntersectionObserver((entries, observer) => {
  132. entries.forEach(entry => {
  133. if (entry.isIntersecting) {
  134. node.src = node.getAttribute('data-src');
  135. observer.unobserve(node);
  136. }
  137. });
  138. }, {
  139. rootMargin: '0px 0px ${rootMarginBottom} 0px', // Trigger when element is 30% away from the viewport bottom
  140. threshold: 0 // Trigger as soon as any part of the element is visible
  141. });
  142. imageObserver.observe(node);
  143. } else if (node.classList.contains('lazy-css') && node.hasAttribute('data-lazy-css')) {
  144. const cssHref = node.getAttribute('data-lazy-css');
  145. loadStylesheet(cssHref).then(() => {
  146. node.parentElement.removeChild(node); // Remove placeholder element
  147. });
  148. } else if (node.matches('.target-element')) {
  149. hardwareAccelerationObserver.observe(node);
  150. }
  151. }
  152. });
  153. });
  154. });
  155. mutationObserver.observe(document.body, { childList: true, subtree: true });
  156.  
  157. // ResizeObserver to monitor viewport size changes
  158. const resizeObserver = new ResizeObserver(() => {
  159. requestAnimationFrame(enableHardwareAccelerationForVisibleElements);
  160. });
  161. resizeObserver.observe(document.body);
  162.  
  163. // Optional optimizations
  164. // ... (rest of the optional optimizations code remains the same)
  165. })();