Transkript

Transklusion

Frontendintegration im Web

Lucas Dohmen spricht mit Franziska Dessart über Transklusion, eine Möglichkeit, Web-Anwendungen über das Frontend miteinander zu integrieren. Themen sind unter anderem: Wie kann man diese Methode konkret einsetzen, um Web-Anwendungen lose zu koppeln? Welche Möglichkeiten zur Transklusion gibt es und wann ist welche Art angebracht? Außerdem geht es im Gespräch um den Umgang mit Fehlern, Caching und Testen.

Zurück zur Episode

Transkript

Lucas Dohmen: Hallo und herzlich willkommen zu einer neuen Folge des INNOQ Podcasts. Heute habe ich mir die Franzi eingeladen. Hallo Franzi!

Franziska Dessart: Hallo Lucas!

Lucas Dohmen: Magst du dich kurz vorstellen?

Franziska Dessart: Ja, gerne. Ich bin Franziska Dessart, ich bin jetzt seit über einem Jahr bei der INNOQ und meistens im Bereich Webapplikationen unterwegs.

Lucas Dohmen: Super. Wir wollen heute über Transklusion sprechen. Magst du uns kurz erklären, was Transklusion so grundlegend ist?

Franziska Dessart: Transklusion ist ein Begriff, der wurde 1982 von Ted Nelson geprägt. Das ist jemand, der an den Grundlagen des Webs mitgearbeitet hat. Bei der Transklusion geht es in erster Linie darum, Dokumente aus Einzeldokumenten zusammenzustellen, indem ich ein Wurzeldokument aufrufe, das Referenzen enthält auf andere Dokumente. Die bringe ich zur Laufzeit dann zusammen, um ein Ganzes zu erstellen.

Lucas Dohmen: Und warum möchte ich sowas machen? Warum möchte ich solche Dokumente zusammenführen?

Franziska Dessart: Das kann verschiedene Gründe haben. Zum einen kann es halt sein, dass ich eine Architektur in meinem System habe, wo das Gesamtsystem in kleinere Teile zerschnitten ist. Dann brauche ich einen Weg, um die Teile des Systems wieder zusammenzubringen, vom Frontend her. Oder ich kann andere Ziele verfolgen, wie zum Beispiel die Performance des Gesamtsystems zu steigern. Dann kann ich meine Einzelsysteme, bzw. dessen Ressourcen so schneiden, dass ich Teile davon gut cachen kann, was insgesamt die Performance steigert.

Lucas Dohmen: Okay. Also ein Anwendungsszenario wäre zum Beispiel Self-contained Systems?

Franziska Dessart: Ja, zum Beispiel.

Lucas Dohmen: Okay. Was gibt es denn noch für andere Strategien, solche Systeme miteinander zu vernetzen?

Franziska Dessart: Da kann ich mir vielfältige Möglichkeiten ausdenken. Eine spontane Reaktion von Leuten, die Systeme bauen ist: Ich baue mir einen Frontend-Monolithen davor und integriere über den. Das ist aber vielleicht keine so gute Idee, weil ich dann alles, was ich mit meiner modularisierten Backend-Architektur bezweckt habe, dadurch quasi konterkariere. Weil ich dann die ganzen Abhängigkeiten, die ich ja eigentlich vermeiden wollte, halt dann in diesem Frontend-Monolithen wieder habe.

Lucas Dohmen: Was wäre jetzt dein Gegenvorschlag? Was könnte man stattdessen tun?

Franziska Dessart: Stattdessen kann man sich auf die Grundprinzipien des Webs verlassen und Mechanismen einsetzen, wie zum Beispiel Link-Integration, Transklusion und Redirects. Das sind drei Punkte, die sich gegenseitig ergänzen, die gut zusammen spielen und mit denen ich diesen Anwendungsfall gut abdecken kann.

Lucas Dohmen: Du hast jetzt schon gesagt, einer der Gründe, warum ich das machen möchte, ist aus Achitekturüberlegungen heraus. Aber es gibt ja durchaus auch Aspekte wie Performance und Usability, die da reinspielen. Welchen Einfluss hat denn diese Strategie darauf?

