Node.js Backend Entwicklung mit TypeScript

Oliver Vogel
27.03.2020
Oliver Vogel

Wer bei der Server-Entwicklung auf Node.js setzt, wird bei komplexeren Projekten sicherlich schonmal darüber nachgedacht haben zukünftig TypeScript zu verwenden. In unserem heutigen Magazin-Beitrag erfährst du, wie Node.js konfiguriert werden kann, um produktiv mit TypeScript zu arbeiten.

Warum TypeScript?

Traditionell werden Node.js Server mit JavaScript entwickelt. JavaScript ist eine Skriptsprache, welche lediglich für kleinere Programme konzipiert wurde. Für den ursprünglichen Einsatzzweck von JavaScript, das interaktive Erstellen von Elementen auf einfachen Webseiten, ist dies praktisch. Was jedoch problematischer werden kann, ist die Entwicklung von komplexen Servern oder Webanwendungen. Hier kann JavaScript an seine Grenzen stoßen in Form von höherer Fehleranfälligkeit und unübersichtlichem Code. TypeScript wurde im Gegensatz zu JavaScript direkt für die Entwicklung von komplexen Programmen entworfen. Es ist eine vollständige Programmiersprache, die den Funktionsumfang von JavaScript erweitert und somit viele Probleme der Sprache behebt. Außerdem muss der Entwickler hier keine komplette neue Programmiersprache lernen.

Grundvorraussetzungen

Voraussetzung für die Einrichtung sind lediglich die Node.js Runtime. Hier verwenden wir die aktuelle Version 12.16.1 und eine IDE wie VS Code. Selbstverständlich kannst du auch mit deiner bevorzugten IDE arbeiten.

Express und TypeScript

Im CLI erstellen wir einen Projektordner und navigieren in diesen. Dort initialisieren wir zunächst ein neues Node Projekt und installieren dann Express und die benötigten Entwicklungstools:

  • Nodemon, welches den Server bei jeder Dateiänderung neu startet und somit die Entwicklung deutlich angenehmer gestaltet
  • TS Node, welches bei der Entwicklung den Code umrechnet und Source-Maps unterstützt
  • Typescript selbst und ein Typisierungs-Package für Express
npm init
npm i express
npm i -D nodemon ts-node typescript @types/express

Bei der Arbeit mit TypeScript können mit Typisierungs-Packages JavaScript Code Typen hinzufügt werden, wodurch die erweiterte Autovervollständigung verfügbar ist.
Hier lassen sich zu den meisten bekannten Packages zugehörige Typisierungs-Packages finden.

Nun erstellen wir im Root unseres Projekts die Datei ’nodemon.json‘ um Nodemon zu konfigurieren:

 

{
  "ext": "ts",
  "ignore": [".git", "node_modules/**/node_modules", "src/**/*.spec.ts"],
  "execMap": {
    "ts": "node --require ts-node/register"
  },
  "watch": ["src/"]
}

Zusätzlich wird zur Konfiguration vom Typescript Compiler die Datei ‚tsconfig.json‘ erstellt:

 

{
  "compilerOptions": {
    "target": "es2018",
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.test.ts"]
}

Als Nächstes erstellen wir in der ‚package.json‘ Datei ein Skript zur Ausführung von Nodemon und schreiben anschließend einen Test-Server in der Datei ’src/app.ts‘:

"scripts": {
"start-dev": "nodemon src/app.ts"
}
import express from "express";

const app = express();

app.use((req, res) => {
  const test = "Hallo Welt!";
  res.status(200).json({ message: test });
});

app.listen(3000, () => {
  console.log("Running at port 3000"));
});

Was hier auffällt, ist dass in Node mit TypeScript Imports nicht über die require() Funktion, sondern über normale ES6 Module erfolgt.

Wenn wir nun das Skript mit npm run start-dev ausführen, können wir den Server bereits über localhost:3000/ aufrufen.

ESLint und Prettier

Um die Entwicklung noch angenehmer zu gestalten, kannst du in diesem Schritt ESLint und Prettier konfigurieren. ESLint prüft den Code auf Fehler, zeigt diese an und behebt einige automatisch. Prettier hingegen sorgt dafür, dass der Code stets richtig formatiert ist und lesbar bleibt.

Des Weiteren installieren wir die VS Code Erweiterung ‚ESLint‘. Diese zeigt die Fehler direkt in der IDE an und markiert sie.

Wir installieren, neben ESLint und Prettier selbst, verschiedene Packages, welche die Kompatibilität zwischen Typescript, ESLint und Prettier herstellen:

npm i -D eslint prettier @typescript-eslint/eslint-plugin
@typescript-eslint/parser eslint-config-prettier eslint-plugin-import
eslint-plugin-prettier

