Helfen Sie Ihren Benutzern, `Daten zu sparen`

Avatar of Jeremy Wagner
Jeremy Wagner on

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Die Breite und Tiefe des Wissens, das man im Bereich der Web-Performance aufnehmen muss, ist *lächerlich*. Mindestens einmal pro Woche entdecke ich etwas Neues. Ein aktuelles Beispiel: Der Save-Data Header, den ich über einen Google Developers Artikel von Ilya Grigorik entdeckt habe.

Wenn Sie die *tl;dr*-Version davon suchen, wie Save-Data funktioniert, lass ich Sie nicht hängen: Wenn Sie auf der Android-Version von Chrome (oder der Data Saver Erweiterung auf Ihrem Desktop-Gerät) die Dateneinsparung aktivieren, sendet Chrome bei jeder Anfrage an einen Server einen Save-Data Header mit dem Wert On. Sie können dann auf diesen Header reagieren, um die Auslieferung von Inhalten Ihrer Website so zu ändern, dass Daten für den Benutzer gespart werden. Dies ist eine sehr offene Gelegenheit, die Ihnen geboten wird. Lassen Sie uns also ein paar Möglichkeiten erkunden, wie Sie auf den Save-Data Header reagieren können, um weniger Bytes über die Leitung zu senden!

Ändern Sie Ihre Bildlieferstrategie

Ich weiß nicht, ob Ihnen das aufgefallen ist, aber Bilder machen oft den größten Teil der gesamten Nutzlast einer Seite aus. Der vielleicht wirkungsvollste Schritt, den Sie mit Save-Data unternehmen können, ist also, die Art und Weise zu ändern, wie Bilder geliefert werden. Für meinen Blog habe ich mich entschieden, Anfragen für hochauflösende Bilder in niedrigauflösende Bilder umzuschreiben. Wenn ich solche Bildersets auf meiner Website serviere, verwende ich das <picture> Element, um WebP-Bilder mit einem JPEG- oder PNG-Fallback bereitzustellen, wie folgt

<picture>
  <source srcset="/img/george-and-susan-1x.webp 1x, /img/george-and-susan-2x.webp 2x">
  <source srcset="/img/george-and-susan-1x.jpg 1x, /img/george-and-susan-2x.jpg 2x">
  <img src="/img/george-and-susan-1x.jpg" alt="LET'S NOT GET CRAZY HERE" width="320" height="240">
</picture>

Diese Lösung wird durch in modernen Browsern integrierte Technik unterstützt. Das <picture> Element liefert das optimale Bildformat entsprechend den Fähigkeiten eines Browsers, während srcset dem Browser hilft zu entscheiden, was für den Bildschirm eines bestimmten Geräts am besten aussieht. Leider fehlt sowohl <picture> als auch srcset die Kontrolle darüber, welche Bildquelle für Benutzer, die Daten sparen möchten, bereitgestellt werden soll. Und das sollten sie auch nicht! Das ist nicht die Aufgabe von srcset oder <picture>.

Hier kommt Save-Data ins Spiel. Wenn Benutzer meine Website besuchen und einen Save-Data Request Header senden, verwende ich mod_rewrite in Apache, um niedrigauflösende Bilder anstelle von hochauflösenden zu liefern.

RewriteCond %{HTTP:Save-Data} =on [NC]
RewriteRule ^(.*)-2x.(png|jpe?g|webp)$ $1-1x.$2 [L]

Wenn Sie mit mod_rewrite nicht vertraut sind, ist die erste Zeile eine Bedingung, die prüft, ob der Save-Data Header vorhanden ist und den Wert on enthält. Das Flag [NC] weist mod_rewrite lediglich an, eine Fall-insensible Übereinstimmung durchzuführen. Wenn die Bedingung erfüllt ist, sucht die RewriteRule nach Anfragen für ein PNG-, JPEG- oder WebP-Asset, das mit -2x endet (die hochauflösende Version), und leitet solche Anfragen an ein Asset weiter, das mit -1x endet (die niedrigauflösende Version).