Franziska Dessart: Genau, also ich kann die Transklusion einsetzen, um Performance zu steigern. Das mache ich, indem ich meine Ressourcen entsprechend schneide, sodass ich cache-bare Inhalte von nicht-cache-baren Inhalten trenne. Und eventuell auch, indem ich Hauptinhalte und sekundäre Inhalte voneinander trenne und die dann versetzt ausliefere. Was dazu führt, dass im Endeffekt – da gibt es zwei Kriterien, die man messen kann, das ist die “Time to First Meaningful Paint”, das ist da, wo der Benutzer zum ersten Mal was sinnvolles lesen kann. Und die “Time to First Interaction”, das ist das andere Kriterium, das kann man messen, das ist da, wo der Benutzer zum ersten Mal etwas mit der Anwendung tun kann. Also klicken, oder so. Und die kann ich dadurch steigern, indem ich genau das mache, was ich gerade erzählt habe. Hauptinhalte und sekundäre Inhalte trennen, und cache-bare von nicht-cache-baren Inhalten trennen.

Lucas Dohmen: Okay. Du hast jetzt gesagt, ich habe ein Hauptdokument und das referenziert andere Dokumente. Irgendwie muss ich die jetzt zusammenbringen. Wo passiert das denn? Passiert das irgendwie in meiner Anwendung? Wie funktioniert das?

Franziska Dessart: Da gibt es verschiedene Möglichkeiten. Und zwar entlang so einer typischen Request-Response-Chain gibt es – ich kann es gleich nochmal aufzählen – ganz viele Orte, wo ich das tun kann. Je nachdem, welches Ziel ich mit dem Schnitt verfolge, werde ich halt den einen oder den anderen einsetzen. Die mir bekannten möglichen Transklusionsorte sind: Einmal im Client, im Browser kann ich Dinge nachladen. Ich kann das aber auch schon, gerade wenn ich aus architektonischen Gründen geschnitten habe, direkt in meinem Backend machen. Genauso wie ich an anderer Stelle vielleicht eine JSON-Schnittstelle zwischen zwei Services oder Applikationen aufrufen würde, kann ich genauso gut eine Ressource aufrufen, die mir HTML zurück liefert, und dann die Antwort bei mir in meine eigene Antwort einbetten.

Dann kann ich hergehen, und ich könnte zum Beispiel für die Transklusion auch ein eigenes System aufsetzen. Das mache ich zum Beispiel, wenn ich nicht will, dass der ursprünglich angesprochene Service für dieses Template zuständig ist – also dafür, welche Referenzen jetzt wo eingebettet werden sollen – sondern wenn ich da mehr Kontrolle drüber haben möchte. Dann würde ich das unter Umständen in einem anderen System aufsetzen. Zalando hat sich zum Beispiel eins selber gebaut, das nennt sich Tailor, das ist frei verfügbar, das kann man nehmen und bei sich selbst verwenden.

Darüberhinaus könnte ich meinen Webserver einsetzen. Da gibt es einen Standard, der dazugehört, das sind die Server Side Includes. Oder ich könnte einen Caching Proxy oder einen CDN-Knoten, also Content Delivery Network Knoten nehmen, und dort die Sprache ESI – Edge Side Includes – verwenden.

Lucas Dohmen: Okay. Und wie entscheidest du jetzt, an welcher Stelle du die Transklusion machen würdest? Liegt das am Usecase? Was tust du da?

Franziska Dessart: Das liegt daran, um welchen Inhalt es sich gerade handelt. Klassischerweise würde ich Dinge, die sich gut cachen lassen, natürlich da inkludieren, wo sie gecacht wurden, also auf dem Caching Proxy oder auf dem CDN. Oder vielleicht im Client, wenn es was User-spezifisches ist. Da würde ich es jetzt nicht auf dem CDN cachen, sondern direkt im Browser. Ressourcen, die ich nur aus architektonischen Gründen getrennt habe, würde ich jetzt vielleicht eher im Backend zusammenbringen wollen, oder dann auf dem Webserver, je nachdem. Wenn ich zum Beispiel nicht-technischen Usern die Kontrolle darüber geben will, was wo wann wie inkludiert und eingebunden wird, dann würde ich vielleicht so ein dediziertes System wie Tailor aufsetzen, um da eine graphische Oberfläche dran zu hängen. Oder das mit meinem CMS zu verknüpfen, und da Redakteuren die Möglichkeit geben, Inhalte beizusteuern, aber auch die Verknüpfung der Dokumente untereinander zu steuern.

