<divclass="mod_group mod_timetable_input_form_buttonwrapper" data-timetableInputForm='button_wrapper'><buttontype="submit" class="text__primarybutton button"><svgfocusable="false" class="mod_svgsprite_icon var_cta_arrow"><usexlink:href="#SBB_08_arrow_down"/>
</svg>
Verbindung suchen
<svgfocusable="false" class="mod_svgsprite_icon var_cta_arrow"><usexlink:href="#SBB_08_arrow_down"/>
</svg></button></div><!-- dazu kommen Referenzen zu CSS Files sowie SVG Sprites -->
Notes
Anschaungsbeispiel eines kleinen / einfachen Moduls heute auf SBB.ch.
Ich gehe davon aus, dass alle bereits ein wenig HTML gesehen haben?
Dieses Markup beschreibt wie ein Button auf SBB.ch aussieht. In diesem konkreten Fall beschreibt es den Button für das Absenden der Fahrplanabfrage (siehe nachfolgend).
Dazu kämen ebenfalls Referenzen zu CSS Files (die für die Darstellung zuständig sind) sowie SVG Sprites (die die Icons beinhalten) ...
je nach Modul auch JavaScript Abhängigkeiten (und in diesem Fall weitere Abhängigkeiten zu jQuery)
All dies muss berücksichtigt werden, wenn heutzutage Markup vom Backend eingepflegt / aktualisiert wird.
Für die damalige Zeit war dies der modularste Ansatz, heute gibt es jedoch andere Lösungen.
Webkomponenten sind eine Gruppe von Web-Technologien, die es ermöglichen, benutzerdefinierte, wiederverwendbare HTML Elemente zu erstellen, deren Funktionalität gekapselt ist und damit vollständig getrennt von anderem Code.
DRY (Do Not Repeat Yourself) ist eine goldene Regel der Softwareentwicklung. Code sollte möglichst wiederverwendet werden. Für HTML / CSS / JS ist dies (bisher) nicht so einfach. Eben vorhin haben wir gesehen, was alles nötig ist, um ein Custom UI-Element zu erstellen (Beispiel CTA Button).
Des Weiteren sollten Implementationsdetails einer API für die Nutzer der API nicht ersichtlich sein. Z.B. wollen wir beim Nutzen einer Rest API keine DB spezifischen Konfigurationen vornehmen. Dasselbe sollte für unser Frontend gelten. Heute muss man zum Beispiel im Button ein SVG mitgeben.
Kommt die Button Komponente an mehreren Orten zum Einsatz, muss diese dementsprechend an mehreren Orten gepflegt und gewartet werden. Passen wir unsere Implementation an, z.B. ein Wechsel von SVG auf Canvas, müssen alle Bezüger des Buttons ihren Code anpassen (AEM, Fahrplan, Webshop, …). Breaking Changes kommen oft vor. Oder es wird von möglichen Verbesserungen abgesehen, da diese für die Bezüger einen erheblichen mehraufand bedeuten.
Weiter besteht die Möglichkeit, dass das Styling (CSS) unserer Komponenten von den beziehenden Seiten überschrieben wird.
Web Components bieten für diese Probleme eine einheitliche und standardisierte Lösung.
Wie wird dies gelöst?
Mittels drei Haupttechnologien die gemeinsam (oder einzeln) verwendet werden können.
Custom Elements (Benutzerdefinierte Elemente): Sind JavaScript APIs, die es ermöglichen, benutzerdefinierte Elemente sowie deren Verhalten zu definieren.
Shadow DOM: Sind ebenfalls JavaScript APIs, um einen Baum aus darin gekapselten Shadow-DOM-Elementen an ein Element anzufügen, der unabhängig vom DOM des Hauptdokuments gerendert wird, sowie um die dazugehörige Funktionalität zu steuern. Mit Hilfe dieser Technologie verbleiben die Ausprägungen solcher Elemente privat, sodass Skripte und Styles auf sie angewendet werden können, ohne dass sie mit anderen Teilen des Dokuments kollidieren.
HTML-Templates / Slots: Die - und -Elemente gestatten es, Markup-Vorlagen zu schreiben, die nicht auf der dargestellten Seite abgebildet werden. Diese können dann als Grundlage für benutzerdefinierte Elemente mehrere Male wiederverwendet werden.
Ich möchte dies noch einmal anhand eines Beispiels kurz erläutern. Keine Bange, dies ist das letzte Code Snippet, welches ich hier heute zeige.
Was sehen wir nun hier?
zum Einen ein neues Tag <sbb-cta> welches im HTML Standard so natürlich nicht existiert, aber wir mittels einem Custom Element definieren können
zum Anderen sehen wir die Quelle (JavaScript File), die das Aussehen und die Funktionalität / das Verhalten des Elements definiert
Mit den folgenden zwei Zeilen Code ist man also in der Lage einen benutzerdefinierten Call to Action Button, mit einem einheitlichen Design und Verhalten projektübergreifend / unternehmensweit zu nutzen
Dabei kommt dazu, dass das Styling nicht von aussen beeinflusst wird und in sich geschlossen ist (Komponenten Architektur).
<divclass="mod_group mod_timetable_input_form_buttonwrapper" data-timetableInputForm='button_wrapper'><buttontype="submit" class="text__primarybutton button"><svgfocusable="false" class="mod_svgsprite_icon var_cta_arrow"><usexlink:href="#SBB_08_arrow_down"/>
</svg>
Verbindung suchen
<svgfocusable="false" class="mod_svgsprite_icon var_cta_arrow"><usexlink:href="#SBB_08_arrow_down"/>
</svg></button></div><!-- dazu kommen Referenzen zu CSS Files sowie SVG Sprites -->
Abhängigkeit zu Stencil als Abstraktion (Web Component Library).
Potential für falsche Anwendung besteht nach wie vor (Web Component Library).
Potential für Performance Impact
Wenn Web Component Library nicht korrekt bezogen wird (z.B. selber hosten mit http1.1 und keinen Caching Headers)
Potentiell höhere Caching Komplexität in PWA (JSON-Antworten)
Klassische Web Crawler könnten Probleme bei der Indexierung haben
Notes
Single point of failure
der Vorteil der Zentralisierung bringt auch Risiken mit sich. Das heisst, es muss gewährleistet werden, dass die Komponenten stets gemonitored / getracked (Error Tracking) werden.
JavaScript notwenig wenn Web Components nicht auf dem Server gerendert werden. Auch dies ist bei den meisten unserer Komponenten schon jetzt der Fall.
Umgesetzt mit Stencil (Components sowie App) und Redux
Explizit umgesetzt für die Verwendung in Chromium, andere Browser wurden nicht berücksichtigt
Explizit entwickelt für zwei Viewports
Accessibility (a11y) wurde explizit vernachlässigt
Wegen der von Anfang an gesetzten Einschränkungen können die erstellten Webcomponents nicht ohne Weiteres in anderen Kanälen (z.B. Webshop) eingesetzt werden
Für die Ansprüche des Billetautomaten ist die App aus Sicht Frontend quasi produktionsreif
Vereinfachtes Setup
Komponenten und App wurden im selben Projekt erstellt
Kein Preview der Komponenten
Komponenten wurden nicht auf npm o.ä. veröffentlicht
Präsentation am Digitaltag / anderen internen SBB Veranstaltungen mit viel positivem Feedback / hohe Resonanz
Portierung / Migrierung der Stencil Web Components (PoC Web Components) auf Stencil One (Major Release)
Kontinuierliche Updates des Stencil Web Components PoCs
PoC Pre Rendering von Web Components mit Stencil (prerender output target)
Testing Magento REST API
Testing Magento GraphQL (ab Anfang Sept. möglich)
Aufbau GraphQL Knowhow
PoC Nuxt – Rendering Web Components in Nuxt (CSR)
Aufbau Nuxt / Vue Knowhow
PoC Nuxt / Apollo Client – GraphQL Magento Anbindung mittels Apollo Client
Kontinuierlicher Austausch mit Stencil Core Team / (Web Component) Community (SSR)
PoC Nuxt – Rendering Web Components in Nuxt (SSR)
Aufgrund der harzigen / ungewissen SSR Implementation von Web Components verlagerte sich der Fokus auf den zweiten Teil der Web Component Library. Auf den Zeitpunkt vor der Erstellung (sowie des Betriebs der Komponenten Library)
Component Browser Integration (Storybook)
Analyse Design System Space
Design System API / Design Tokens / Dokumentation des DS / Feedback Loops / Austausch UX / PO / Component Testing
...
Bei all dem war stets die Developer Experience (DX), die Zusammenarbeit, die Wartbarkeit, Skalierung, Performance und Machbarkeit im Fokus
Flexibles, modulares System welches sich anpassen lässt / Teile ausgetauscht werden können (kein Tool / Vendor Lock-In)
Was beinhaltet denn nun ein Design System?
Bei dieser Frage gehen die Meinungen bereits auseinander und es ist nicht klar definiert, was alles zu einem Design System gehört und was nicht. Aber man sollte wohl die folgenden Punkte miteinbeziehen.
Was klar ist, ist das Web Components die ideale Basis eines Design Systems sind / sich in ein Design System einfügen — dies sehen nicht ganz unwesentliche Unternehmen (IBM, Ionic, Google, ...) ebenso und haben ein Bestreben dies zu ändern falls dem nicht bereits so wäre.