mobile Web Performance Optimization mit Chromiums 38 Responsive Design View

Der Titel ist ein ziemlicher Buzzword Dump, hält aber was er verspricht.

TL;DR

Mit Hilfe der Responsive Design View im Chromium((Responsive Design Mode – Ein Werkzeug welches verschiedene Geräteprofile und Netzverbindungen simulieren kann)) 38, konnte ich schnell Flaschenhälse auf einer Seite erkennen und mit kleinen Handgriffen beheben.

Neben einer kleinen Theorie-Runde gibt es weiter unten die Messwerte vor und nach der Optimierung, Verbesserungen um 66% sind drin!

und los…

Bis gestern habe ich immer das Firefox Responsive Design View genutzt. Das äquivalente Tool im Chromium war mir bekannt, aber ich fand es nicht so intuitiv wie beim Firefox.

Der Ansatz im Firefox war einfach direkter, allerdings muss man als Anwender das Device Pixel Ratio((Device Pixel Ratio – Hierbei weicht die native Auflösung eines Displays, zum Beispiel Full HD (1920×1080), von der im Gerätebrowser verfügbaren um einen bestimmten Faktor ab)) Konzept verstanden haben und die meta name="viewport" Angabe nicht vergessen.

Also zur Theorie

Device Pixel Ratio???

Ganz kurz erklärt: Die [Smartphone/Tablet] Hersteller prahlen mit immer höheren Auflösungen in ihren Geräten. Ein LG G3 hat auf 5,5 Zoll 1.440×2.560 Pixel gepresst. Wenn man im mobilen Browser aber die Höhe und Breite des Fensters ausliest, stellt man fest, das nur ein Bruchteil der nativen Auflösung angegeben wird‽ Hier spielt die DPR eine Rolle, beim LG G3 beträgt diese vier (4). Das heißt, dass man die native Auflösung durch die DPR teilen muss um die Größe im Browser zu wissen. Auf mydevice.io((mydevice.io – Ein Service der sehr viele DPR und weitere Geräteeigenschaften auflistet)) findet man vom eigenen Gerät die DPR und alles was man wissen will.

<meta name=“viewport“ content=“….“>?

Es gab einen Moment da surften schon viele Menschen mit ihrem Smartphone durch das Web, aber die Webseiten waren noch gar nicht angepasst dafür. In diesem Fall zoomte der mobile Browser einfach die komplette Website auf eine Art Vogelperspektive und zum Beispiel mit einem Doppeltab kann man hinein- und herauszoomen.

Dann kam Responsive Web Design überall an und mit der <meta name="viewport" content="....">?((Using the viewport meta tag… – Beitrag zu dem Thema im Mozilla Developer Network)) Angabe teilt man dem mobilen Browser mit, wie groß der Viewport sein soll. Meistens setzt man hier die Device Höhe und Breite rein: <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">.

Desktop Browser ignorieren diese Angabe und verhalten sich beim resizen so, wie man das von seinem Telefon erwarten würde, aber ohne diese Angabe wird das Telefon ein anderes Ergebnis anzeigen.

Round Trip Time (RTT)

Der interessanteste Punkt beim mobile Web ist neben der Datenrate die eine Verbindung bereitstellt (LTE, 3G, EDGE, GPRS, WLAN usw.) die Round Trip Time((Wikipedia: Paketumlaufzeit)) einer Verbindung. Grob umschrieben ist das die Zeit, die ein Datenpaket in einem Netz unterwegs ist.

Neben der Zeit, die man sowieso für den Download dieser Ressource benötigt, kommt die RTT noch hinzu. Selbst eine kleine Datenmenge braucht über EDGE also länger, als über 3G.

Um ein Gefühl für die Geschwindigkeit der eigenen Seite bei einem mobilen Abruf zu bekommen, ist es wichtig die Datenrate (Bits pro Sekunde) zu kontrollieren und die RTT Werte im Testing zu berücksichtigen.

Und genau dieses Feature bietet Chromium 38 in der Responsive Design View…

Web Performance Optimierung mit diesem Tool

Genug der Theorie, ich habe das Tool gestern sofort bei einem One Pager, den ich kürzlich erstellt habe, ausprobiert. Als Geräteprofil nutze ich das Profil des Nexus 4.

Bei einem One Pager ist die First Impression Zeit natürlich enorm wichtig. Zum Einen existiert nur eine einzige Seite und dann ist diese meistens noch inhaltsreicher als bei einem normalen Webauftritt mit Unterseiten.

Testszenario

Meine Beispielwebseite ist die Stiftung Tag am Meer((Stiftung Tag am Meer – Link)), die ich kürzlich im Auftrag meines Arbeitgebers der pro in space GmbH((pro in space gmbh – Link)) mit Contao 3.3((Contao Open Source CMS – Link)) umgesetzt habe.