Jetzt kommt der seltsame Teil: Was passiert, wenn ein Benutzer die Datensparfunktion aktiviert hat, sie aber wieder deaktiviert und später mit einer unbegrenzten (d.h. WLAN-) Verbindung zurückkehrt? Da wir die Anfrage für ein -2x Bild heimlich in eine -1x geändert haben, wird der Browser die niedrigqualitative Version des Bildes aus dem Browser-Cache verwenden, anstatt die hochqualitative Version vom Server anzufordern. In diesem Szenario ist der Benutzer an eine niedrigqualitative Erfahrung gebunden, bis er seinen Browser-Cache leert (oder die Cache-Einträge ablaufen).

Wie beheben wir das? Die Antwort liegt im Vary Antwort-Header. Vary weist den Browser an, wie und ob er ein gecachtes Asset verwenden soll, indem Cache-Einträge bestimmten Headern zugeordnet werden. Werte für Vary sind einfach andere Headernamen (z.B. Accept-Encoding, User-Agent, usw.). Wenn wir möchten, dass der Browser Inhalte basierend auf dem Vorhandensein des Save-Data Headers cacht, müssen wir lediglich den Server so konfigurieren, dass er einen Vary Antwort-Header mit dem Wert Save-Data sendet, wie folgt.

<FilesMatch "\.(gif|png|jpe?g|webp)$">
  Header set Vary "Save-Data"
</FilesMatch>
<FilesMatch "\.svg$">
  Header set Vary "Accept-Encoding, Save-Data"
</FilesMatch>

In diesem Beispiel sende ich einen Vary Antwort-Header mit dem Wert Save-Data, wann immer GIF-, PNG-, JPEG- oder WebP-Bilder angefordert werden. Im Fall von SVGs sende ich einen Vary Header mit dem Wert Accept-Encoding, Save-Data. Der Grund dafür ist, dass SVGs komprimierbare Text-Assets sind. Daher möchte ich sicherstellen, dass der Browser (und jeder Zwischen-Cache, wie z.B. ein CDN) den Wert des Accept-Encoding Headers *zusätzlich* zum Save-Data Header berücksichtigt, wenn er entscheidet, wie Einträge aus dem Cache abgerufen werden.

Bildlieferung mit und ohne Datensparfunktion

Als Ergebnis haben wir nun eine Bildlieferstrategie, die den Benutzern hilft, Daten zu sparen, *und* den Browser-Cache mit Bildern füllt, die nicht bestehen bleiben, wenn der Benutzer die Datensparfunktion später deaktiviert.

Natürlich gibt es andere Möglichkeiten, wie Sie die Bildlieferung bei Vorhandensein von Save-Data ändern könnten. Zum Beispiel schrieb Cory Dowdy einen Beitrag, in dem er beschreibt, wie er Save-Data verwendet, um Bilder von geringerer Qualität zu liefern. Save-Data gibt Ihnen viel Spielraum, um eine Bildlieferstrategie zu entwickeln, die für Ihre Website oder Anwendung am sinnvollsten ist.

Server-Pushes ablehnen

Server-Push ist großartig, wenn Sie HTTP/2 verwenden und es nutzen können. Es erlaubt Ihnen, Assets an den Client zu senden, bevor dieser überhaupt weiß, dass er sie benötigt. Das Problem dabei ist jedoch, dass es in bestimmten Szenarien seltsam unvorhersehbar sein kann. Auf meiner Website nutze ich es nur zum Pushen von CSS, und das funktioniert im Allgemeinen gut. Allerdings passe ich meine Push-Strategie in Apache an, um Browser zu vermeiden, die damit Probleme haben (z.B. Safari), wie folgt.

<If "%{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i">
  Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style; nopush"
</If>
<Else>
  Header add Link "</css/global.5aa545cb.css>; rel=preload; as=style"
</Else>

In diesem Fall sage ich: "Hey, ich möchte, dass Sie proaktiv das CSS meiner Website pushen, aber nur, wenn sie nicht Safari verwenden." Selbst wenn Safari-Benutzer vorbeikommen, erhalten sie immer noch einen preload Ressourcenhinweis (wenn auch mit dem Attribut nopush, um zu verhindern, dass mein Server etwas pusht).

