Optimiere den Aufruf deiner Webseite mit Async und Defer

Wenn du deine Webseite schon einmal in Google Pagespeed Insights analysiert hast, wurde dir bestimmt schon folgende Verbesserung von Google vorgeschlagen:

Google Pagespeed - Ressourcen beseitigen die das Rendering blockieren

Ich erkl√§re dir, was der Hinweis "Ressourcen beseitigen, die das Rendering blockieren" bedeutet und wie du das Rendering deiner WordPress-Webseite verbesserst. Wenn du bereits wei√üt, was dieser Hinweis bedeutet, kannst du dir den PHP-Code f√ľr deine Webseite im letzten Teil des Beitrags "Ressourcen beseitigen die das Rendering blockieren in WordPress" kopieren. √úber einen Kommentar w√ľrde ich mich sehr freuen, wenn du zufrieden mit dem Code-Schnipsel bist.

Was geschieht beim Aufruf einer Webseite?

Stelle dir vor, dein Webseiten-Besucher möchte deine Seite aufrufen. Dein Server sendet bei Erhalt der Anfrage die HTML-Datei, nachdem der PHP-Service alles vorbereitet hat. (Ich gehe mal bei dieser Annahme davon aus, dass du keinen Server-Cache installiert hast)

Nun analysiert der Browser die HTML-Datei und sucht alle externen Dateien, wie Bilder, CSS- und JavaScript-Dateien auf dem Server oder auf anderen Quellen heraus. Sofern der Besucher noch nicht auf deiner Seite war, hat er diese auch noch nicht in seinem Browser-Cache und muss diese beim Server einzeln anfragen.

Der Server sendet nun alle Dateien nacheinander an den Besucher. Nachdem die ersten Dateien beim Benutzer aufschlagen, f√§ngt der Browser an das DOM zu vervollst√§ndigen und die Formatierungen auszuf√ľhren. Danach werden noch alle JavaScripte geladen, um auch die Dynamik zur Seite hinzuzuf√ľgen.

(Dieses Beispiel dient nur der Veranschaulichung. Das echte "abholen" von Dateien sieht ein wenig komplexer aus)

Du merkst jetzt wahrscheinlich, dass der Prozess sehr umfangreich ist, bis eine einzelne Seite vollst√§ndig geladen wurde. Gerade bei gekauften Templates auf Themeforest oder Andere, werden h√§ufig sehr viele Stile und Skripte ausgef√ľhrt, die das erstmalige Rendering einer Webseite blockieren. Die Template-Hersteller wollen damit nichts b√∂ses bezwecken, sondern m√∂glichst viele Anpassungsm√∂glichkeiten f√ľr deine Webseite zur Verf√ľgung stellen.

Einf√ľgen von Skripten in WordPress

Wenn du bereits ein wenig mit WordPress programmiert hast, kennst du wahrscheinlich die Funktion, um ein neues Skript in deine Webseite hinzuzuf√ľgen: wp_enqueue_script()

So könnte dein Code aussehen:

<?php
	function set_frontend_scripts() {
		wp_register_script( 'custom-script', get_template_directory_uri().'/js/custom.js', array( 'jquery' ) );
		wp_enqueue_script( 'custom-script' );
	}
	add_action( 'wp_enqueue_scripts', 'set_frontend_scripts' );
?>

Mit dieser Funktionen werden Scripte in den wp_head() Bereich geladen. Es können mehrere Einstellungen und Abhängigkeiten in den Parametern der Funktion hinterlegt werden. Jedoch keinen Parameter, um ein Skript nachzuladen zu lassen.

Skripte in HTML nachladen

Um ein Script in HTML nachzuladen, werden zum <script>-Tag die Attribute async und defer hinzugef√ľgt.

Das Attribut "async" gibt an, dass ein Script "Asynchron" ausgef√ľhrt werden soll. Das bedeutet nicht, dass der Code in der Datei nacheinander ausgef√ľhrt wird, sondern dass der Code simultan mit beim Laden der Seite ausgef√ľhrt wird.

Das Attribut "defer" gibt an, dass der JavaScript-Code erst ausgef√ľhrt wird, wenn die Seite vollst√§ndig geladen wurde.

