Von Angular zu React mit KI: Ein Erfahrungsbericht
Kann man mit KI ein mittelgrosses Angularprojekt automatisch auf React umschreiben lassen? Nico hat's versucht und berichtet live aus dem Labor.
Ausgangslage
Vor einigen Monaten kriegten wir den Auftrag, ein älteres Meteorprojekt so gut wie möglich zu aktualisieren. Leider stellte sich heraus, dass das Meteor Ökosystem Angular nicht mehr unterstützt. Aufgrund der Angular-Dependency konnten die meisten wichtigen Libraries, inkl. MongoDB und Node.js selber nicht mehr aktualisieren werden.
Unser Rat: Schreibt das Frontend auf React um. Bei rund 80 Komponenten und 20'000 Zeilen Code zwar eine Challenge, aber machbar. Doch der Aufwand für ein händisches Refactoring lag nicht im Budget.
Doch da kam ich auf eine Idee: Eigentlich ein perfekter Case für ein Experiment! Kann man mit KI ein Angularprojekt effizient auf React umschreiben? – Wir schlugen also vor, das zu probieren, mit Kostendach und Risiko im Falle des Scheiterns bei uns. Fünf Tage – die Wette gilt!
Fragestellung
Wie die meisten Entwicklungsfirmen benutzen wir jeden Tag KI-Tools wie Cursor oder Copilot. Diese Assistenten helfen einem beim Coden ad hoc, in einem eingeschränkten Rahmen, direkt im Editor.
Für ein grösseres Auto-Refactoring ist ein anderer Ansatz nötig: ein Scripting-Ansatz. Die Frage: Sind heutige Coding-LLMs für das brauchbar? Kann man KI Tools so konfigurieren, dass man die machen lassen kann, dazu gemütlich vor dem Bildschirm zurücklehnen, ein Müesli essen und ab und zu ein paar Anweisungen geben?
Setup
Für das Refactoring entschied ich mich für Aider, ein Terminalbasiertes AI-Coding-Tool; ausserdem probierte ich OpenRouter aus, eine Art Proxy-API für verschiedene LLMs. Als LLM nahm ich claude-3-5-sonnet-20241022, im Aider LLM Leaderboard damals auf Platz 1. Als Editor benutzte ich VSCode. Daneben legte ich eine Notion-Seite für notizen an, die sich schnell füllen sollte.
Pronti, partenza, via!
Test Suite
Als erstes versuchte ich mit Aider Tests zu generieren: Kann ich, ohne selber den Code lesen zu müssen, funktionale und umfangreiche (Playwright) End-to-End Tests generieren lassen?
Nun müssen wir in die Funktionsweise von Aider eintauchen: Aider ist eine REPL, also ein interaktives Command Line Tool. Es hört auf verschiedene Befehle, z.B. /add
, um die Files der Code-Base als Kontext mitgeben. Ich gab Aider das File mit allen Routen der Webseite an und gab ihm dann den Befehl:
/code create a test for /websites
Aider suchte sich die relevanten Files, las den Code und generierte einen Testentwurf – und die ersten Probleme: die Dependency-Detection funktionierte gut mit Imports, aber nicht mit Angular Template Tags. Ich musste ziemlich viel ausprobieren mit Instruktionen, bis es einigermassen funktionierte – und da wo es nicht funktionierte, musste ich halt die relevanten Files für den spezifischen Test händisch (mit /add
) dem Kontext mitgeben.
Nach etwas Pröbeln, war der erste End-to-End Test generiert. Automatisch und fehlerfrei war der Prozess jedoch nicht. Mit dem Playwright-Testgenerator, mit dem man sich einfach durch das Interface klicken kann, wäre ich schneller gewesen (auch wenn das Tool seine Tücken hat).
Refactoring
Auch hier nahm ich das TypeScript-File als Basis, mit allen Routen der Webseite, die dadurch als Verzeichnis der Komponenten diente. Ich versuchte Aider Route um Route auf React umschreiben zu lassen. Zur Orientierung für Aider schrieb ich einen CONTEXT.md
File, mit einer Beschreibung des Unterfangens und des Ansatzes.
Mit jedem Learning passte ich das Dokument an. Aber hey... eigentlich könnte doch auch die AI ihre Anweisungen schreiben. Ich fing also an, Aider selbst mit jeder Anpassung das Dokument aktualisieren zu lassen.
you created files while we were in dependencies mode. undo and update CONTEXT.md so it doesn't happen again
Relativ schnell wurde klar, dass das Management der Files im Kontext sehr wichtig war: bei zu vielen oder zu grossen Files nahm die Qualität rapide ab.
Und noch ein Tipp: Bei so einem Refactoring lohnt es sich, die neuen Komponenten in neuen Files neben den alten zu generieren, anstatt die alten direkt zu überschreiben oder zu löschen, damit Quervergleiche bis zum Schluss noch möglich sind.
Nach einer Weile Herumschrauben konnte ich anfangen, oberflächlich einigermassen stimmige Komponenten zu generieren – allerdings:
- Bei längeren Files war die Code-Generierung langsamer und langsamer;
- oft wurden Teillösungen generiert, und/oder
- Abhängigkeiten wurden nicht importiert.
Aber mit wenigen Fixes oder Retries war ich meist bei einem kompilierbaren Stand, der bei Betrachtung im Browser oberflächlich visuell stimmte.
Ganz so automatisch, wie ich es mir vorgestellt hatte, war das nicht, aber ich kam endlich in eine Art Flow und konnte Komponenten relativ schnell generieren und fixen. Irgendwann fing ich an, parallel 3 Aider-Instanzen in separaten Terminals zu bedienen und Komponenten umschreiben zu lassen, und innerhalb von wenigen Stunden war die ganze Webseite "fertig".
Ich wusste, dass nun die Stunde der Wahrheit näher kam. Es gab drei Möglichkeiten
- Der generierte Code braucht ein genaues Review und einige Fixes und ist dann good to go
- Ich finde während des Reviews systematische oder tiefer gehende Fehler, die sich aber problemlos durch bessere Aider Instructions und eine neue Generation des Codes lösen lassen
- Worst Case Scenario: Ich komme an den Punkt an dem es sich lohnen würde, alles selber umzuschreiben.
Review & Fixing
Das Review gestaltete sich aus verschiedenen Gründen ziemlich anstrengend:
- AI-generierter Code-Review ist ungewohnt. Die KI ist mächtig, macht aber gleichzeitig Fehler, die ein Mensch nie machen würde. So hat die KI z.B. einen Placeholder grundlos mit einem anderen ersetzt. Oder sie hat eine Komponente, die nicht im Kontext war, bei jedem Gebrauch neu implementiert – insgesamt ein Dutzend Mal.
- Überarbeiten lassen von generiertem Code machte das Resultat graduell schlechter. Zielführender war es, die Komponenten mit einem besseren Prompt komplett neu generieren zu lassen. Dadurch konnten jedoch sinvolle Ansätze verlorengehen.
- Fehler konnten überall sein: Im alten Code, im generierten Code, in den neu generierten Fixes, in den eigenen Fixes, und in der Testing-Pipeline. Das machte das Managen und Quervergleichen der verschiedenen Versionen herausfordernd bis mühselig.
- Komplexere technischen Challenges musste ich am Schluss doch selber lösen, insbesondere Paradigmenunterschiede wie Two-Way-Binding (Angular) vs Unidirectional Data Flow (React) oder Formvalidierung.
- Jede separate Ausführung der KI (dadurch jedes generierte File) hatte einen subtil anderen Coding-Style, subtil andere Annahmen, Ansätze und Fehler. Learnings aus dem Review eines Files liessen sich nicht immer auf das nächste übertragen.
Kurz gesagt: Der Review-und-Fix-Prozess wurde extrem frustrierend. Mit Mühe und Not konnte ich einige wenige Komponenten auf einen befriedigenden Stand bringen, aber ich hatte mehr und mehr das Gefühl, dass ich mir selbst ein Minenfeld gebaut hatte. Mir wurde klar: Ich konnte die Qualität des Endresultats mit vertretbarem Aufwand nicht garantieren. Das Experiment war gescheitert.
Fazit
Als Assistent bleibt KI nach wie vor hilfreich – als scripting-Tool für umfangreiche Rewrites ist sie nicht bereit (jedenfalls Aider, stand Dezember 2024).
Welche anderen Ansätze könnte man fahren? Ich sehe folgende Möglichkeiten:
- KI ist wirklich, wirklich billig: Das ganze Experiment kostete knapp 60$. Es stellt sich die Frage: Was könnte man erreichen, wenn man viel mehr in KI-Power investieren würde? Könnte man vielleicht mit einem clever eingesetzten Schwarm, einer Pipeline von KI-Agenten, die Code-Qualität besser, systematischer gewährleisten?
- Ein anderer Weg, der sich lohnen könnte, ist auf einem anderen Abstraktionslevel zu agieren: anstatt Code mit KI direkt umzuschreiben, könnte man, unterstützt von KI, Codemods schreiben, die den Code auf AST-Level umschreiben (mit Libraries wie ts-morph, babel, jscodeshift, und angular-compiler). Der Vorteil: Wenn ein Refactoring-Tool mal geschrieben ist, funktioniert es, und zwar immer 100% gleich. Das Problem ist, dass KIs nicht auf dem Abstraktionslevel trainiert sind, und drum bedingt helfen können (wir sind wieder im etablierten Assistent-Modus).
- Last but not least: abwarten. Das KI-Feld entwickelt sich so rasant, dass man wahrscheinlich vor Ende 2025 eine ganze Webseite auf einmal umschreiben können wird. Z.B. führte Cursor schon während meines Experiments einen Agent-Mode ein, womit meines Erachtens Aider schon zur Obszoleszenz verdammt ist.
Noch nicht genug? Hier findest du noch mehr Beiträge (und sogar einen ganzen Newsletter!) zu KI.
Geschrieben von
Nicola Marcacci Rossi