Ziel dieser Aufgabe ist es eine Umgebung zu haben, in der man, sobald eine Änderung in einer TypeScript Datei gemacht wird, die Auswirkungen direkt beim Speichern im Browser sieht.
Wir werden dabei eine Ansammlung an Tools benutzen: TSC (TypeScript Compiler), Nodemon (Node Runtime mit Watcher auf .js Dateien) und Express (Lokaler Webserver).
Das hier wird dabei der Flow des Ganzen:
Der Weg
1. Strukturieren des Projekts
Viele Projekte in der Webentwicklung haben mindestens folgende Ordner im Top Level:
public (für statische Inhalte wie z.B. .html Dateien oder Bilder)
src (für Quellcode)
In /public sollte eine frische Datei index.html liegen.
In /src eine Datei main.js (noch nicht .ts, das kommt später).
Der Überischtlichkeit halber wäre es hilfreich alle Dateien, die ähnlich heißen, entsprechend unbenennen.
2. Einbinden der .js Datei in index.html
Um JavaScript im Browser ausführen zu können, müssen wir eine Script Datei einbinden. Wie das geht, lässt sich einfach ergooglen. Der Pfad zur main.js aus Sicht der index.html lautet übrigens ../src/main.js (also gehe ein Level hoch, dann in src, und darin die main.js).
Um das zu testen erstelle in main.js ein Objekt person mit den Props givenName und lastName und logge dies in die Konsole.
Wenn das Script richtig eingebunden wurde, wird nun die entsprechende Ausgabe in der Browser Konsole ausgegeben (Cmd+Option+I -> Tab: "Console").
3. Umstellen der Source auf TypeScript
Wir wollen in unserem Sourcecode TypeScript verwenden. Deshalb müssen wir nun also main.js in main.ts umbenennen, und einen Typen Person definieren, der als Vorlage für das bereits definierte Objekt dient.
Das Problem ist hier, dass der Browser kein TypeScript versteht. Die src des Scripts im .html File also einfach auf src/main.ts umzustellen funktioniert nicht.
Um das zu lösen, werden wir eine CLI verwenden, die aus unserem Sourcecode (TypeScript) browser-kompatiblen Code (natives JavaScript) kompiliert. Die besagt CLI dafür heißt tsc.
Damit die CLI anständig funktioniert, müssen ein paar Ändeurngen in der tsconfig.json vorgenommen werden. In den compilerOptions müssen folgende Einträge enthalten sein:
"outDir": "./dist",
"rootDir": "./src"
Zudem muss im Top level "include": ["src/**/*.ts"] definiert sein.
Fertig konfiguriert lässt sich das Ganze dann einfach über npx tsc ausführen.
Mit diesem Command wird der Code in src/main.ts gelesen, zu JavaScript Code kompiliert, und in einem Verzeichnis dist ausgespuckt.
Es wurde nach dem Ausführen des Commands nun also ein Ordner dist mit einer Datei main.js darin erstellt.
Wenn wir nun in der .html Datei sagen, dass das Script nicht mehr aus src/main.js sondern aus dist/main.js gelesen werden soll, sieht man, dass alles wieder funktioniert.
Das dist Verzeichnis nimmt man übrigens üblicherweise in die .gitignore Datei mit auf, weil darin nur automatisch generierter Code liegt. In Git soll aber nur der Sourcecode liegen.
4. Aufsetzen eines lokalen Webservers
Aktuell ist es nun so, dass wir nach jeder Änderung in main.ts erstmal den TypeScript Compiler mit npx tsc drüberjagen müssen. Das wollen wir natürlich nicht.
Zudem müssen wir jedes Mal die Seite neu laden, damit wir unsre kompilierten Änderungen im .js File sehen. Auch das wollen wir nicht.
Damit der .js File sich automatisch updated, wenn wir etwas in main.ts ändern, können wir den TypeScript Compiler mit der Flag -w aufrufen, also so: npx tsc -w.
-w steht für Watcher, und dies bewirkt, dass der Terminal Tab quasi "blockiert" und permanent auf Änderungen in in der konfigurierten rootDir ("./src") lauscht und diese direkt neu kompiliert – Also unser .js File updatet.
Damit Änderungen im Quellcode nun auch sofort ein Neuladen im Browser verursachen, können wir unsre index.html nicht mehr lokal aufrufen. Stattdessen werden wir auf unsrem Rechner einen "lokalen Webserver" aufsetzen, der – ähnlich wie der tsc Watcher – auf Änderungen im /dist Verzeichnis lauscht, und dem Browser sagt: "Wenn sich hier was ändert, lade die Seite neu".
Dafür installieren wir neue Dependencies:
npm i express
npm i -D nodemon livereload connect-livereload
nodemon ist ähnlich wie node eine JavaScript Runtime CLI, mit der sich ein Node Server hochfahren lässt. Anders als node merkt nodemon aber, wenn sich Dateien ändern, und startet dann den Express Server neu.
express ist eine Library, die es ermöglicht dann lokal den eigentlichen Webserver aufzusetzen.
livereload und conntect-livereload sind Libraries, die in Express eingebunden werden können um ein Refresh-Signal an den Browser zu senden.
Dafür brauchen wir einmal eine neue Datei server.js in unsrer Root Dir (parallel zur package.json) mit folgendem Inhalt:
Wenn wir nun npx nodemon server.js in der Konsole ausführen, starten wir mit Nodemon dieses Script, welches effektiv den lokalen Webserver unter http://localhost:3000 hostet.
Unter dieser Adresse können wir nun unsere Seite aufrufen.
Als letzte Anpassung muss nun noch in der .html Datei der Pfad zur .js Datei geändert werden.
Auf einem Webserver kann man nämlich nicht mit ../ über die Root Directory hinaus nach oben raus gehen. Deshalb haben wir in server.js auch explizit den dist Ordner unter /dist zur Verfügung gestellt.
Wenn wir nun also den Pfad zu /dist/main.js ändern, funktioniert wieder alles.
Und wenn nun etwas in main.ts geändert wird, aktualisiert sich direkt der Browser, weil durch den TSC Watcher direkt der .js File in /dist geupdatet wird, und durch Nodemon das Update in /dist einen Refresh im Browser triggert.
5. Scripts
Um uns alles noch ein wenig einfacher zu machen, können wir zuletzt in unsrer package.json Scripts definieren. Aktuell schreiben wir also jedes Mal npx tsc -w und npx nodemon server.js um unsre Entwicklungsumgebung zu starten.
npm lässt uns mit Hilfe des run Befehls aber auch Scripts aus der package.json auszuführen.
Heißt also, wenn wir in der package.json folgendes einfügen:
Ziel
Ziel dieser Aufgabe ist es eine Umgebung zu haben, in der man, sobald eine Änderung in einer TypeScript Datei gemacht wird, die Auswirkungen direkt beim Speichern im Browser sieht.
Wir werden dabei eine Ansammlung an Tools benutzen: TSC (TypeScript Compiler), Nodemon (Node Runtime mit Watcher auf .js Dateien) und Express (Lokaler Webserver). Das hier wird dabei der Flow des Ganzen:
Der Weg
1. Strukturieren des Projekts
Viele Projekte in der Webentwicklung haben mindestens folgende Ordner im Top Level:
/public
sollte eine frische Dateiindex.html
liegen. In/src
eine Dateimain.js
(noch nicht .ts, das kommt später).Der Überischtlichkeit halber wäre es hilfreich alle Dateien, die ähnlich heißen, entsprechend unbenennen.
2. Einbinden der .js Datei in
index.html
Um JavaScript im Browser ausführen zu können, müssen wir eine Script Datei einbinden. Wie das geht, lässt sich einfach ergooglen. Der Pfad zur main.js aus Sicht der index.html lautet übrigens
../src/main.js
(also gehe ein Level hoch, dann in src, und darin die main.js). Um das zu testen erstelle inmain.js
ein Objektperson
mit den PropsgivenName
undlastName
und logge dies in die Konsole. Wenn das Script richtig eingebunden wurde, wird nun die entsprechende Ausgabe in der Browser Konsole ausgegeben (Cmd+Option+I -> Tab: "Console").3. Umstellen der Source auf TypeScript
Wir wollen in unserem Sourcecode TypeScript verwenden. Deshalb müssen wir nun also main.js in main.ts umbenennen, und einen Typen
Person
definieren, der als Vorlage für das bereits definierte Objekt dient.Das Problem ist hier, dass der Browser kein TypeScript versteht. Die src des Scripts im .html File also einfach auf
src/main.ts
umzustellen funktioniert nicht. Um das zu lösen, werden wir eine CLI verwenden, die aus unserem Sourcecode (TypeScript) browser-kompatiblen Code (natives JavaScript) kompiliert. Die besagt CLI dafür heißttsc
. Damit die CLI anständig funktioniert, müssen ein paar Ändeurngen in dertsconfig.json
vorgenommen werden. In den compilerOptions müssen folgende Einträge enthalten sein:Zudem muss im Top level
"include": ["src/**/*.ts"]
definiert sein.Fertig konfiguriert lässt sich das Ganze dann einfach über
npx tsc
ausführen.Mit diesem Command wird der Code in
src/main.ts
gelesen, zu JavaScript Code kompiliert, und in einem Verzeichnisdist
ausgespuckt. Es wurde nach dem Ausführen des Commands nun also ein Ordnerdist
mit einer Dateimain.js
darin erstellt.Wenn wir nun in der .html Datei sagen, dass das Script nicht mehr aus
src/main.js
sondern ausdist/main.js
gelesen werden soll, sieht man, dass alles wieder funktioniert.Das
dist
Verzeichnis nimmt man übrigens üblicherweise in die.gitignore
Datei mit auf, weil darin nur automatisch generierter Code liegt. In Git soll aber nur der Sourcecode liegen.4. Aufsetzen eines lokalen Webservers
Aktuell ist es nun so, dass wir nach jeder Änderung in main.ts erstmal den TypeScript Compiler mit
npx tsc
drüberjagen müssen. Das wollen wir natürlich nicht. Zudem müssen wir jedes Mal die Seite neu laden, damit wir unsre kompilierten Änderungen im .js File sehen. Auch das wollen wir nicht.Damit der .js File sich automatisch updated, wenn wir etwas in main.ts ändern, können wir den TypeScript Compiler mit der Flag
-w
aufrufen, also so:npx tsc -w
. -w steht für Watcher, und dies bewirkt, dass der Terminal Tab quasi "blockiert" und permanent auf Änderungen in in der konfigurierten rootDir ("./src") lauscht und diese direkt neu kompiliert – Also unser .js File updatet.Damit Änderungen im Quellcode nun auch sofort ein Neuladen im Browser verursachen, können wir unsre
index.html
nicht mehr lokal aufrufen. Stattdessen werden wir auf unsrem Rechner einen "lokalen Webserver" aufsetzen, der – ähnlich wie der tsc Watcher – auf Änderungen im /dist Verzeichnis lauscht, und dem Browser sagt: "Wenn sich hier was ändert, lade die Seite neu".Dafür installieren wir neue Dependencies:
nodemon
ist ähnlich wienode
eine JavaScript Runtime CLI, mit der sich ein Node Server hochfahren lässt. Anders alsnode
merktnodemon
aber, wenn sich Dateien ändern, und startet dann den Express Server neu.express
ist eine Library, die es ermöglicht dann lokal den eigentlichen Webserver aufzusetzen.livereload
undconntect-livereload
sind Libraries, die in Express eingebunden werden können um ein Refresh-Signal an den Browser zu senden.Dafür brauchen wir einmal eine neue Datei
server.js
in unsrer Root Dir (parallel zurpackage.json
) mit folgendem Inhalt:Wenn wir nun
npx nodemon server.js
in der Konsole ausführen, starten wir mit Nodemon dieses Script, welches effektiv den lokalen Webserver unterhttp://localhost:3000
hostet. Unter dieser Adresse können wir nun unsere Seite aufrufen.Als letzte Anpassung muss nun noch in der .html Datei der Pfad zur .js Datei geändert werden. Auf einem Webserver kann man nämlich nicht mit
../
über die Root Directory hinaus nach oben raus gehen. Deshalb haben wir inserver.js
auch explizit dendist
Ordner unter/dist
zur Verfügung gestellt. Wenn wir nun also den Pfad zu/dist/main.js
ändern, funktioniert wieder alles.Und wenn nun etwas in
main.ts
geändert wird, aktualisiert sich direkt der Browser, weil durch den TSC Watcher direkt der .js File in /dist geupdatet wird, und durch Nodemon das Update in /dist einen Refresh im Browser triggert.5. Scripts
Um uns alles noch ein wenig einfacher zu machen, können wir zuletzt in unsrer
package.json
Scripts definieren. Aktuell schreiben wir also jedes Malnpx tsc -w
undnpx nodemon server.js
um unsre Entwicklungsumgebung zu starten.npm
lässt uns mit Hilfe desrun
Befehls aber auch Scripts aus derpackage.json
auszuführen. Heißt also, wenn wir in derpackage.json
folgendes einfügen:können wir einfach
npm run ts
undnpm run dev
benutzen, was gerade wenn man komplexere Startbefehle verwendet, eine wahre Erleichterung sein kann.