In diesem Codelab erfahren Sie, wie Sie die Leistung Ihrer Website oder Anwendung mit Google Analytics und der User Timings API analysieren und optimieren, um Ihre Nutzererfahrung zu verbessern.
Tools wie WebPagetest.org sind ein guter Ausgangspunkt für Leistungsoptimierungen. Der tatsächliche Test der Websiteleistung ist jedoch immer ein reales Bild der tatsächlichen Nutzer.
Wenn Sie eine Website betreiben, ist es sehr wahrscheinlich, dass Sie bereits Google Analytics verwenden, um Zugriffe zu messen und Daten zur Nutzung von Geräten und Browsern abzurufen. Mit zusätzlichem Code können Sie Leistungsmesswerte in den Mix aufnehmen.
Lerninhalte
- Wie Sie Leistungsmesswerte mit der User Timings API genau und effektiv messen können
- Diese Daten an Google Analytics senden und in Berichte einbinden
Voraussetzungen
- Ein Browser mit einer Entwicklerkonsole
- Webserver für Chrome oder Ihren eigenen Webserver Ihrer Wahl
- Der Beispielcode
- Ein Texteditor
- Optional: Google Analytics-Konto
Wie werden Sie diese Anleitung verwenden?
Wie würdest du deine Erfahrung beim Erstellen von Websites oder Anwendungen bewerten?
Sie können entweder den gesamten Beispielcode auf Ihren Computer herunterladen...
...oder das GitHub-Repository über die Befehlszeile klonen.
git clone https://github.com/googlecodelabs/performance-analytics.git
Der Beispielcode ist in Unterverzeichnisse unterteilt, die den nummerierten Schritten in diesem Lab entsprechen. Damit können Sie das Code-Lab ganz einfach überspringen oder prüfen, ob die Implementierung korrekt ist.
Wenn Sie Zugriff auf ein anderes Programm haben, können Sie sich genau ansehen, was sich Schritt für Schritt geändert hat.
In diesem Code-Lab erstellen Sie eine einzelne HTML-Datei, die folgende Assets lädt:
- Webschriftarten
- Stylesheets
- Bilder
- JavaScript
Außerdem erstellen Sie neuen Code, der die wichtigsten Leistungsmesswerte für jeden dieser Asset-Typen erfasst.
Hinweise zur Leistung von Assets
Wenn Sie schon einmal etwas zur Leistungsoptimierung gelesen haben, wissen Sie wahrscheinlich schon, dass jeder dieser Asset-Typen in eigenen Eigenheiten aussieht und sich auf verschiedene Weise auf die Gesamtleistung auswirken kann.
Preisvergleichsportal
Zum Beispiel blockieren Stylesheets das Rendering aller nachfolgenden Elemente im DOM. Das bedeutet, dass der Browser eine Anfrage für das Stylesheet stellen, es herunterladen und parsen muss, bevor der Inhalt des nachfolgenden DOMs gerendert werden kann. Aus diesem Grund empfiehlt es sich, Stylesheets normalerweise im <head>-Dokument zu platzieren. Und aufgrund der Blockierungsmöglichkeit von CSS wird außerdem häufig empfohlen, Ihr kritisches CSS nur im „<head>“ zu platzieren und das nicht kritische CSS anschließend asynchron zu laden.
JavaScript
JavaScript blockiert dagegen nicht das Rendering, sondern sperrt das Parsing und die Erstellung des DOMs. Das ist notwendig, weil JavaScript das DOM ändern kann. Wenn der Browser ein <script>-Tag sieht (außer asynchrone Skripts), muss der Code dann ausgeführt werden, bevor Sie zum nächsten Tag wechseln. Wenn das Tag <script> auf eine externe JavaScript-Datei verweist, muss der Code heruntergeladen und ausgeführt werden, bevor Sie fortfahren.
Aus diesem Grund wird oft empfohlen, Ihr JavaScript direkt vor dem schließenden Tag zu laden, damit der Großteil des DOMs so schnell wie möglich verfügbar ist.
Webschriftarten
Wenn Sie Webschriftarten laden, können Sie die Darstellung des Dokuments auch blockieren, bis die Schriftart verfügbar ist. In diesem Fall ist es wichtig zu verstehen, wie lange es tatsächlich dauert, bis Nutzer eine Aktion durchführen. Eine Webschriftart kann für die meisten Besucher, die Ihre Website besuchen, schnell und langsam laden. Daher ist es sehr wichtig, die Daten präzise zu analysieren.
Bilder
Schließlich kann eine Website zwar mit Bildern lebendig werden, aber sie haben oft auch die längste Ladezeit. Damit Sie Optimierungen vornehmen können, sollten Sie wissen, was das tatsächlich bedeutet und wie Sie Korrelationen zwischen Nutzungsmustern und Seitenladezeiten erkennen können.
Der erste Schritt in diesem Code-Lab besteht darin, sich anzusehen, wie die Demoseite aussieht, bevor Sie Code zur Leistungsmessung hinzufügen.
Erstellen Sie zur Anzeige der Demo einen neuen Ordner und fügen Sie darin eine Datei mit dem Namen „index.html“ hinzu. Kopieren Sie dann den Code unten und fügen Sie ihn in die Datei „index.html“ ein.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img src="http://lorempixel.com/380/200/animals/1/">
<img src="http://lorempixel.com/380/200/animals/2/">
<img src="http://lorempixel.com/380/200/animals/3/">
</div>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End JavaScript -->
</body>
</html>
Öffnen Sie als Nächstes den Webserver für Chrome und starten Sie einen lokalen Server in dem Verzeichnis, das Sie gerade erstellt haben. Achten Sie darauf, dass „&indexs;automatisch anzeigen“ angezeigt wird.
Rufen Sie in Ihrem Browser die Seite http://127.0.0.1:8887/ auf und sehen Sie sich die Demodatei an. Die Ausgabe sollte ungefähr so aussehen:
Nachdem Sie die Demoseite ausgeführt haben, nehmen Sie sich einen Moment Zeit, um sich den Code anzusehen und alle verschiedenen Asset-Typen zu sehen. In den nächsten Schritten fügen Sie Code hinzu, um zu messen, wann diese Assets geladen werden und mit dem der Nutzer interagieren kann.
Wie bereits im Abschnitt zur Leistung von Assets erwähnt, blockiert CSS das Rendering von DOM-Elementen sowie die Ausführung von Skripts, die im DOM danach eingehen.
Die soeben erstellte Demodatei enthält das folgende CSS, das auf Bootstrap und einige Inline-Styles verweist.
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->
Da CSS sowohl das Rendern von DOM-Elementen als auch die Ausführung von Skripts blockiert, können Sie feststellen, wann das CSS blockiert ist. Fügen Sie dazu ein <script>
-Tag unmittelbar nach dem Preisvergleichsportal hinzu, das die aktuelle Uhrzeit speichert.
Eine Variable lässt sich erstellen und new Date()
zuweisen. Dank der User Timings API ist das jedoch viel einfacher: die performance.mark
-Methode.
Wenn Sie möchten, dass das Preisvergleichsportal sowohl das Rendering als auch die Skriptausführung blockiert, fügen Sie die folgende Codezeile unmittelbar vor dem schließenden Kommentar <!-- End CSS -->
ein.
<script>performance.mark('css:unblock');</script>
Die Methode performance.mark
erstellt zu diesem Zeitpunkt einen hochauflösenden Zeitstempel und verknüpft ihn mit dem Namen, der an die Methode übergeben wurde. In diesem Fall haben Sie die Marke „quos;unblock"“ genannt.
Die Methode performance.mark
geht Hand in Hand mit der performance.measure
-Methode, mit der die Zeitunterschiede zwischen zwei Markierungen berechnet werden. Neben den Markierungen können Sie auch die Marken verwenden, die der Browser automatisch für die verschiedenen Punkte in der Navigation Timing API ausführt.
Mit der folgenden Dienstfunktion wird die Dauer zwischen einer von Ihnen hinzugefügten Markierung und der von der Navigation Timing API erstellten Markierung responseEnd gemessen und zurückgegeben.
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}
Erstelle eine neue Datei mit dem Namen perf-analytics.js
, die sich im selben Verzeichnis wie die index.html
-Datei befindet, und kopiere den oben aufgeführten Code in diese Datei.
Nachdem diese Funktion definiert ist, können Sie sie aufrufen und den Namen „"css:unblock"“ übergeben. Damit keine weiteren Ressourcen geladen werden, sollten Sie die Messungen auf später verschieben, bis das Ladeereignis des Fensters ausgelöst wird.
Nachdem Sie den Code mit einer Funktion aufgerufen haben, sollte die Datei perf-analytics.js
so aussehen:
window.onload = function() {
measureCssUnblockTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then logs that value to the console.
*/
function measureCssUnblockTime() {
console.log('CSS', 'unblock', measureDuration('css:unblock'));
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically).
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {number} The time duration
*/
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}
Abschließend müssen Sie das Skript perf-analytics.js
von index.html
laden. Fügen Sie dazu das Hauptskript-Tag in das Hauptdokument ein. Fügen Sie sie zuletzt hinzu, damit sie nicht das Laden anderer Ressourcen stört.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
Nachdem Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem im 01-css
-Verzeichnis des Code Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte in etwa die folgende Ausgabe angezeigt werden:
Webschriftarten werden normalerweise über ein externes Stylesheet geladen (siehe erste Demodatei):
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
Da es sich um ein <link>
-Tag in einer CSS-Datei handelt, kann es so wirken, als ob Sie herausfinden würden, wann die Schriftarten geladen und einsatzbereit sind – so wie in Schritt 1 direkt nach dem <link>
-Tag eine Marke innerhalb eines <script>
-Tags hinzugefügt wird.
Leider ist es nicht so einfach.
Mit Stylesheets wird die Ausführung von JavaScript blockiert, weil der Inhalt der Stylesheets zum Erstellen von CSSOM verwendet wird. Da das geladene JavaScript auf das CSSOM zugreifen muss, muss die Ausführung verzögert werden, bis das CSSOM vollständig erstellt wurde.
Der Vorteil ist, dass der Browser das CSSOM erstellen kann, ohne die Schriftart tatsächlich herunterzuladen. Wenn Sie also über ein Inline-Script-Tag im DOM direkt nach der Schriftart ein Zeichen hinzufügen, ist es wahrscheinlich, bevor die Schriftart vollständig geladen wird.
Bevor Schriftartereignisse für Browser verfügbar sind, muss JavaScript ermittelt werden, wann eine Schriftart aktiv ist und auf der Seite verwendet werden kann. Glücklicherweise wird das Laden von Schriftarten über JavaScript auch zu Leistungseinbußen führen, da keine zusätzliche Blockieranfrage an eine CSS-Datei erforderlich ist.
Die meisten Schriftarten (einschließlich Schriftarten von Google, typekit und font.com) können über das Skript webfont.js geladen werden, das gemeinsam von Google und Typekit entwickelt wurde.
Wenn Sie statt „<link>“ die Datei webfont.js zum Laden der Schriftarten verwenden möchten, ersetzen Sie die Schriftarten im Code durch Folgendes:
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->
Zwei wichtige Hinweise zum Code oben:
- Dadurch wird im aktiven Callback die Zeile „&font“:active" erstellt, mit der Sie später messen können, wie lange es dauert, bis die Schriftarten geladen werden.
- Das
<script>
-Tag, das „webfonts.js“ lädt, enthält das Attribut „async
“. Das Parsing oder Rendern des restlichen Dokuments wird dadurch nicht blockiert. Dies gilt nicht für<link>
-Tags.
Durch die oben genannten Codes werden zwar eine &font-Zeichen:aktiv&&t; Das liegt daran, dass die Schriftart jetzt asynchron geladen wird. Wenn Sie also versuchen, die Messung &":active " im window.onload
-Handler zu messen (wie bei &"css:unblock"), wird die Schriftart noch nicht geladen.
Zur Behebung dieses Problems können Sie ein Versprechen erstellen, das aufgelöst wird, sobald die Schriftart geladen wurde. Die folgende Funktion übernimmt das für Sie. Kopieren Sie ihn und fügen Sie ihn in die Datei „perf-analytics.js“ ein:
/**
* Creates a promise that is resolved once the web fonts are fully load or
* is reject if the fonts fail to load. The resolved callback calculates the
* time duration between the responseEnd timing event and when the web fonts
* are downloaded and active. If an error occurs loading the font, this fact
* is logged to the console.
*/
function measureWebfontPerfAndFailures() {
new Promise(function(resolve, reject) {
// The classes `wf-active` or `wf-inactive` are added to the <html>
// element once the fonts are loaded (or error).
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
// If the fonts are already done loading, resolve immediately.
// Otherwise resolve/reject in the active/inactive callbacks, respectively.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script fails to load, always reject the
// promise after the timeout amount.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
console.log('Fonts', 'active', measureDuration('fonts:active'));
})
.catch(function() {
console.error('Error loading web fonts')
});
}
Aktualisiere auch den window.onload
-Handler, um diese neue Funktion aufzurufen
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};
Nachdem Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem im 02-fonts
-Verzeichnis des Code Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte in etwa die folgende Ausgabe angezeigt werden:
Es ist nicht so einfach zu erkennen, wann ein Bild sichtbar ist. Aus vorherigen Schritten wissen wir, dass Stylesheets und synchrone <script>
-Tags das Rendering, das Parsen und die Skriptausführung blockieren können. Niemand weiß, dass keiner der Browser den Scanner zum Vorabladen blockiert.
Jeder moderne Browser implementiert einen Preload-Scanner als einen von vielen Versuchen, die Leistung zu verbessern. Dies gilt auch für Websites, die viele Blockier-Assets blockieren. Dabei können einige Assets zwar das Parsing oder Rendern oder die Ausführung von Skripts blockieren, sie müssen jedoch keine Downloads blockieren. Der Browser scannt die HTML-Datei, bevor das DOM erstellt wird, und sucht nach Assets, die sofort heruntergeladen werden können.
Im Hinblick auf die Bilder bedeutet dies, dass die Wahrscheinlichkeit sehr hoch ist, dass Ihre Bilder bereits zum Zeitpunkt des Hinzufügens zum DOM heruntergeladen werden. Das bedeutet auch, dass der Punkt, an dem ein Bild heruntergeladen wird, nicht unbedingt ein guter Leistungsmesswert ist. Der Leistungsmesswert ist der Punkt, an dem ein Bild für den Nutzer sichtbar ist.
Wenn ein Bild heruntergeladen wird, bevor es dem DOM hinzugefügt wird, ist der Punkt, an dem es sichtbar wird, der Punkt, an dem es im DOM erscheint. Wenn ein Bild hingegen nicht heruntergeladen wird, bevor es dem DOM hinzugefügt wurde, wird der Punkt sichtbar, an dem der onload
-Handler ausgelöst wird.
Damit Sie wissen, wann ein Bild sichtbar ist, müssen Sie beide Fälle bearbeiten.
Fügen Sie dazu Markierungen in jedem Onload-Handler von Bildern und in einem Inline-Skript auf dem Tag direkt nach dem letzten Bild im DOM ein. Dabei geht es um die Markierung, die angibt, wann alle Bilder sichtbar sind.
Wenn Sie Markierungen sowohl für das Laden der Bilder als auch für das Rendern der Bilder hinzufügen möchten, aktualisieren Sie den Bildcode in index.html
folgendermaßen:
<!-- Start images -->
<div class="gallery">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>performance.mark('img:visible')</script>
<!-- End images -->
Weil die performance.measure
-Methode für einen bestimmten Markennamen immer die letzte Markierung verwendet (wenn mehrere Marken mit demselben Namen gefunden werden), kann die Funktion measureDuration
in der Datei perf-analytics.js
ohne zusätzliche Änderungen verwendet werden:
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then logs that value to the
* console.
*/
function measureImagesVisibleTime() {
console.log('Images', 'visible', measureDuration('img:visible'));
}
Füge die oben genannte Funktion der Datei perf-analytics.js
hinzu und aktualisiere dann den window.onload
-Handler:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};
Nachdem Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem im 03-images
-Verzeichnis des Code Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte in etwa die folgende Ausgabe angezeigt werden:
Da <script>
-Tags ohne das async
-Attribut das DOM-Parsing blockieren, bis sie sowohl heruntergeladen als auch ausgeführt wurden, können Sie den Punkt, an dem alle Skripts ausgeführt wurden, ermitteln. Fügen Sie dazu direkt nach dem letzten synchronen <script>
-Tag im DOM eine Markierung in einem Inline-Skript-Tag hinzu.
Beachten Sie, dass die Verwendung von onload
-Handlern in diesem Fall nicht funktioniert, da der Browser das Skript nach dem Laden ausführen muss, was einige Zeit in Anspruch nimmt. Ein Skript, das schnell geladen, aber langsam ausgeführt werden kann, kann genauso schlecht sein wie ein langsam ladendes Skript.
Wenn Sie erfassen möchten, wann der gesamte JavaScript-Code im Hauptdokument geladen und ausgeführt wird, aktualisieren Sie den JavaScript-Abschnitt in index.html
mit folgendem Code:
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>performance.mark('js:execute');</script>
<!-- End JavaScript -->
Dadurch wird direkt nach den Skripts für die Plug-ins „jQuery“ und „Boottrap“ eine Markierung mit dem Namen „execute:execute“ hinzugefügt.
Fügen Sie perf-analytics.js
hinzu, um die Dauer der Messung zu messen:
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files have been downloaded and executed, then
* logs that value to the console.
*/
function measureJavaSciptExecutionTime() {
console.log('JavaScript', 'execute', measureDuration('js:execute'));
}
Rufe dann den Handler window.onload
auf:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
Nachdem Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem im 04-javascript
-Verzeichnis des Code Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte in etwa die folgende Ausgabe angezeigt werden:
Nicht alle Browser unterstützen JavaScript-Promise oder die User Timing APIs. Wenn Sie den Code, den Sie bisher in einem Browser ohne Unterstützung einer dieser Funktionen geschrieben haben, ausführen, erhalten Sie Fehler.
Das können Sie mit der Funktionserkennung tun. Fügen Sie das folgende Code-Snippet direkt vor den Schriftarten ein. Diese Zeile von JavaScript erkennt, dass die Methode performance.mark
unterstützt wird. Daher muss sie der Seite hinzugefügt werden, bevor diese Methode verwendet wird:
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->
Als Nächstes überall in index.html
, wo Sie performance.mark
aufrufen, muss ihm das Featureerkennung vorangestellt werden. Hier sehen Sie ein Beispiel für die Aktualisierung des Codes im Bildblock. Sie müssen jedoch auch die anderen Abschnitte aktualisieren.
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->
Da die Variable __perf
auf window
festgelegt ist, können Sie sie nun in perf-analytics.js
verwenden, um eine Methode aufzurufen, die im aktuellen Browser nicht unterstützt wird.
Die Funktion measureDuration
muss aktualisiert werden, um die folgende Bedingung hinzuzufügen:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}
Da nicht alle Browser JavaScript-Versprechen unterstützen, muss die Funktion measureWebfontPerfAndFailures
auch in eine Bedingung eingeschlossen sein:
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}
Sie sollten Ihren Code jetzt problemlos in einem beliebigen Browser ausführen können.
Nachdem Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem im 05-feature-detects
-Verzeichnis des Code Lab-Repositorys übereinstimmen.
Im letzten Schritt in diesem Codelab werden die Daten, die in der Konsole protokolliert werden, stattdessen an Google Analytics gesendet. Bevor Sie Daten an Google Analytics senden können, müssen Sie die analytics.js-Bibliothek und das Standard-Tracking-Snippet auf Ihrer Seite einfügen.
Fügen Sie index.html
den folgenden Code nach dem Haupt-JavaScript-Block und vor dem Laden des perf-analytics.js
-Skripts ein:
<!-- Start analytics tracking snippet -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics_debug.js"></script>
<!-- End analytics tracking snippet -->
Wenn Sie Google Analytics einer Website bereits hinzugefügt haben, müssen Sie den Platzhalter UA-XXXXX-Y durch die Tracking-ID ersetzen, die Sie beim Erstellen einer neuen Property in Google Analytics erhalten haben.
Das analytics.js-Tracking-Snippet wird folgendermaßen ausgeführt:
- Erstellt ein asynchrones
<script>
-Element, mit dem die analytics.js-JavaScript-Bibliothek heruntergeladen wird. - Initialisiert eine globale
ga()
-Funktion (GA-Befehlswarteschlange), mit der Sie die Ausführung von Befehlen für die analytics.js-Bibliothek planen können. - Fügt der Befehlwarteschlange
ga()
einen Befehl hinzu, um für die über den Parameter'UA-XXXXX-Y' angegebene Property ein neues Tracker-Objekt zu erstellen. - Fügt der Befehlwarteschlange
ga()
einen weiteren Befehl hinzu, um einen Seitenaufruf für die aktuelle Seite an Google Analytics zu senden.
Allein die mit den Seitenaufrufen erfassten Daten sind zwar nützlich, jedoch nicht die gesamte Geschichte. Wenn Sie sehen möchten, wie Nutzer Ihre Website oder App wahrnehmen, müssen Sie zusätzliche Interaktionsdaten an Google Analytics senden.
In Google Analytics werden verschiedene Arten von Interaktionsdaten unterstützt: Seitenaufrufe, Ereignisse, soziale Interaktionen, Ausnahmen und letztere Nutzerzeiten. Mithilfe der folgenden Befehlssignatur können Nutzertiming-Daten an Google Analytics gesendet werden:
ga('send', 'timing', timingCategory, timingVar, timingValue);
Dabei ist timingCategory
ein String, mit dem Sie Timing-Treffer in einer logischen Gruppe organisieren können, timingVar
die Variable, die Sie messen, und timingValue
die tatsächliche Dauer in Millisekunden ist.
Wenn Sie sehen möchten, wie das in der Praxis funktioniert, kann die Anweisung console.log
in der Funktion measureCssUnblockTime
folgendermaßen aktualisiert werden:
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));
Der oben beschriebene Code funktioniert zwar in einigen Situationen, es gibt jedoch zwei wichtige Hinweise:
- Im vorherigen Schritt wurde die
measureDuration
-Funktion so aktualisiert, dass sie nur dann ausgeführt wird, wenn der Browser die User Timings API unterstützt. Deshalb wird manchmalundefined
zurückgegeben. Da es keinen Grund gibt, nicht definierte Daten an Google Analytics zu senden, kann es in einigen Fällen sogar zu Verwirrung bei den Berichten kommen. Daher sollten Sie diesen Timing-Treffer nur senden, wennmeasureDuration
einen Wert zurückgibt. - Wenn
measureDuration
einen Wert zurückgibt, ist es einDOMHighResTimeStamp
, der eine höhere Genauigkeit als Millisekunden hat. DatimingValue
in Google Analytics eine Ganzzahl sein muss, müssen Sie den vonmeasureDuration
zurückgegebenen Wert runden.
Aktualisieren Sie die Rückgabeanweisung in der Funktion „measureDuration“, um den Rückgabewert zu runden, um diese Berechnungen zu berücksichtigen:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}
Aktualisieren Sie außerdem die Timing-Befehle, sodass nur der Wert des betreffenden Messwerts vorliegt. Die Funktion measureCssUnblockTime
sollte beispielsweise so aktualisiert werden:
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
Alle anderen Messfunktionen müssen ähnlich aktualisiert werden. Wenn Sie fertig sind, sollte die endgültige perf-analytics.js-Datei so aussehen:
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then sends this measurement to Google
* Analytics via a timing hit.
*/
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* the web fonts are downloaded and active, then sends this measurement to
* Google Analytics via a timing hit. If an error occurs loading the font, an
* error event is sent to Google Analytics.
*/
function measureWebfontPerfAndFailures() {
if (window.Promise) {
new Promise(function(resolve, reject) {
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script failed to load.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
var fontsActiveTime = measureDuration('fonts:active');
if (fontsActiveTime) {
ga('send', 'timing', 'Fonts', 'active', fontsActiveTime);
}
})
.catch(function() {
ga('send', 'event', 'Fonts', 'error');
});
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then sends this measurement
* to Google Analytics via a timing hit.
*/
function measureImagesVisibleTime() {
var imgVisibleTime = measureDuration('img:visible');
if (imgVisibleTime) {
ga('send', 'timing', 'Images', 'visible', imgVisibleTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files are downloaded and executed, then sends
* this measurement to Google Analytics via a timing hit.
*/
function measureJavaSciptExecutionTime() {
var jsExecuteTime = measureDuration('js:execute');
if (jsExecuteTime) {
ga('send', 'timing', 'JavaScript', 'execute', jsExecuteTime);
}
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically). The return value is rounded to the nearest whole
* number to be compatible with Google Analytics.
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {?number} The time duration as an integer or undefined if no
* matching marks can be found.
*/
function measureDuration(mark, opt_reference) {
if (window.__perf) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return Math.round(measure.duration);
}
}
Die endgültige Datei „index.html“ sollte so aussehen:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start navigation timing feature detect -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End navigation timing feature detect -->
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
__perf && performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<script>__perf && performance.mark('css:unblock');</script>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>__perf && performance.mark('js:execute');</script>
<!-- End JavaScript -->
<!-- Start analytics tracking snippet -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
<!-- End analytics tracking snippet -->
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
</body>
</html>
Wenn Sie die Seite laden und die Anfragen im Netzwerkbereich prüfen, wird Folgendes angezeigt:
Dies ist nützlich, kann jedoch mühsam sein, diese Daten als URL-codierte Anfrage anzusehen. Wenn Sie diese Anfragen aus irgendeinem Grund nicht sehen, können Sie wirklich herausfinden, wo der Fehler aufgetreten ist.
Ein besserer Ansatz bei der lokalen Entwicklung besteht darin, die Debug-Version von analytics.js zu verwenden, die nützliche Debugging-Informationen in der Konsole protokolliert, sobald jeder analytics.js-Befehl ausgeführt wird.
aktualisiere die analytics.js-URL in index.html
auf analytics_debug.js
und öffne die Browserkonsole. Die ausgegebenen Anweisungen sehen dann so aus:
Nachdem Sie jetzt wissen, wie die Leistungsmessung für diese Demoseite implementiert wird, können Sie versuchen, sie Ihrer eigenen Website hinzuzufügen, um echte Nutzerdaten an Google Analytics zu senden.
Berichterstellung zu den von Ihnen erhobenen Daten
Nachdem Sie einige Tage lang Leistungsdaten gesammelt haben, können Sie einen Bericht dazu erstellen, um umsetzbare Informationen darüber zu erhalten, wie schnell Ihre Website und deren Ressourcen für echte Nutzer geladen werden.
Wenn Sie die Berichte zum Nutzertiming aufrufen möchten, klicken Sie oben auf den Tab „Berichterstellung“ und wählen Sie in der Seitenleiste die Option „Verhalten > Websitegeschwindigkeit“ aus. Alternativ können Sie auch die Anleitung im Artikel Nutzertiming aufrufen.
Wenn Sie den Bericht „Nutzertiming“ in Google Analytics laden, sollten Sie die Timing-Kategorien sehen, die den von Ihnen gesendeten Daten entsprechen. Klicken Sie auf eine davon, um eine detaillierte Visualisierung Ihrer Timing-Daten aufzurufen. Die folgende Abbildung ist ein Beispiel für die Ladezeiten einer Schrift auf einer echten Website mit Google Fonts in den letzten 24 Stunden.
Glückwunsch! Sie haben dieses Code-Lab erfolgreich abgeschlossen. Im nächsten Abschnitt erhalten Sie einige Vorschläge, wie Sie diesen Code erweitern, um noch mehr Erkenntnisse zu erhalten.
Die in diesem Code-Lab behandelten Leistungsmesswerte sind wichtig, um zu messen, wie eine Website für echte Nutzer geladen wird. Doch das ist erst der Anfang. Wenn Sie sich genauer über Leistungsanalysen informieren möchten, können Sie ganz einfach weitere Messwerte erfassen.
In diesem Code-Lab haben Sie Messwerte in Bezug auf die Verfügbarkeit der Ressourcen für den Nutzer erfasst. Wenn Sie möchten, können Sie die meisten davon noch weiter unterteilen. So können Sie beispielsweise nicht nur messen, wann der JavaScript-Test abgeschlossen ist, sondern auch, wann der Ladevorgang abgeschlossen ist, wann er begonnen hat und schließlich abgeschlossen ist. Jeder dieser Messwerte könnte ein Problem aufdecken, von dem nur einer weiß.
Neben einer noch präziseren Analyse sollten Sie auch Ihre allgemeine Leistungsanalysestrategie überdenken. Was sind die Ziele? Was ist Erfolg?
Wenn es um Analysen geht, solltest du mit einer Art von Frage beginnen und dann herausfinden, wie du diese Frage anhand von Daten beantworten kannst.
Nehmen Sie sich beispielsweise die folgende Liste von Fragen an und wie Sie das Wissen, das Sie in diesem Code-Lab gewonnen haben, mithilfe von Analytics anwenden können.
- Entsprechen die Werte der Messwerte, die Sie erfassen, im Laufe der Zeit?
- Wie wirkt sich die Verwendung von Offline-Caching über Service Worker oder lokalen Speicher auf die Gesamtleistung Ihrer Website aus?
- Werden Ihre Ressourcen optimal geladen? Das heißt, es besteht eine große Lücke zwischen dem Download der Ressource und ihrer Verwendung?
- Gibt es einen Zusammenhang zwischen der Leistung und anderen Messwerten (z. B. Registrierungsrate, Zeit auf der Website, Käufen usw.).
Außerdem können Sie sich über die Webleistung und Google Analytics informieren. Hier finden Sie hilfreiche Ressourcen für den Einstieg:
- Tools und Informationen zum Erstellen leistungsstarker Websites
https://developers.google.com/speed/ - Tools und APIs für Entwickler zur Nutzung der Google Analytics-Plattform
https://developers.google.com/analytics/ - Onlinekurse, in denen das Google Analytics-Produkt selbst vorgestellt wird. Es ist für Personen konzipiert, die Google Analytics selbst nutzen.
https://analyticsacademy.withgoogle.com/