Backend-Genese: Von PHP zu Node.js & TypeScript (Teil 1)
Tags: webdev, javascript, php, typescript
Published: 2024-05-08 06:26:13

Als langjähriger PHP-Entwickler, der sich auf Backend-Systeme mit [Symfony (Framework)](https://symfony.com/) spezialisiert hat (oder eher wie die Jungfrau zum Kinde kam), bietet der Wechsel zu einer TypeScript- und Node.js-basierten Umgebung sowohl spannende Möglichkeiten als auch herausfordernde Hürden aber auch jede Menge positive Erfahrungen.
In dieser Serie möchte ich meine Erfahrungen teilen, die ich beim Übergang von PHP zu TypeScript und Node.js gemacht habe, insbesondere im Hinblick auf die Arbeit mit Fastify, tap und TypeORM. Ziel ist es, anderen (PHP-)Entwicklern einen kleinen Einblick in einige der Kernunterschiede und Anpassungen zu geben, die notwendig sind, um in dieser neuen Umgebung effektiv zu arbeiten.
Ich gehe auf einige Aspekte ein, die sicherlich nicht die komplette Experience widerspiegeln, aber in meinen Doing die größten Unterschiede darstellen.

## What we did so far

![Experience with TypeScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at7vhtzxw74h6mlp256i.gif)

Um mich noch einmal etwas detaillierter einzuordnen und die Genese in einen Kontext zu setzen:
Ich habe bereits JS/TS-Erfahrung. Allerdings "nur" aus dem Frontend. Angefangen habe ich wie jeder pubertierende Web-Entwickler (oder sagen wir eher Frontpage-Artist™) in den 1990er-Jahren mit dem Versuch, etwas Dynamik auf statische HTML-Seiten zu erstellen. Der oft scheiternde Versuch, gegen die Mühlen jeder Microsoft Internet Explorer Version zu kämpfen, mündete zuerst in völlig überladenen Macromedia Fireworks Extrakten. Später kam dann jQuery respektive [Prototype](https://de.wikipedia.org/wiki/Prototype_(Klassenbibliothek)) dazu, die auch irgendwie den Weg in Richtung Web 2.0 ebneten. Natürlich gemeinsam mit Ruby on rails im Backend.
Auch an mir ging der Kelch nicht vorbei, Webseiten mit unnötig komplexen, asynchronen [XHR](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest?retiredLocale=de) zu gestalten. Weil es doch irgendwie cool war, server-generated content dynamisch nachzuladen. Egal wann, wo und wie.
Rund um 2017 oder 2018 beschäftigte ich mich erstmalig mit Angular(JS). Das Konzept war ein eye-opener. Gerade das Two-Way Data Binding hat unheimlich viel erleichtert. So war es ein Einfaches Datenänderungen im Modell in der Benutzeroberfläche (View) zu ermöglichen.
Auch die systematische Art, Abhängigkeiten zwischen Components zu verwalten hilft enorm, Modularität und Testbarkeit zu ermöglichen.
Nach ein paar Ausflügen in Richtung [React](https://react.dev/) habe ich vue.js zu meinem präferierten Framework für SPA gemacht. 

In der Zeit in der ich diesen Beitrag verfasse, sind wahrscheinlich weitere 5 Frameworks gelauncht, die sicher in Teilen überlegen und moderner scheinen und es ggf. auch sind - aber am Ende ist mir wichtig, die Grundkonzepte verstanden zu haben. Die Anwendung ist dann am Ende wie der Wechsel vom Traktor auf einen Bagger in ein Auto oder Formel 1 Wagen. Im Prinzip das Gleiche, im Detail unterschieden.

![I can handle it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgf1d6ovxad9mlii9m97.gif)

Wie man sich denken kann ist die Arbeit im Frontend aber relativ wenig vergleichbar mit einer Backend-Applikation auf TypeScript-Basis. Zumindest in dem Scope, den ich bisher nutzte. Mehr als ein paar Service-Klassen hinsichtlich abstrahiertem HTTP-Client oder kleinen Algorithmen sowie Frontend-Tests in jest, habe ich die Intensität und Tiefe des Supersets von Javascript noch nicht genutzt. 
Na dann...

## ...ab ins Backend 

![Backend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vejqgkdxiabkbea15qn8.gif)

### Comparison
PHP und node.js sind beides Engines, die in der Regel als Backend von dynamischen Webapplikationen eingesetzt werden können. Der Hauptunterschied liegt vorweg schon darin, dass der PHP-Interpret Scripts blocking ausführt. Node.js ist eher als Runtime zu verstehen, die dauerhaft läuft. 
Der Clue der Macher von node.js war, die [V8-Engine](https://de.wikipedia.org/wiki/V8_(JavaScript-Implementierung)), eine Implementierung von ECMAScript von Google, als Backend-Runtime bereitzustellen. Ein versprochener Vorteil liegt auf der Hand: Erfahrene Javascript-Entwickler sind, was die generelle Syntax und das Processing angeht, in der Lage, Backend-Applikation zu schreiben.

### Concurrency
#### PHP
PHP läuft in der Regel mit blocking multi-threaded I/O. D.h. PHP kann die Anzahl verfügbarer Prozesse parallel ausliefern. Sollten diese belegt sein, werden neue Anfragen in eine Warteschlange eingereiht und nacheinander abgearbeitet. 

#### Node.js
Node.js basiert auf einer Event-Loop und ist dadurch in der Lage, non-blocking-code auszuführen. Der Hauptteil des Codes wird mit _Callbacks_ ausgeführt. 
```javascript
console.log('test')
db.query('SELECT * FROM users', (err, res) => {
    console.log('query executed')
})
console.log('test2')
```

Das Resultat ist folgende Output:
```shell
$ test
$ test2
$ query executed
```
Während der Datenbank-Treiber die Query im Hintergrund ausführt, wird JavaScript nicht geblockt und kann mit dem letzten `console.log()`-Statement weitermachen.
Sobald die Query ausgeführt wurde, wird der Callback auf die I/O Event Queue gepusht. Die Event loop verbindet die Queue mit dem Call stack und führt das erste Item in dem Fall das `console.log()`-Statement aus.

Der Vorteil ist, dass man einzig den node.js Prozess als limitierenden Faktor hat. Asynchrone Prozesse innerhalb der Applikation werden parallel ausgeführt.
 
In den nächsten Beiträgen dieser Serie werde ich näher in die Materie hineinzoomen. So möchte ich, besonders auf Werkzeuge innerhalb des jeweiligen Scopes ihrer Sprache, eingehen und miteinander vergleichen.