Skripte verzögern, bis sie benötigt werden

Laden Sie JavaScript bei Bedarf mithilfe von IntersectionObserver und Benutzerinteraktions-Triggern

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-05

Skripte verzögern, bis sie benötigt werden

Laut dem [url=https:\/\/almanac.httparchive.org\/en\/2025\/page-weight]2025 Web Almanac[\/url] liefert die durchschnittliche mobile Seite 251 KB an ungenutztem JavaScript aus. Das ist JavaScript, das der Browser herunterlädt, analysiert und kompiliert, bevor ein Besucher es überhaupt benötigt. Formulare, auf die niemand geklickt hat. Chat-Widgets, die niemand geöffnet hat. Kartenintegrationen, die sich unter dem Falz (below the fold) befinden. All dies konkurriert während der kritischsten Phase des Seitenladens um Bandbreite und CPU-Zeit.

Der effektivste Weg, damit umzugehen, besteht darin, Skripte erst dann zu laden, wenn sie tatsächlich benötigt werden. Dies unterscheidet sich von der Verwendung des [url=\/pagespeed\/async-vs-defer-javascript-and-core-web-vitals]async- oder defer-Attributs[\/url] in einem Skript-Tag. Diese Attribute laden das Skript immer noch während des Seitenladens herunter; sie ändern lediglich den Zeitpunkt der Ausführung. Das Laden bei Bedarf (On-demand loading) lädt das Skript überhaupt nicht herunter, bis ein Trigger ausgelöst wird.

Zuletzt überprüft von [url=https:\/\/www.linkedin.com\/in\/arjenkarel\/]Arjen Karel[\/url] im März 2026

[include]toc.html[\/include]

Bei Bildern machen wir das schon lange. Es nennt sich Lazy Loading. Beim Lazy Loading wird ein Bild unter dem Falz erst kurz vor dem Hineinscrollen in den Sichtbereich geladen. Der Browser kann seine Ressourcen für das Herunterladen, Analysieren und Zeichnen von Dingen aufwenden, die tatsächlich benötigt werden. Das gleiche Prinzip gilt für JavaScript. Es behebt die [url=\/pagespeed\/reduce-unused-javascript-lighthouse]Lighthouse-Warnung "Ungenutztes JavaScript reduzieren"[\/url] und verbessert Reaktionsmetriken wie [url=\/core-web-vitals\/interaction-to-next-paint]Interaction to Next Paint (INP)[\/url].

Leider ist es nicht so einfach wie das Hinzufügen von loading="lazy" zu einem Bild, aber mit einer kleinen Hilfsfunktion und einem Trigger können wir es umsetzen.

Der Hilfsskript zur Skript-Injektion

Um Skripte nach dem Seitenladen zur Seite hinzuzufügen, benötigen wir eine kleine Funktion, die ein Skript-Element erstellt und es an den Dokumentenkopf anhängt.

function injectScript(scriptUrl, callback) {
    const script = document.createElement('script');
    script.src = scriptUrl;
    if (typeof callback === 'function') {
        script.onload = callback;
    }
    document.head.appendChild(script);
}

Der Parameter scriptUrl ist die URL des zu ladenden Skripts. Die optionale callback-Funktion wird ausgeführt, nachdem das Skript geladen wurde. Dies ist wichtig für Skripte, die eine Initialisierung benötigen, wie z. B. das Aufrufen von initMap() nach dem Laden der Google Maps API.

Das Laden bei Bedarf auslösen

Nachdem die Hilfsfunktion zur Injektion bereitsteht, benötigen wir einen Trigger. Es gibt zwei zuverlässige Methoden: das Laden, wenn ein Element in den Sichtbereich scrollt, und das Laden, wenn der Benutzer mit einem Element interagiert.

IntersectionObserver: laden, wenn sichtbar

Der IntersectionObserver wird ausgelöst, wenn ein Element in den Viewport eintritt. Dies ist der richtige Trigger für Skripte, die an einen bestimmten Abschnitt der Seite gebunden sind: einen Karten-Container, einen Kommentarbereich oder ein eingebettetes Widget unter dem Falz.

function injectScriptOnIntersection(scriptUrl, elementSelector, callback) {
    const element = document.querySelector(elementSelector);
    const observer = new IntersectionObserver((entries, obs) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                injectScript(scriptUrl, callback);
                obs.unobserve(entry.target);
            }
        });
    });
    observer.observe(element);
}

Die Funktion erwartet die Skript-URL, einen CSS-Selektor für das Element, das das Laden auslösen soll, und einen optionalen Callback zur Initialisierung. Wenn das Element in den Sichtbereich scrollt, wird das Skript injiziert und der Observer trennt die Verbindung.

\/\/ Laden der Google Maps API, wenn der Karten-Container in den Sichtbereich scrollt
injectScriptOnIntersection(
    'https:\/\/maps.googleapis.com\/maps\/api\/js?key=YOUR_KEY',
    '#map-container',
    () => initMap()
);

IntersectionObserver wird in allen modernen Browsern unterstützt (95,76 % globale Abdeckung laut [url=https:\/\/caniuse.com\/intersectionobserver]Can I Use[\/url]). Ein Polyfill ist nicht erforderlich.

Bei Interaktion: laden, wenn der Benutzer interagiert