Zur Analyse habe ich die Website auf meinem Rechner gespiegelt (ein LAMP Stack mit Apache 2.4, PHP 5.5 und mysql 5.5) um bei den Messungen keine äußeren Einflüsse zu erhalten.

Messwerte

Alle Ergebnisse sind aus dem Netzwerkreiter des Chromiums abgeschrieben:

×LadezeitloadDOMreadyScreen
Beispielseite ohne Optimierungen
Wifi((Wifi – Datenrate 30 Mbps, 2ms RTT ))780ms729ms480mswifi.unoptimized
3G/UMTS((3G/UMTS (Universal Mobile Telecommunications System) – Datenrate 750 Kbps, 100ms RTT))13.85s13.64s2.11s3g.unoptimized
EDGE((EDGE (Enhanced Data Rates for GSM Evolution) – Datenrate 250 Kbps, 300ms RTT))41.35s40.75s6.81sedge.unoptimized
GPRS((GPRS (General Packet Radio Service) – Datenrate 50 Kbps, 500ms RTT))3.4m3.4m37.34sgprs.unoptimized

Fazit

Das große Hintergrundbild ist ein echter Showstopper. Insgesamt werden pro Abruf 27 GET Requests ausgeführt. Hier muss man schauen, ob man die nicht bündeln kann. Ob der komplette FontAwesome gebraucht wird, steht auch zur Frage.

Die Optimierung

Hintergrundbild

Das große Fullscreen Hintergrundbild spielt seine stärken nur auf Tablets und Desktops aus. Daher muss es auch nur in deren Media Queries eingebunden werden. Für Smartphones reicht ein kleinerer Ausschnitt des Bildes, der Landscape und Portrait abdeckt. Ich habe einfach mal einen quadratischen Ausschnitt aus der Mitte gewählt in 723×723 Pixel und 72,8 kB Dateigröße.

Javascripte zusammenfassen

: Nun habe ich mir Grunt: The Javascript Task Runner((Grunt – The Javascript Task Runner)) angeschaut, womit alle JS Dateien, konkateniert und uglifiziert werden. Auch für compass((Compass – an open-source CSS Authoring Framework)) gibt es Erweiterungen. Ich habe das Gruntfile nun unten angefügt, anstatt des Shell Scriptes.

Neben jQuery werden auch noch das jquery.easing.plugin und jquery.scrollto geladen. Dazu kommt noch das bootstrap.js und die app.js mit der Anwendungslogik, aktuell beide nicht minifiziert (ouch!).

Die jQuery Dateien können gefahrlos zusammengefasst werden. Damit spart man 2 GET Requests.

Die bootstrap.js beinhaltet alle Bootstrap((Bootstrap – The most popular Responsive Web Design Framework)) Komponenten, auch jene die nicht genutzt werden. Da ich mich gerade aber nicht mit Code Refactoring aufhalten will, wird das bootstrap javascript auch nur minifiziert und in die javascript bundle Datei eingefügt. Zur Minifizierung nutze ich Brackets und das Minifier Plugin zur Javascript Minifzierung grunt-uglify((grunt-contrib-uglify – Minifizierung und Uglifizierung von Javascript Dateien mit Uglify.js)).