Lucas Dohmen: Okay, also wenn ich jetzt beispielsweise eine Warenseite habe, wo Waren angezeigt werden als Hauptinhalt, und ich möchte immer einen Warenkorb anzeigen. Wo würdest du den jetzt transkludieren, den Warenkorb, wenn der von einem anderen System kommt?

Franziska Dessart: Also wenn ich davon ausgehe, dass die Warenseite zum Beispiel über so ein CMS oder Produktmanagement-System gepflegt wird, dann würde innerhalb dieses Dokuments – also das würde ich quasi dem nicht-technischen User überlassen, das zu editieren, und dem dann die Möglichkeit geben, da eine Referenz einzubauen, wo dann aus dem Backend, aus der Applikation der Warenkorb hinzugezogen wird.

Lucas Dohmen: Ah okay, gut. Wie ist es denn mit SEO-kritischen Inhalten, wo würdest du die transkludieren?

Franziska Dessart: Die kann ich im Prinzip überall transkludieren, wo ich möchte, außer im Client, denn ich kann mich immer noch nicht darauf verlassen, dass der Suchmaschinenbot JavaScript auswertet. Und der deswegen nicht in der Lage ist, zu erkennen, dass die Inhalte auf der Seite eigentlich drauf sind.

Lucas Dohmen: Also, theoretisch können das einige Suchmaschinen, aber man weiß es immer nicht so genau, ob das funktioniert.

Franziska Dessart: Also, Google kann es, theoretisch, man kann sich aber auch nicht darauf verlassen. Und die anderen Suchmaschinen können es halt nicht. Das heißt, ich sollte mich auf keinen Fall darauf verlassen.

Lucas Dohmen: Okay. Du hast gesagt, eine Möglichkeit ist jetzt, auf dem Client die Transklusion durchzuführen, wie muss ich mir das vorstellen? Was muss ich dafür tun?

Franziska Dessart: Da gibt es verschiedene Möglichkeiten. Ich könnte jetzt zum Beispiel iframes dafür einsetzen. iframes sind heutzutage eher unbeliebt, haben aber einen Vorteil, sie bieten auf jeden Fall die größte Kapselung. Das Problem mit den iframes ist halt, dass sie von außen gestylt werden müssen, und sich zum Beispiel deren Größe nicht nach dem Inhalt richtet, sondern nach dem, was von außen vorgegeben ist. Deswegen sind sie richtig schwer, in z.B. responsive Websites, einzubetten. Und aus dem Grund empfiehlt es sich vielleicht nicht unbedingt. Wenn ich aber den Sicherheitsaspekt habe, dann ist es vielleicht trotzdem das Mittel der Wahl. Genau, also iframes ist eine Variante, dann kann ich JavaScript Libraries einbinden, die im Netz verfügbar sind. Zum Beispiel gibt es eine, die nennt sich h-include von Gustaf Nilsson Kotte. Da lade ich mir die Library und verwende die. Oder ich könnte halt einfach auch selber was schreiben, weil es schnell gemacht ist. Es sind ein paar Zeilen JavaScript, und ich habe dann halt die volle Kontrolle darüber, was passiert.

Lucas Dohmen: Ein Beispiel davon hattest du auch auf Github irgendwo zu sehen. Das können wir vielleicht in den Shownotes verlinken, wie man das beispielsweise bauen kann.

Franziska Dessart: Genau, ein Kollege von mir, der Frederik, der hat damals einen Proof of Concept gebaut, wie das denn aussehen kann, wenn man sich bei der Transklusion auf ganz banale a hrefs stützen möchte. Das hat den Vorteil, dass, wenn zum Beispiel kein JavaScript verfügbar ist, dann habe ich den natürlichen Fallback zu dem Link. Und der Nutzer kann dann den Link an sich benutzen, um die Ressource selbst aufzurufen, falls bei der Transklusion irgendwas schiefgehen sollte oder, wie gesagt, kein JavaScript verfügbar ist.

Lucas Dohmen: Okay. Zur App und zum dedizierten Service hattest du schon einiges gesagt. Was ist mit diesem SSI, wie funktioniert das? Du hast gesagt, das ist eine Sprache, wie muss ich mir das vorstellen?