Die effektivste Methode besteht darin, ein Skript erst dann zu laden, wenn der Besucher tatsächlich mit dem Element interagiert, das es benötigt. Ein [url=\/pagespeed\/chat-widget-perfect-core-web-vitals]Chat-Widget[\/url] muss erst geladen werden, wenn jemand auf die Chat-Schaltfläche klickt. Eine Formularvalidierungs-Bibliothek muss erst geladen werden, wenn der Benutzer ein Formularfeld fokussiert.

function injectScriptOnInteraction(scriptUrl, elementSelector, eventTypes, callback) {
    const element = document.querySelector(elementSelector);
    const handler = () => {
        eventTypes.forEach(type => element.removeEventListener(type, handler));
        injectScript(scriptUrl, callback);
    };
    eventTypes.forEach(type => {
        element.addEventListener(type, handler);
    });
}

Diese Funktion hört auf die angegebenen Ereignisse am Ziel-Element. Beim ersten Ereignis entfernt sie alle Listener und injiziert das Skript. Der Vorteil: Wenn der Besucher nie mit dem Element interagiert, wird das Skript überhaupt nicht geladen.

\/\/ Chat-Widget-Skript laden, wenn die Chat-Schaltfläche angeklickt oder mit der Maus berührt wird
injectScriptOnInteraction(
    'chat-widget.js',
    '#chat-button',
    ['click', 'mouseover', 'touchstart'],
    () => initChat()
);

Auswirkungen in der Praxis

Dieses Muster funktioniert für jedes Skript, das während des ersten Seitenladens nicht benötigt wird. Einige häufige Anwendungsfälle:

  • Chat-Widgets: Ein typisches Chat-Widget lädt 200 bis 400 KB an JavaScript. Als Postmark [url=https:\/\/www.patterns.dev\/vanilla\/import-on-interaction]ihr Intercom-Widget verzögert hat[\/url], um es bei Klick anstatt sofort zu laden, sank ihre Time to Interactive von 7,7 Sekunden auf 3,7 Sekunden.
  • Video-Einbettungen: Eine [url=\/pagespeed\/perfect-youtube-core-web-vitals]YouTube-Einbettung[\/url] lädt über 1 MB an Daten. Zeigen Sie ein Vorschaubild mit einer Play-Taste an und laden Sie die Einbettung erst bei Klick.
  • Kartenintegrationen: [url=\/pagespeed\/google-maps-100-percent-pagespeed]Google Maps[\/url] lädt hunderte Kilobyte an JavaScript. Verwenden Sie den IntersectionObserver, um es zu laden, wenn der Karten-Container in den Sichtbereich scrollt.
  • Analytics und Tracking: [url=\/pagespeed\/the-case-for-limiting-analytics-and-tracking-scripts]Analytics-Skripte[\/url] können bis nach der ersten Benutzerinteraktion warten. Niemand war jemals enttäuscht, dass sein Heatmap-Tool erst 3 Sekunden nach dem Seitenladen mit der Aufzeichnung begann.
  • Formular-Bibliotheken: Validierungs-Bibliotheken, Datumsauswähler und Rich-Text-Editoren können geladen werden, wenn der Benutzer das Formular fokussiert.

    Wann man nicht verzögern sollte

    Nicht jedes Skript sollte verzögert werden. Wenn ein Skript für das Rendern von Inhalten oberhalb des Falzes verantwortlich ist, wird das Verzögern Ihr [url=\/core-web-vitals\/largest-contentful-paint]Largest Contentful Paint (LCP)[\/url] verschlechtern, nicht verbessern. Skripte, die Ihre Header-Navigation initialisieren, Ihren Hero-Bereich rendern oder kritische A\/B-Testvarianten einrichten, müssen frühzeitig ausgeführt werden.

    Die Regel ist einfach: Wenn der Besucher das, was das Skript erzeugt, innerhalb des ersten Viewports sieht oder damit interagiert, laden Sie es normal. Wenn das Skript etwas unterhalb des Falzes oder hinter einer Benutzeraktion steuert, verzögern Sie es mit einem der oben genannten Muster.

    Tipp: Eine vollständige Übersicht über alle JavaScript-Ladestrategien finden Sie unter [url=\/pagespeed\/14-methods-to-defer-javascript]16 Methoden zum Verzögern oder Planen von JavaScript[\/url].

    Die Verbesserung messen

    Der [url=https:\/\/almanac.httparchive.org\/en\/2025\/performance]2025 Web Almanac[\/url] berichtet von einer medianen mobilen Total Blocking Time von 1.916 ms, was einem Anstieg von 58 % gegenüber 2024 entspricht. Ein Großteil dieser Blockierung stammt von JavaScript, das während des Seitenladens nicht ausgeführt werden musste. Indem Sie nicht-kritische Skripte verzögern, entfernen Sie diese vollständig aus dem kritischen Pfad.

    Überprüfen Sie nach der Implementierung des Ladens bei Bedarf die Verbesserung mit [url=https:\/\/coredash.app]Real User Monitoring[\/url]. Überprüfen Sie Ihre INP-Werte und die Total Blocking Time in den Felddaten, nicht nur in Lighthouse. Lab-Tests laufen auf schnellen Maschinen mit leeren Caches. Ihre Besucher nutzen mobile Netzwerke mit 15 geöffneten Browser-Tabs. Dort zeigt sich der Unterschied. [include]cwv\/authorbio.html[\/include]

    [include]sidebar.html[\/include] [include]blogfooter.html[\/include]
    Skripte verzögern, bis sie benötigt werdenCore Web Vitals Skripte verzögern, bis sie benötigt werden