Das KOSTENLOSE Skript zur Ladezeit-Optimierung als letzter Ausweg
Beschleunige deine unreparierbare Seite. Diese Methode ist dein letzter Ausweg, um selbst die langsamsten Seiten zu verbessern.
Das KOSTENLOSE Skript zur Optimierung der Seitengeschwindigkeit als letzter Ausweg
Manchmal treffe ich als Berater für Core Web Vitals auf eine unreparierbare Seite. Sie ist nicht unreparierbar, weil ich nicht weiß, wie man sie repariert! Nein, sie ist unreparierbar, weil die Reparatur große Teile einer Website umschreiben würde, die ohnehin bald ersetzt wird. Oder weil es einfach nicht genug Zugriff und Kontrolle gibt, um den Code der Website zu verbessern. Das passiert bei geschlossenen CMS-Systemen wie WIX, HubSpot, WebFlow usw. Oder, zu guter Letzt, wenn einfach das Budget fehlt. Das passiert nicht oft. Aber manchmal können Kunden den nötigen Arbeitsaufwand nicht genau vorhersagen und bezahlen.
Zuletzt überprüft von Arjen Karel im März 2026
Hier ist das „Skript zur Optimierung der Seitengeschwindigkeit als letzter Ausweg“
Wenn du in dieser Zwickmühle steckst, ist dieses Skript dein verzweifelter letzter Versuch. Es verbessert die Seitengeschwindigkeit zumindest ein wenig, bis du etwas Besseres bauen kannst. Es nutzt clever den Mutation Observer. Das Skript beobachtet, wie der Browser das Document Object Model deiner Website erstellt. Es fängt langsamen Code sofort ab und ersetzt ihn durch schnelleren Code.
Was es tut:
- Alle render blocking Skripte abfangen und verzögern, indem der Typ des Skripts in type="module" geändert wird. Dieser Trick nutzt die Tatsache, dass alle modularen Skripte standardmäßig verzögert werden. Selbst Inline-Skripte. Das macht dies zur sichersten Methode, alle Seitenskripte zu verzögern.
- Lazy loading für Bilder: loading="lazy" und decoding="async" wird allen Bildern hinzugefügt. Das wird das Laden dieser Bilder verzögern, bis sie fast im sichtbaren viewport sind. Gleichzeitig erfolgt die asynchrone Aktualisierung des Bild-Layouts. Vorsicht: Du willst dein LCP-Bild nicht per lazy loading laden. Nutze die prioImgs-Konfiguration, um es auszuschließen. Siehe, warum lazy loading des LCP-Bildes der Performance schadet.
- Lazy loading für iframes. Genau wie bei Bildern kann lazy loading von iframes deine eigenen, wichtigeren Inhalte priorisieren!
Konfiguration
Das Skript erwartet ein einziges „Config-Objekt“. Es nutzt diese Konfiguration, um das Verzögern oder lazy loading wichtiger Bilder und Skripte zu überspringen. Bei iframes funktioniert es umgekehrt. Es wendet lazy loading nur auf iframes an, die deiner Konfiguration entsprechen. Alle Konfigurationen sind reguläre Ausdrücke. Das mag beängstigend klingen, ist in der Praxis aber sehr einfach.
- prioScripts: Überspringt das Verzögern von Skripten, bei denen die src mit der Konfiguration übereinstimmt.
Beispiel: „jquery|menu“ trifft auf dein jquery- und dein menu-Skript zu. - prioImgs: Überspringt lazy loading für alle Bilder, bei denen Bildname, Bildklasse oder Bild-ID übereinstimmen.
Beispiel: „hero“ trifft auf <img id="hero" ..> und <img src="hero.jpg"> zu. - lazyFrames: Wendet lazy loading nur auf iframes an, deren iframe src der Konfiguration entspricht.
Beispiel: „youtube|maps“ wendet lazy loading auf alle YouTube- und Google Maps-iframes an.
Verwendung
Einschränkungen
Wie bereits erwähnt, solltest du dieses Skript nicht als Hauptlösung nutzen, um deine Seitengeschwindigkeit zu reparieren. Nur wenn alles andere fehlschlägt, während du aktiv an einer neuen Website arbeitest, ist so eine Lösung akzeptabel!
Technisch gesehen liefert sich dieses Skript ein Rennen mit dem Browser (und dem Preload-Scanner). Man kann also nicht sagen, welche langsamen Elemente bereits zum Download ausgelöst wurden, bevor das Skript aktiv wird.
Das Skript zur Optimierung der Seitengeschwindigkeit als letzter Ausweg
Hier ist eine minifizierte Version, die in der Produktion verwendet werden sollte
!function(t){['prioScripts', 'prioImgs', 'lazyFrames'].forEach(e=>{t[e]=t[e]?RegExp(t[e],"i"):null});let e=new MutationObserver(e=>{e.forEach(({addedNodes:e})=>{e.forEach(e=>{if(1===e.nodeType)switch(e.tagName){case"SCRIPT":if(!t.prioScripts||!t.prioScripts.test(e.src)){let t=e.getAttribute("type");t&&"text/javascript"!==t||e.setAttribute("type","module")}break;case"IMG":console.log(e.outerHTML),t.prioImgs&&(t.prioImgs.test(e.outerHTML)||e.getAttribute("loading"))||(e.setAttribute("loading","lazy"),e.setAttribute("decoding","async"));break;case"IFRAME":t.lazyFrames.test(e.src)&&e.setAttribute("loading","lazy")}})})});/MSIE|Trident/.test(navigator.userAgent)||(e.observe(document.documentElement,{childList:!0,subtree:!0}),document.addEventListener("DOMContentLoaded",()=>{e.disconnect()}))}({prioScripts:"jquery",prioImgs:"hero",lazyFrames:"youtube|maps"});
Hier ist eine besser lesbare Version des Skripts. Nutze diese nicht in der Produktion! Nutze die minifizierte Version!
!function (cfg) {\r\n\r\n // Regexify config or nullify\r\n ['prioScripts', 'prioImgs', 'lazyFrames'].forEach((e) => {\r\n cfg[e] = cfg[e] ? new RegExp(cfg[e], "i") : null;\r\n });\r\n\r\n t0 = performance.now();\r\n\r\n /* Watch mutated nodes */\r\n const mutator = new MutationObserver((e) => {\r\n e.forEach(({ addedNodes: e }) => {\r\n e.forEach((e) => {\r\n switch (e.nodeType) {\r\n case 1:\r\n switch (e.tagName) {\r\n // defer scripts by adding type="module", excusive test on src\r\n case "SCRIPT":\r\n if (!cfg.prioScripts || !cfg.prioScripts.test(e.src)) {\r\n let type = e.getAttribute("type");\r\n if (!type || type === "text/javascript") {\r\n e.setAttribute("type", "module");\r\n }\r\n }\r\n break;\r\n\r\n // lazy load images, excusive test on outerHTML for classname, id etc etc\r\n case "IMG":\r\n console.log(e.outerHTML);\r\n if (!cfg.prioImgs || (!cfg.prioImgs.test(e.outerHTML) && !e.getAttribute("loading"))) {\r\n e.setAttribute("loading", "lazy");\r\n e.setAttribute("decoding", "async");\r\n }\r\n break;\r\n\r\n // lazy load iframes, inclusive test on src\r\n case "IFRAME":\r\n if (cfg.lazyFrames.test(e.src)) {\r\n e.setAttribute("loading", "lazy");\r\n }\r\n break;\r\n }\r\n break;\r\n }\r\n });\r\n });\r\n });\r\n\r\n\r\n // Check for IE\r\n if (!/MSIE|Trident/.test(navigator.userAgent)) {\r\n mutator.observe(document.documentElement, { childList: true, subtree: true });\r\n document.addEventListener("DOMContentLoaded", () => {\r\n mutator.disconnect();\r\n console.log("I quit after watching for " + (performance.now() - t0) + " ms");\r\n });\r\n }\r\n}({\r\n prioScripts: 'jquery',\r\n prioImgs: 'hero',\r\n lazyFrames: 'youtube|maps',\r\n});\r\n\r\n\r\n
Dein Lighthouse-Score zeigt nicht das ganze Bild.
Deine Besucher sitzen auf Android-Geräten im 4G-Netz. Ich analysiere, was die tatsächlich sehen.
RUM-Daten auswerten