Franziska Dessart: Also es ist eine Sprache im Sinne von – es sind eigentlich HTML-Kommentare, die Kommandos enthalten. Das ist ein Standard, der mal spezifiziert wurde, und es geht im Prinzip um ein besonderes Kommando, das include Kommando. Das war eigentlich mal gedacht, um Dateien mit einzubetten, die sich auf dem Webserver befinden. Es kann aber verwendet werden, also leicht am Standard vorbei, um Pfade einzubinden. Virtual Resources, nennt sich das, glaube ich. Die können auf andere Services zeigen, wo dann Inhalte her geladen werden. Das heißt, der Webserver hat ein Template, das eben diese Tags enthält oder HTML-Kommentare mit dem include, und löst diese dann auf.

Lucas Dohmen: Wie unterscheidet sich das dann von den ESIs? Wie funktionieren die und was funktioniert da anders?

Franziska Dessart: Im Prinzip gibt es da zwei Unterschiede. Einmal halt, wo habe ich das Ding verfügbar. ESI wird implementiert von verschiedenen CDNs oder Caching Proxies. Und der andere Unterschied ist in der Mächtigkeit der Sprache oder des Tags, quasi. Also, welche Möglichkeiten habe ich dann innerhalb des Templates, Dinge zu beeinflussen. SSI ist halt sehr basic, sage ich jetzt mal. Das beschränkt sich hauptsächlich auf das include. Und bei ESI habe ich if/else-Konstrukte, ich kann mit Variablen arbeiten, ich kann sehr dediziert Fallbacks spezifizieren, über Exception-Blöcke, über Fallback-Ressourcen, …. Und ich habe für bestimmte Anwendungsfälle auch noch andere Tags. Zum Beispiel esi:inline wäre so ein anderer Tag, mit dem ich spezielle Use-Cases handeln kann.

Lucas Dohmen: Wie sieht das denn jetzt aus, wenn ich beispielsweise Assets wie CSS und JavaScript in den verschiedenen Systemen habe. Worauf muss ich da achten?

Franziska Dessart: Ich muss mich auf jeden Fall erstmal darüber unterhalten, wie ich das machen möchte, und eine Strategie entwickeln. Keine wird perfekt sein. Das heißt, ich muss halt meine Randbedingungen angucken. Im Prinzip gibt es zwei Sachen, die ich entscheiden muss: Möchte ich die per push oder möchte ich die per pull einbinden? Push bedeutet, ich bekomme eine Version der Assets quasi untergeschoben. Oder möchte ich explizit zum Beispiel eine bestimmte Version reinziehen. Die andere Entscheidung, die ich treffen muss, ist, möchte ich es zur Laufzeit oder zur Buildzeit einbinden. Und das hat zum Beispiel auch Auswirkungen darauf, wie gut kann ich etwas testen. Oder um Tests aufzuziehen, welche Rahmenbedingungen muss ich denn erfüllen. Zum Beispiel wenn ich es zur Laufzeit einbinden will, dann muss ich es zum Testzeitpunkt ja irgendwo herkriegen. Und da muss ich mir Gedanken drüber machen, und damit umgehen.

Lucas Dohmen: Kann ich dafür nicht auch einen Styleguide zum Beispiel verwenden?

Franziska Dessart: Ja, das ist zum Beispiel eine ganz gute Idee. Eine Variante, das zu handhaben, wäre zum Beispiel, ich setze eine zentrale Pattern Library oder einen Styleguide auf, und da drin pflege ich Komponenten, die dann für die Transklusion erlaubt sein sollen. Alle HTML-Fragmente, die ich irgendwo anders transkludieren möchte, können sich aus dem Styleguide bedienen. Und die dazugehörigen Assets wie Styles und JavaScript werden dann über den Styleguide von dem einbettenden System zur Verfügung gestellt. Weil das ist dann quasi die Schnittstellenabsprache, die ich treffe, zwischen den Systemen.

Lucas Dohmen: Okay. Wie geht man denn mit Fehlern um? Also wenn eine Ressource nicht antwortet, was kann man da tun?