Sollten beide Attribute fehlen, wird der JavaScript sofort ausgef√ľhrt, wenn er geladen wurde. Der Rest des HTML-Codes wird geparst, sobald das JavaScript beendet wurde. Deshalb wei√üt Google immer darauf hin, dass der Analytics-Code am Ende der Seite vor dem schlie√üenden <body>-Tag eingef√ľgt werden soll.

Zudem solltest du beachten, dass die Attribute async und defer nur bei externen Ressourcen funktionieren. Also bei JavaScript-Dateien und nicht bei Inline-Skripten.

Der HTML-Code um ein Skript hinzuzuf√ľgen, dass nachgeladen werden soll, w√ľrde dann zum Beispiel so aussehen:

<script async="async" defer="defer" src="/js/custom.js"></script>

Ressourcen beseitigen die das Rendering blockieren in WordPress

Wie k√∂nnen wir es also anstellen, dass die Attribute defer und async zum wp_enqueue_script() hinzugef√ľgt werden?

Die kurze Antwort: √úber diese Funktion gar nicht.

Es gibt jedoch in WordPress einen Filter, mit dem Skripte gepr√ľft und bearbeitet werden k√∂nnen, nachdem sie vom Template oder Plugins zur "Pipe" hinzugef√ľgt wurden.

Mit dem script_loader_tag-Filter und einem str_replace() k√∂nnen wir den Output des Skripts nach belieben bearbeiten. Ich habe eine Funktion vorbereitet, die du f√ľr dein Projekt kopieren und anpassen kannst, um bestimmte Skripte mit den wertvollen defer- und async-Attributen zu versehen.

Aber vorsicht: Es kann sein, dass Skripte durch diese Angaben nicht mehr funktionieren. Teste am besten ein Skript nach dem anderen, ob deine JavaScripts die Attribute unterst√ľtzen. Im besten Fall verwendest du ein lokales Test-System, also eine Spiegelung deiner Webseite, auf der du verschiedene Sachen ausprobieren kannst.

Die nachfolgenden Code-Schnipsel kannst du in die functions.php deines Child-Themes hinzuf√ľgen, oder ein eigenes Plugin daf√ľr erstellen.

Das Async-Attribut hinzuf√ľgen

<?php
	add_filter( 'script_loader_tag', 'add_async_attribute', 10, 2 );
	function add_async_attribute( $tag, $handle ) {
		$scripts_to_async = array( 'custom-script', 'another-script' );
		
		foreach( $scripts_to_async as $defer_script )
			if( $defer_script === $handle )
				return str_replace( ' src', ' async="async" src', $tag );
		
		return $tag;
	}
?>

Das Defer-Attribut hinzuf√ľgen

<?php
	add_filter( 'script_loader_tag', 'add_defer_attribute', 10, 2 );
	function add_defer_attribute( $tag, $handle ) {
		$scripts_to_defer = array( 'custom-script', 'another-script' );
		
		foreach( $scripts_to_defer as $defer_script )
			if( $defer_script === $handle )
				return str_replace( ' src', ' defer="defer" src', $tag );
		
		return $tag;
	}
?>

Kompatibilität des Codes

script_loader_tag Ab WordPress 4.1.0
str_replace() Ab PHP 4
async Ab HTML 4
Von allen modernen Browsern unterst√ľtzt:
Async auf CanIUse.com
defer Ab HTML 5
Von allen modernen Browsern unterst√ľtzt:
Defer auf CanIUse.com
 

Bevor du dieses Skript auf deiner Webseite einf√ľgst, kannst du mit meinem Performance-Vergleich eine Analyse deiner Webseite starten. Wenn du das Ergebnis in deinem Browser sicherst, kannst du die Daten (Vorher und Nachher) besser miteinander vergleichen.

Nachdem dann deine Skripte mit Defer oder Async geladen werden, kannst du mit dem Performance-Vergleich einen weiteren Test durchf√ľhren. Du solltest feststellen, dass die Kategorie "Performance" einen besseren Wert als vor der Umsetzung hat.

Ein letzter Hinweis: Ich habe die Erfahrung gemacht, dass es besser ist jQuery nicht als Defer oder Async zu laden. Außerdem gibt es Templates, die keines der beiden Attribute zulassen. Du musst ein wenig testen, um herauszufinden ob die Attribute gesetzt werden können oder nicht.

 

Hast du schon Erfahrungen mit den Defer- und Async-Attributen gesammelt? Teile dein Wissen in den Kommentaren.

 

Codepalm
JavaScript in WordPress nachladen