Neue Antworten auf neue Fragen zu Webtechnologien braucht das Land? Kein Problem! Falls ihr noch mehr Fragen zu HTML5, CSS3, JavaScript, Web Components oder ähnlichem beantwortet haben wollt, schreibt sie mir per E-Mail oder gebt die Frage per Twitter ab.

Sind Web Components schlecht für die Performance?

Sind Web Components nicht eine Katastrophe für die Performance? So spaltet sich doch die komplette Seite in hundert Einzel-Downloads auf, jede Komponente lädt jedes Mal neu jQuery … oder gibt es da einen Trick?

Heutzutage ist das möglicherweise tatsächlich ein Problem, das sich aber in Zukunft von selbst in Luft auflösen wird. Das Doppel-Download-Problem besteht in Browsern mit nativer Unterstützung für Web Components gar nicht erst, da hier Doppel-Requests automatisch dedupliziert werden (so liest man jedenfalls allerorten; in konkreten Specs habe ich nichts gefunden, das das verlangt). Im Polymer-Polyfill passiert das einfach anhand des Ressourcen-Pfades, die native Implementierung soll auch identische Ressourcen aus unterschiedlichen Quellen deduplizieren können.

Dass Web Components dann immer noch zu vielen Einzel-Requests führen, ist in nicht all zu ferner Zukunft ein Feature und kein Bug. Mit HTTP/2 bzw. SPDY als Netzwerkprotokoll hat man, anders als beim HTTP 1.1 von heute, keinen Vorteil mehr, wenn man Ressourcen zusammenfasst. Im Gegenteil: wenn man sein Frontend in viele kleine Teile aufsplittet, hat man den Vorteil, dass bei der Änderung einer einzigen Icongrafik der Nutzer nicht mehr das komplette Bild-Sprite, sondern wirklich nur eine einzige Winzdatei neu herunterladen muss. Anders gesagt übernimmt HTTP/2 das Zusammenfassen von Dateien auf Protokollebene und Webentwickler müssen es nicht mehr selbst machen. Und nur die üblichen Verdächtigen (d.h. IE und Safari) können das nicht bereits heute. Mehr Infos zum Thema gibt es in einem epischen Slide Deck aus der Feder von Performance-Papst Schepp.

Die Web-Component-Performance-Problematik löst sich also im Laufe der Zeit von selbst. Bis dahin kann man sich mit Vulcanize, einem Tool zum Zusammenfassen von HTML-Imports inklusive aller Ressourcen in eine einzige Datei, behelfen.

CSS-Variablen und JavaScript

Kann man native CSS-Variablen (Custom Properties) via JavaScript ändern?

Man wird das machen können, allerdings ist noch nicht klar wie genau das im endgültigen Standard funktionieren wird. Das was im aktuellen Working Draft steht, hat aktuell nicht viel mit dem zu tun, was man in heutigen Browsern vorfindet. Zur JavaScript-API wird sogar nur angesagt, dass es eine a custom-property API to be defined in the future geben wird – nichts Konkretes weit und breit.

Dass es aber zumindest im Prinzip eine solche API geben kann, zeigt diese simple Demo (läuft nur im Firefox mit aktiviertem CSS-Variablen-Flag), die noch eine alte API aus früheren Spezifikationen verwendet. Wie es in Zukunft gehen wird, ist noch unklar, aber irgendwie wird es wohl funktionieren.

Data-URLs mit JavaScript laden

Ajax-Requests auf Data URLs werden von der Same Origin Policy unterbunden. Kann man Data-URIs noch anders (also ohne XHR) laden?

Mit der File API geht das. Man nehme die Data-URL, packe sie in einen Blob, lese diesen mittels eines FileReaders aus und schon ist das Ergebnis da:

var dataUrl = 'data:text/plain,Hallo Welt';
var dataString = dataUrl.split(',')[1];
var mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
var blob = new Blob([dataString], {type: mimeString});
var reader = new FileReader();
reader.readAsText(blob);
reader.onload = function(evt){
  window.alert(evt.target.result);
};

Wenn man aber schon zur File API und zu Blobs greift, kann man auch weiterhin XHR verwenden. Es gibt Blob-URLs die aufgrund einer Ausnahme in der der Same Origin Policy auch von XHR abgerufen werden können. So klappt es dann auch ohne File Reader und mit XHR:

var dataUrl = 'data:text/plain,Hallo Welt';
var dataString = dataUrl.split(',')[1];
var mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
var blob = new Blob([dataString], {type: mimeString});
var blobUrl = window.URL.createObjectURL(blob);
$.get(blobUrl, function(result){
  window.alert(result);
});

Der einzige Browser in dem das nicht klappt, ist der Internet Explorer: der macht bekanntlich die Same Origin Policy falsch.

Asynchron ladende Web Components?

Wenn ich viele Web Components via HTML-Import in meine Seite lade, ist das nicht gut für die Performance. Kann ich hier auch das async-Attribut verwenden? Funktionieren die Komponenten dann noch?

Laut Spezifikation für HTML Imports wird es das async-Attribut für <link>-Elemente geben, so dass das Laden von externen Ressourcen nicht mehr blockiert. Die im Rahmen von Web Components selbst erstellten Elemente funktionieren dann auch problemlos. Es ist nicht erforderlich, den HTML-Parser vor Erreichen des noch anzumeldenden Elements „abzufangen“, da die Mechanik von document.registerElement() ohnehin nur ein nachträgliches Upgrade von schon durch den Parser als unbekannt verarbeiteten Elementen vornimmt.

Die Herausforderung hierbei ist natürlich die Zeitspanne bis ein Element geladen und einsatzbereit ist. Durch umsichtige Programmierung und passendes Styling gilt es, nerviges Geflacker zu unterbinden; entsprechende Callbacks und CSS-Pseudoklassen helfen dabei. Polymer feuert ein hilfreiches polymer-ready-Event auf window, sobald alle Elemente beim Browser angemeldet sind.

Weitere Fragen?

Auch eure Fragen zu HTML5, JavaScript und anderen Webtechnologien beantworte ich gerne! Einfach eine E-Mail schreiben oder Twitter bemühen und ein bisschen Geduld mit der Antwort haben. Ansonsten kann man mich natürlich auch als Erklärbär zu sich kommen lassen.