Franziska Dessart: Ich sollte mir auf jeden Fall über den Fallback Gedanken machen. Da kann ich mir beliebig ausgefeilte Strategien ausdenken, je nachdem wo ich transkludiere gibt es da auch mehr oder weniger mächtige Mittel dazu. Aber allen Stellen gemeinsam ist eigentlich, dass ich als allerletzten Fallback, wenn alles andere nicht funktioniert hat, immer noch die Möglichkeit habe, einen ganz einfachen Link zu der Ressource ausliefern zu können. Und wenn dann sogar auf dem Client das JavaScript nicht funktioniert, dann hat der Nutzer immer noch den Link, wo er dann selbst noch mit der Maus draufklicken kann, und dann zu der Ressource – wenn sie schon nicht direkt angezeigt wird – dann zumindest hin navigieren kann.

Lucas Dohmen: Du hattest am Anfang gesagt, eine von den Sachen, die man damit erreichen kann, ist auch Performance durch Caching. Kannst du dazu noch ein paar Worte sagen, wie das funktioniert?

Franziska Dessart: Im Prinzip ist der eine Punkt: Ich trenne cache-bare von nicht-cache-baren Sachen. Contents, die sich nicht ändern, wie zum Beispiel irgendwelche Texte oder so, die vielleicht sogar noch redaktionell gepflegt werden, die sich nicht ändern, die kann ich gut cachen. Und wenn ich die nicht zusammen mit den dynamischen Ressourcen ausliefere, dann klappt es auch ganz gut. Damit es klappt, muss ich es aber eben voneinander trennen.

Ich kann auch Hauptinhalte von sekundären Inhalten trennen. Das heißt, wenn ich zum Beispiel die News-Seite habe, wo die zentrale Ressource der Seite, die ich gerade anzeige, der News-Artikel an sich ist. Dann ist das der Hauptinhalt, den ich zuerst laden möchte. Alles was außenrum noch auf dieser Seite platziert ist, das brauche ich ja erstmal nicht, wenn ich den Inhalt des Artikels lesen möchte.

Lucas Dohmen: Okay. Wie gehe ich denn damit um, wenn mein transkludiertes HTML wiederum was transkludiert. Funktioniert das, oder geht dann was kaputt?

Franziska Dessart: Also rekursives Nachladen von Fragmenten?

Lucas Dohmen: Ja, genau.

Franziska Dessart: Das ist eigentlich überall möglich, außer bei Tailor, die haben da eine Einschränkung drin. Ansonsten ist es entweder möglich, oder ich kann es irgendwie durch Konfiguration ermöglichen. Oder ich kann es halt einfach selber implementieren. Wenn ich jetzt im Backend meine Ressource aufgerufen habe, die mir das HTML liefert, und in dieser Antwort steckt halt wiederum eine Referenz, und ich möchte das zulassen, dass das rekursiv nachgeladen wird, dann implementiere ich meinen Service halt einfach so. Aufpassen muss ich dabei aber: Ich sollte es nicht übertreiben. Es ist grundsätzlich eine schöne Sache, aber ich sollte es nicht übertreiben, weil so rekursives Nachladen natürlich auch sequentiell ausgeführt wird, und dadurch dann wieder einen Impact auf die Performance hat.

Lucas Dohmen: Wie würde ich denn jetzt so ein System, das Transklusion einsetzt, testen?

Franziska Dessart: Grundsätzlich kann man sagen, überall wo eine Transklusion stattfindet, gibt es eine Schnittstelle. Da sollte ich auch grundsätzlich Tests dafür haben. Was ich beachten sollte, ist, nicht immer nur den Gutfall zu testen, sondern insbesondere auch ein Augenmerk zu legen auf das Funktionieren der Fallback-Szenarien. Wenn mein System gerade nicht verfügbar ist oder eine fehlerhafte Antwort liefert, was mache ich denn dann?

Lucas Dohmen: Ja dann, danke für all die Antworten auf die vielen Fragen! Wer sich das mal anschauen möchte in der Praxis, wir haben bei INNOQ auch ein Projekt gebaut, was Transklusion für SCS-Systeme zeigt, die auf der Client-Seite passieren. Es heißt Crimson Assurance. Das Projekt ist Open Source. Man kann sich das entweder einfach im Browser anschauen, wie es funktioniert, oder man kann sich auch den Code dafür anschauen. Das werden wir in den Shownotes verlinken. Genau, und dann danke ich dir!

Franziska Dessart: Ich danke dir!

Lucas Dohmen: Und den Hörern, bis zum nächsten Mal!