Der alte Workflow ergibt mit Grunt keinen Sinn mehr. Mit Grunt dreht sich dieser Ablauf um. Man behält an einem Ort alle Javascript Dateien vor. Diese werden bei einer Änderung dann mit grunt-concat((grunt-contrib-concat – Zusammenfassung von Javascript Dateien) um danach in mit grunt-uglify zu einer (oder mehreren) produktionsfertigen Dateien minifziert zu werden:

...
    jshint: {
        files: ["src/js/app.js"]
    }, 
 
    concat: { 
        options: {
           separator: ";" 
        }, 
        dist: {
            src: [
                "src/js/jquery-1.11.1.js",
                "src/js/jquery-easing.1.3.js",
                "src/js/jquery-scrollto.js",
                "src/js/bootstrap.js",
                "src/js/app.js"
            ], 
           dest: "js/app.js" 
        } 
   }, 
 
   uglify: {
       options: {
           banner: "/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today(\"dd-mm-yyyy\") %&gt; */\n",
           report: "min",
           mangle: false 
       },
       dist: {
           files: {
              "js/app.min.js": ["&lt;%= concat.dist.dest %&gt;"] 
           }
       }
   },
 
  ...
 
    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks("grunt-contrib-concat");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.registerTask("default", ["jshint", "concat", "uglify"]);

Durch die Minifizierung ist die bootstrap Datei von 60.4 kB auf 31.6 kB geschrumpft.

Das gleiche mache ich noch mit der app.js, die von 6.7 kB auf 2.9 kB schrumpft.

Die Zusammenfassung der Javascript Dateien führe ich in der Shell durch, da Editoren häufig mit großen minifizierten Javascriptdetaien überfordert sind:

cat jquery-1.11.1.min.js > js.tam-bundle.min.js
cat jquery-easing.1.3.min.js >> js.tam-bundle.min.js
cat jquery-scrollto.min.js >> js.tam-bundle.min.js
cat bootstrap.min.js >> js.tam-bundle.min.js
cat app.min.js >> js.tam-bundle.min.js

Die Javascript-Sammlung ist nun 134 kB groß und spart 4 GET Requests.

Ich habe noch den grunt-jshint((grunt-contrib-jshint – Javascript Code Qualität Check)) Task für die eigenen Javascript Dateien eingebaut. Das erscheint jedem erstmal sehr nervig, da dieser Task bei Fehlern direkt abbricht, aber auf der anderen Seite zwingt es einen direkt besseres Javascript zu schreiben, welches auch beim Minifzieren keine Probleme bereiten wird.

Das Ergebnis

Ich habe die Javascripte in einer Datei zusammengefasst, minifiziert und im Layout eingebunden. Zusätzlich habe ich das große Hintergrundbild per media queries nur noch bestimmten Adressaten ausgeliefert. Alle anderen bekommen ein kleines Bild zu sehen, ohne UX Einschränkung.

×LadezeitloadDOMreadyScreen
Beispielseite mit Optimierungen
Wifi553ms (780ms, -29,1%)501ms (729ms, -31,3%)308ms (480ms, -35,8%)wifi.optimized
3G/UMTS6.45s (13.85s, -53,4%)4.70s (13.64s, -65,5%)2.83s (2.11s, +34,1%)3g.optimized
EDGE14.48s (41.35s, -65%)13.98s (40.75s, -66%)8.44s(6.81s, +23,9%)edge.optimized
GPRS1.2m (3.4m, -64,7%)1.1m (3.4m, -67,6%)44.92s (37.34s, +20,3%)gprs.optimized

Fazit

Sicherlich hat die Anpassung des Hintergrundbildes den größten Gewinn gebracht. Für die kleineren Geräte ist der Fußabdruck der Seite von auf 1.2 MB auf 410 KB gefallen. Das entspricht einer Einsparung um 65%.

Das Zusammenfassen der Javascript Dateien ist verantwortlich für die gestiegenen DOMContentLoaded Zeiten. In der ersten Version wurden einige Skripte mit dem async Attribut geladen. Dieses hatte ich beim umschreiben entfernt, wodurch der Browser nun das große Javascript Bündel komplett laden muss, bevor er das DOMContentLoaded Event feuern kann.

Nach der Umstellung auf async habe ich für 3G folgende Veränderung feststellen können: total load time: 6.41s, load: 4.68s, DOMContentLoaded: 1.32s.

Der Aufwand für diese Optimierung war gar nicht mal so groß. Mit Aufsetzen der Testumgebung, Definition des Testszenarios (Nexus 4, etc.), Messen der vier Verbindungen, Analyse, Maßnahmen treffen und Nachmessen der Ergebnisse kommt man auf ca. einen halben Tag. Die Dokumentation und das Anfertigen aller Screenshots hat nochmal genauso lange gedauert.

Ohne das Tool im Chromium wäre es mir nicht so einfach gefallen, die gewinnbringenden Punkte so schnell herauszufinden und in Angriff zu nehmen.

2013 hatte ich ja festgestellt dass „meine mobile Webseite ist langsam((meine mobile Webseite langsam ist))“ und jetzt kann ich auch sagen warum! Wieder eine Ausrede weniger ;-)

Ende gut, alles gut?

Wenn man nun immer noch nicht genug hat, wäre der nächste Schritt alle Webfonts anders auszuliefern als bisher, nämlich wie hier beschrieben: high performance webfont loading((Loading webfonts with high performance on responsive websites)).

Dazu kann man noch das Bootstrap verkleinern, indem man nicht genutzte Komponenten gar nicht erst mit ausliefert. Das könnte man entweder über die Bootstrap Customize((Bootstrap Customize)) Funktion machen, oder in meinem Fall mit der (noch nicht öffentlichen) Barebone Theme Extension für Contao.

Wenn dann noch der WebServer entsprechend gute Far Future Expire Header mitsendet wird die Optimierungsluft langsam dünn.

2 thoughts to “mobile Web Performance Optimization mit Chromiums 38 Responsive Design View”

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.