Anschließend erstellen wir zwei Konfigurationsdateien für ESLint. Einerseits ‚.eslintrc‘, womit wir Prettier integrieren und ESLint anpassen können, andererseits ‚.eslintignore‘ in welche wir Dateien angeben können die ESLint ignorieren soll:

{
  "parser": "@typescript-eslint/parser",
  "extends": ["plugin:@typescript-eslint/recommended", "prettier/@typescript-eslint", 
  "plugin:prettier/recommended"],
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "rules": {
    "@typescript-eslint/no-unused-vars": [1, { "argsIgnorePattern": "^_|^next$" }],
  }
}
node_modules/
dist/

Optional kannst du auch die Datei ‚.prettierrc‘ erstellen, in der die Formatierung von Prettier konfigurieret werden kann. Hier konfigurieren wir beispielsweise die Verwendung von einzelnen Anführungszeichen:

{
  "singleQuote": true
}

Damit auch automatisch Fehler korrigiert und der Code formatiert werden kann, muss in der VS Code Einstellungsdatei noch folgender Code eingefügt werden:

"editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
},

Sollte in deiner Installation außerdem die VS Code Erweiterung ‚Prettier‘ installiert und das automatische Formatieren aktiviert sein, solltest du in den VS Code Einstellungen TypeScript Dateien davon ausschließen. Andernfalls könnten sich die Formatierungen von der Prettier Erweiterung und Prettier in ESLint gegenseitig überschreiben:

"[typescript]": {
  "editor.formatOnSave": false
},

Jetzt muss der Editor neu gestartet werden. Die Fehlermeldungen sollten direkt angezeigt werden, wie in unserem Beispiel die doppelten Anführungszeichen und Semikola. Wird die Datei gespeichert, werden die Fehler direkt automatisch korrigiert.

Debugging

Nun fehlt noch das Debugging, welches aber schnell einsatzbereit ist. Zunächst fügen wir ein Debug Skript in der ‚package.json‘ Datei ein, welches Nodemon im Debug-Modus startet:

"scripts": {
  "start-dev": "nodemon src/app.ts",
  "debug": "nodemon --inspect src/app.ts"
}

Jetzt öffnen wir in VS Code das Debug Menu, klicken dort auf ‚create a launch.json file.‘ und wählen im Menü Node.js. aus. Es wird die Datei ‚.vscode/launch.json‘ erstellt, die wir jetzt konfigurieren können:

{
  "version": "0.2.0",
  "configurations": [
  {
    "type": "node",
    "request": "attach",
    "name": "Node: Nodemon",
    "processId": "${command:PickProcess}",
    "restart": true,
    "protocol": "inspector"
    }
  ]
}

Jetzt führen wir unser Debug Skript mit npm run debug aus und wählen im Debug Penal ‚Run and Debug Node: Nodemon‘. Klicken anschließend auf den Start Button und wählen den Prozess ’node –require ts-node/register –inspect src/app.ts‘ aus. Jetzt kann der Server direkt aus den TypeScript Dateien gedebuggt werden.

Building

Wir haben nun ein gutes Entwicklungs-Setup eingerichtet. Was jedoch fehlt, sind Skripts mit denen wir unser Projekt ausführen, linten und builden können. Dazu fügen wir in der ‚package.json‘ Datei folgende Skripte ein:

"scripts": {
  "start": "node dist/app.js",
  "start-dev": "nodemon src/app.ts",
  "debug": "nodemon --inspect src/app.ts",
  "lint": "tsc --noEmit && eslint '*/**/*.{js,ts}' --quiet --fix",
  "build": "tsc"
}

Mit dem Lint Skript ( npm run lint ) prüfen wir nochmal unsere gesamte Codebase auf Fehler. Mit dem Build Skript ( npm run build ) kompilieren wir unseren TypeScript Code in JavaScript um. Der generierte JavaScript Code wird im ‚dist‘ Ordner gespeichert und kann anschließend mit dem Start Skript ( npm start ) bei unserem Hosting Anbieter ausgeführt werden.

Fazit

Die Konfiguration von TypeScript in einem Node.js Projekt scheint auf dem ersten Blick sehr komplex, ist aber mit den nötigen Code Snippets und ein wenig Übung einfach und schnell erledigt. Wer generell noch nie mit TypeScript gearbeitet hat, kann sich anhand des Beitrags, sowie dieser Dokumentation vertraut machen und bei zukünftigen Projekten von dem erweiterten Funktionsumfang profitieren.
Falls wir euch im Bereich der Backend-Entwicklung unterstützen können, könnt ihr uns gerne kontaktieren.