Dennoch wäre es ratsam, bei Push-Vorgängen für Benutzer mit aktivierter Datensparfunktion besonders vorsichtig zu sein. Auf meinem Blog habe ich entschieden, niemandem etwas zu pushen, der die Datensparfunktion aktiviert hat. Um dies zu erreichen, habe ich die folgende Änderung am ursprünglichen <If> Header vorgenommen.

<If "%{HTTP:Save-Data} == 'on' || %{HTTP_USER_AGENT} =~ /^(?=.*safari)(?!.*chrome).*/i">

Das ist dasselbe wie meine ursprüngliche Konfiguration, aber mit einer zusätzlichen Bedingung, die besagt: "Hey, wenn Save-Data vorhanden und auf den Wert on gesetzt ist, pushe dieses Stylesheet nicht. Lade es stattdessen nur mit preload vor." Das mag keine große Änderung sein, aber es ist eines dieser kleinen Dinge, die Besuchern helfen könnten, verschwendete Daten zu vermeiden, falls ein Push aus irgendeinem Grund vergeblich war.

Ändern Sie, wie Sie Markup ausliefern

Mit Save-Data könnten Sie wählen, welche Teile des Dokuments Sie ausliefern. Dies eröffnet allerlei Möglichkeiten, aber bevor Sie sich auf diese Aufgabe einlassen, müssen Sie den Save-Data Header in einer Backend-Sprache prüfen. In PHP könnte eine solche Prüfung etwa so aussehen.

$saveData = (isset($_SERVER["HTTP_SAVE_DATA"]) && stristr($_SERVER["HTTP_SAVE_DATA"], "on") !== false) ? true : false;

Auf meinem Blog verwende ich diese $saveData Boolesche Variable an verschiedenen Stellen, um Markup für Bilder zu entfernen, die für den Inhalt einer bestimmten Seite nicht entscheidend sind. Zum Beispiel einer meiner Artikel enthält einige animierte GIFs und andere humorvolle Bilder, die für Benutzer, die nichts dagegen haben, lustige kleine Verzierungen sind. Aber sie sind *schwer* und nicht wirklich notwendig, um den Kern des Artikels zu vermitteln. Ich entferne auch die Header-Illustration und ein winziges Thumbnail meines Buches aus der Navigation.

Markup-Lieferung von Bildern mit und ohne Datensparfunktion

Aus Sicht der Nutzlast kann dies sicherlich tiefgreifende Auswirkungen haben.

Die potenziellen Auswirkungen der Datensparfunktion auf die Seitenlast

Eine weitere Möglichkeit wäre, die oben genannte $saveData Boolesche Variable zu verwenden, um eine save-data Klasse auf das <html> Element zu setzen.

<html class="<?php if($saveData === true) : echo("save-data"); endif; ?>">

Mit dieser Klasse könnte ich dann Stile schreiben, die ändern könnten, welche Assets in background-image Eigenschaften verwendet werden, oder jede CSS-Eigenschaft, die externe Assets referenziert. Zum Beispiel:

/* Just a regular ol' background image */
body {
  background-image: url("/images/bg.png");
}

/* A lower quality background image for users with Data Saver turned on */
.save-data body {
  background-image: url("/images/bg-lowsrc.png");
}

Markup ist nicht das Einzige, dessen Lieferung Sie ändern könnten. Sie könnten dasselbe für Videos tun oder etwas so Einfaches wie die Auslieferung von weniger Suchergebnissen pro Seite. Es liegt ganz bei Ihnen!

Fazit

Der Save-Data Header bietet Ihnen eine großartige Gelegenheit, Benutzern zu helfen, die Sie bitten, ihnen zu helfen, nun ja, Daten zu sparen. Sie könnten URL-Rewriting verwenden, um die Medienlieferung zu ändern, die Art und Weise, wie Sie Markup liefern, zu ändern, oder wirklich fast alles, was Ihnen einfällt.

Wie werden Sie Ihren Benutzern helfen, `Daten zu sparen`? Hinterlassen Sie einen Kommentar und lassen Sie Ihre Ideen hören!


Cover of Web Performance in Action

Jeremy Wagner ist der Autor von Web Performance in Action, jetzt erhältlich bei Manning Publications. Verwenden Sie den Promo-Code sswagner, um 42% zu sparen.

Schauen Sie ihn sich auf Twitter an: @malchata