FireStart GmbH
Modernize your legacy web applications using Web Components
Description
Andreas Hässler von FireStart berichtet in seinem devjobs.at TechTalk über den Weg, wie das Team ihre legacy Applikation mithilfe von Web Components umgebaut hat – und sie sich dabei gleich mehrere Monate an Arbeit erspart haben.
Beim Videoaufruf stimmst Du der Datenübermittlung an YouTube und der Datenschutzerklärung zu.
Video Zusammenfassung
In Modernize your legacy web applications using Web Components zeigt Andreas Hässler, wie ein komplexer, jQuery-basierter Model-Renderer als Web Component gekapselt wurde, um ihn in einem neuen Angular-Portal ohne Code-Duplizierung weiterzuverwenden. Er beschreibt die verworfenen Optionen (Code kopieren, iFrame mit doppelter Ladezeit) und die Umsetzungsschritte: Bundling mit Webpack/ES6-Imports und TypeScript, Einbindung von Drittbibliotheken, Custom Element mit Shadow DOM und Datensetter sowie Veröffentlichung als NPM-Library für Alt- und Neusystem. Zuschauer lernen ein praxistaugliches Muster zur schrittweisen Modernisierung von Legacy-UIs—Web Components für Kapselung, Wiederverwendung und schnellere Auslieferung.
Legacy‑Webanwendungen modernisieren mit Web Components – Praxisleitfaden aus „Modernize your legacy web applications using Web Components“ von Andreas Hässler (FireStart GmbH)
Einleitung: Warum jetzt? Mobile Nutzung trifft auf monolithisches Erbe
Bei DevJobs.at verfolgen wir seit Jahren, wie Teams ihre gewachsenen Web‑Anwendungen Schritt für Schritt erneuern. In der Session „Modernize your legacy web applications using Web Components“ von Andreas Hässler (FireStart GmbH) sahen wir eine präzise, pragmatische Blaupause dafür: Statt ein zentrales, hochkomplexes UI‑Modul neu zu implementieren, hat FireStart den existierenden Renderer als Web Component gekapselt und so in eine moderne Angular‑App integriert.
Die Ausgangslage war klar umrissen: Kundinnen und Kunden modellieren Geschäftsprozesse im FireStart‑Windows‑Client; im Web‑basierten Process Portal können Modelle angezeigt und Aufgaben eingesehen werden. Die Nutzung verschiebt sich aber zunehmend Richtung Mobilgeräte – und die Legacy‑Webapp war dafür weder technisch noch architektonisch gerüstet. Gleichzeitig war der bestehende Renderer über Jahre gereift, reich an Edge Cases und Logik, die plattformübergreifend konsistent bleiben musste. Eine komplette Neuentwicklung? Nicht realistisch innerhalb weniger Wochen. Die Deadline rückte näher.
„Reimplementing this from scratch wasn’t really feasible … it would have taken us months and would still not cover any edge cases.“
Was folgte, war eine nüchterne Evaluierung der Optionen – und eine Entscheidung für Web Components als Standard‑API, um Framework‑agnostische UI‑Bausteine in eine Next‑Gen‑Anwendung zu heben.
Problemraum: Ein komplexer Renderer, harte Zeitvorgabe, paralleler Betrieb
Die zentrale Herausforderung lag im Modell‑Renderer: Viele unterschiedliche Prozessmodelle, zahlreiche Elemente, komplexe Render‑ und Modellierlogik – über Jahre verfestigt, getestet und mit subtilen Sonderfällen angereichert. Diese Logik musste konsistent bleiben – zwischen Windows‑Anwendung und Web‑Portal.
Parallel dazu gab es klare Randbedingungen:
- Steigende mobile Nutzung erforderte ein modernes, performantes Web‑Erlebnis.
- Der neue Angular‑basierte Prozess‑Portal‑Prototyp war funktional, aber der eigentliche Model‑View fehlte noch.
- Paralleler Betrieb sollte möglich sein: Die alte Anwendung musste vorerst weiterlaufen, während das neue Portal Form annimmt.
- Ein „Big Bang“ war ausgeschlossen; der Preview‑Release stand an.
Aus dieser Konstellation ergab sich eine zentrale Leitlinie: So viel wie möglich wiederverwenden, ohne die neue App in Altlasten zu verstricken – und ohne doppelten Pflegeaufwand.
Verworfen: Code kopieren oder iframe einbetten
Das Team diskutierte mehrere naheliegende Ansätze – und verwarf sie nach Tests und Abwägung.
1) Code kopieren
Die naheliegende Idee: alten Code direkt in die neue Anwendung übernehmen. Doch mit parallelem Betrieb wären Änderungen doppelt zu pflegen – in „Alt“ und „Neu“. Das erhöhte Risiko für Inkonsistenzen und verschlingt wertvolle Zeit in einer Phase, in der Geschwindigkeit zählt.
2) iframe mit dem alten Renderer
Eine zweite Option: die alte Renderer‑Ansicht per iframe einbetten. Ein vorhandener Query‑Parameter konnte die restliche alte UI ausblenden, sodass im iframe nur der Renderer sichtbar blieb. In Tests fiel jedoch die Ladezeit negativ auf. Grund: Komponenten wurden doppelt geladen – einmal durch die neue App, einmal im iframe.
„The load time was getting really high because the whole process elements needed to be loaded two times.“
Das Fazit: technisch machbar, aber zu schwergewichtig und nicht nutzerfreundlich.
Entscheidung: Web Components als saubere Integrationsschicht
Der endgültige Ansatz setzte auf Standard‑Web‑APIs: Web Components. Sie erlauben es, UI‑Bausteine framework‑unabhängig zu verpacken und in beliebige Anwendungen einzubinden – egal, ob jQuery, React oder Angular im Spiel ist. Hässler fasst den Kern zusammen: Den bestehenden Modell‑Renderer als Web Component kapseln, im Next‑Gen‑Portal verwenden und die Daten von außen setzen.
Ein wichtiger Verweis aus der Session: https://www.webcomponents.eu. Der Standard umfasst u. a. Custom Elements und Shadow DOM – genau die Mechanik, die für klare Kapselung von Markup, Logik und Styles benötigt wird.
Architekturskizze: Ein Legacy‑Renderer wird zur wiederverwendbaren Bibliothek
Damit die Kapselung gelingt, mussten mehrere Bausteine vorbereitet werden:
1) Bundling-fähige Codebasis schaffen. Der alte Renderer war nicht als wiederverwendbare Bibliothek organisiert. Script‑Dateien wurden direkt per „script“‑Tags in einer HTML geladen. Ziel war, explizite ES6‑Imports einzuführen, damit ein moderner Bundler daraus eine Library erzeugen kann.
2) Drittanbieter‑Abhängigkeiten sicher einbinden. Der Renderer nutzte Bibliotheken wie jQuery und ConvertJS. Mit Webpack plus diversen jQuery‑Plugins sind die Integrationsdetails knifflig – Trial‑and‑Error inklusive.
3) Web Component definieren. Ein Custom Element erstellt die Shadow‑Root und initialisiert darin den Legacy‑Renderer. Daten fließen über einen Setter aus der neuen App in die Komponente. Die Registrierung des Elements macht es anschließend überall konsumierbar.
4) Styling kapseln. Shadow DOM sorgt dafür, dass Styles der neuen Anwendung nicht in die Komponente „hineinbluten“. Im Debugging zeigte Hässler den Unterschied zwischen „open“ (sichtbar in DevTools) und „closed“ (verhält sich wie ein nativer Browser‑Baustein).
Das Ergebnis: eine interne NPM‑Bibliothek mit Web Component, die sowohl in der neuen Angular‑Anwendung als auch weiterhin im alten Portal nutzbar ist – ein „Single Source of Truth“ für Render‑Verhalten und Edge‑Case‑Handling.
Schritt 1: Bundling – vom Script‑Zoo zu expliziten ES6‑Imports
Hässler schildert, dass das alte Build‑Setup kein wiederverwendbares Paket erzeugen konnte. Der Umbau auf Webpack war deshalb der erste substanzielle Schritt. Dabei passierte zweierlei:
- Script‑Tags in der HTML wichen ES6‑Imports in Modulen. Abhängigkeiten zwischen Dateien wurden explizit, statt implizit über Lade‑Reihenfolgen zu wirken.
- TypeScript‑Support kam hinzu. Der Renderer bleibt zwar Legacy‑Code, aber künftig sind Refactorings sicherer.
„We had to switch to something more modern like Webpack and actually add all the different import statements … so we could then bundle it inside a library.“
Dieser Umbau mag wie eine Formalie wirken, ist aber entscheidend: Erst dadurch wird der Renderer bundelbar, versionierbar und in Projekten sauber konsumierbar.
Schritt 2: Drittanbieter‑Bibliotheken – jQuery und ConvertJS unter Webpack
Die zweite Hürde: Integrationen rund um jQuery und ConvertJS. Wer jQuery‑Plugins mit Webpack verheiratet, kennt die Fallstricke. Laut Hässler brauchte es viel Ausprobieren, verschiedene Webpack‑Konfigurationen und Sorgfalt, um alle Plugins korrekt zu laden.
„For those of you who have tried to use jQuery together with Webpack, you will know that it’s kind of a pain.“
Wichtig ist hier die Erwartungshaltung: Der Weg ist machbar, aber nicht „plug and play“. Wer den Aufwand einplant, gewinnt am Ende eine sauber verpackte Bibliothek, die in unterschiedlichen Umgebungen zuverlässig lädt.
Schritt 3: Die Web Component – Custom Element und Shadow DOM
Nachdem Bundling und Dependencies standen, wurde der Renderer als Custom Element gekapselt. Die Eckpunkte, wie sie Hässler beschreibt:
- Ein Custom‑Element‑Konstruktor erstellt eine Shadow‑Root.
- Der Legacy‑Renderer wird innerhalb dieser Shadow‑Root initialisiert.
- Ein Setter dient als Eingang für die Inhalte/Modelldaten, die die neue Anwendung liefert.
- Die Definition des Elements macht es im Browser verfügbar und in jeder App konsumierbar.
Shadow DOM ist dabei der Schlüssel zur Robustheit. Styles der neuen App beeinflussen den Legacy‑Renderer nicht, und umgekehrt. Für Debugging nutzte Hässler den „open“‑Modus – sichtbar in den DevTools. Mit „closed“ wäre die Komponente wie ein nativer Browser‑Baustein nicht einsehbar.
„Shadow DOM encapsulates this, so your styling from the outside application cannot leak into the Web Component.“
Ergebnis: Schneller Wert, einheitliches Verhalten, weniger Risiko
Der Ansatz zahlte sich schnell aus:
- Der Renderer wurde als interne NPM‑Bibliothek gebündelt, inkl. jQuery und aller nötigen Plugins.
- Die Web Component kapselt Logik und Styles, ist in der neuen Angular‑App sofort nutzbar und lässt sich weiterhin in der alten Anwendung einsetzen.
- Die Entwicklungszeit schrumpfte von „Monate“ (für eine Neuimplementierung) auf „ein paar Wochen“ bis zum Proof‑of‑Concept und produktionsreifen Einsatz.
- Der „Single Source of Truth“ sichert konsistentes Render‑Verhalten zwischen Alt und Neu – wichtige Edge Cases inklusive.
„It took us just a couple of weeks to get started instead of the months that it would have taken to rebuild this from scratch.“
Die positive Erfahrung wiederholte FireStart beim Dashboards‑Modul: ebenfalls als Web Component extrahiert, erneut Zeit gespart – und die Next‑Gen‑App wurde rechtzeitig ausgeliefert.
Warum Web Components hier „genau richtig“ waren
Aus unserer Beobachtung passt der Ansatz ideal zum Problem:
- Der kritische Teil (Renderer) ist stabil, funktionsreich und reich an Sonderfällen – perfekt zum Kapseln statt Neuschreiben.
- Die Zielplattform (Angular‑App) kann Web Components nativ konsumieren, ohne Technologiespagat.
- Paralleler Betrieb erfordert eine gemeinsam genutzte Implementierung – die NPM‑Bibliothek liefert genau das.
- Die Risiken des iframes (Doppelladen, Performance, UX‑Brüche) werden vermieden; das Custom Element fügt sich nahtlos ein.
Praktische Leitlinien für Teams mit ähnlicher Ausgangslage
Die Session liefert konkrete Anhaltspunkte, wie sich ein ähnlicher Weg planen lässt.
1) Kandidaten identifizieren
- Welche Legacy‑Module sind wertstabil (funktionieren gut, besitzen viele Edge Cases) und zugleich schwer neu zu bauen?
- Wo ist Konsistenz zwischen Alt und Neu geschäftskritisch (z. B. Rendering, Modellierung, Berechtigungen)?
2) API‑Oberfläche definieren
- Welche Daten braucht die Komponente von außen? Ein klarer Setter oder eine schmale öffentliche API vermeidet Kopplung.
- Welche Events müssen nach außen signalisieren, was im Inneren passiert?
3) Build‑Fundament legen
- Schritt von Script‑Tags zu ES6‑Imports vollziehen; Dateigrenzen und Abhängigkeiten explizit machen.
- Einen modernen Bundler (wie Webpack) konfigurieren, der eine Library‑Ausgabe ermöglicht.
- Optional TypeScript einführen, um Refactorings am Legacy‑Code zu entschärfen.
4) Drittanbieter‑Libs zähmen
- Mit jQuery‑Plugins unter Webpack rechnen: Kontext, Reihenfolgen, globale Objekte prüfen.
- Integrationsprobleme früh adressieren; einen kleinen Showcase bauen, der nur das Laden testet.
5) Shadow DOM bewusst wählen
- „open“ erleichtert Debugging in der Übergangsphase.
- „closed“ schützt vor unerwünschten Eingriffen, wenn die Komponente stabil ist.
6) Performance im Blick behalten
- iframes vermeiden, wenn doppelte Ladevorgänge drohen.
- Das Bundle der Komponente schlank halten und nur notwendige Abhängigkeiten einpacken.
7) Parallelbetrieb planen
- Die Bibliothek sowohl in der alten als auch in der neuen App konsumieren, um eine einheitliche Semantik zu sichern.
- Versionen sorgfältig taggen; ein stabiler Release‑Zyklus verhindert Divergenz.
Was wir besonders bemerkenswert fanden
- Die Klarheit, mit der das Team Optionen geprüft und verworfen hat: Copy‑Paste (Pflegeaufwand) und iframe (Ladezeit) scheiterten an praktischen Kriterien.
- Die Sorgfalt beim Build‑Umbau: erst explizite Imports, dann Bundling, dann Komponentenkapselung – in genau dieser Reihenfolge ergibt es Sinn.
- Die nüchterne Erwartungssteuerung bei jQuery/ConvertJS: „painful“, aber lösbar.
- Die Entscheidung, die Web Component auch im Legacy‑System einzusetzen – dadurch entsteht echte „Single Source of Truth“.
Demos und Einblicke: Shadow DOM und offene/geschlossene Komponenten
In der Session veranschaulichte Hässler die Wirkung der Kapselung über Shadow DOM. Besonders einleuchtend: Der Unterschied zwischen „open“ und „closed“. Im „open“‑Modus ist die Shadow‑Root in DevTools sichtbar, was das Debugging erleichtert. Im „closed“‑Modus verhält sich die Komponente wie ein nativer Browser‑Baustein – robust, aber in der Tiefe nicht einsehbar. Für Teams im Übergang ist „open“ oft die pragmatischere Wahl.
Übertragbarkeit: Wann lohnt sich dieser Ansatz?
Aus Sicht der Session ist der Ansatz überall dort attraktiv, wo:
- ein bewährtes, jedoch schwer neu zu bauendes UI‑Modul existiert,
- eine moderne Hülle (z. B. Angular‑App) entstehen soll,
- paralleler Betrieb mit der Legacy‑App gefordert ist,
- und die Nutzerinnen und Nutzer schnell ein verbessertes Erlebnis brauchen (z. B. auf Mobilgeräten).
Ein zusätzlicher Pluspunkt: Die Framework‑Neutralität. Die Web Component bleibt auch dann nutzbar, wenn die Hülle künftig wechselt (etwa zu React oder zu einer anderen Architektur) – ohne erneute Portierung.
Fazit: Ein sauberer, standardkonformer Migrationspfad
„Modernize your legacy web applications using Web Components“ von Andreas Hässler (FireStart GmbH) zeigt eine klare Lehre: Wer eine zentrale, komplexe UI‑Komponente in eine moderne App heben will, ohne ihre gewachsene Semantik zu verlieren, ist mit Web Components gut beraten. Der Weg führt über Bundling‑Reife, disziplinierte Dependency‑Integration und eine schlanke API nach außen. Das Ergebnis sind schnellere Releases, weniger Risiko und eine langlebige, wiederverwendbare Bibliothek – exakt das, was FireStart gebraucht hat, um den Next‑Gen‑Release rechtzeitig zu liefern und zugleich die alte Welt konsistent weiter zu bedienen.
Oder, in Hässlers Worten: Der Web‑Component‑Ansatz „saved us a lot of time“. Das bestätigen die Resultate – bis hin zur Wiederverwendung beim Dashboards‑Modul. Für Teams mit ähnlicher Aufgabenstellung ist diese Session eine hervorragend nachvollziehbare Vorlage.