/ TypeScript

TypeScript - Node.js - Start Template

!ACHTUNG, veraltert! Neuere Template Version siehe:
VS Code/TypeScript Start Template für Node.js und Web Applikationen

Die Überlegungen und grundsätzlichen Anmerkungen sind aber hilfreich und deshalb wurde der Artikel nicht entfernt.

Vielleicht geht es nur mir so, aber es fällt mir schwer, ein TypeScript Projekt zu starten, dass alles soweit enthält, dass ich mich auf den Code konzentrieren kann.

Die Zusammenfassung der Let's Code 3/4: VS Code + TypeScript schafft schon einen guten Einstieg und damit will ich für mich die Arbeitsschritte festhalten, um ein TypeScript Template zu erzeugen, das einem hilft ein Projekt zu starten.

Ich denke, man braucht sicher für jeden Projekttyp (Client, Server, Mobile App, ...) so eine Vorgehensweise und so starte ich mal mit einem Node.js Projekt.

  • Yeoman

Viele verwenden anscheinend Yeoman dazu, aber es ist nicht so einfach, sich ein Template dort auszusuchen. Oft hat man dann zu viele Komponenten in seinem Projekt, die man gar nicht einsetzt.

  • GitHub Beispiele

Für mich bisher praktikabler waren Projekte auf Github, die ich kopiert habe und dann soweit bereinigt habe, dass sie für mich passend waren (z.B. das Projekt hottowel-angular-typescript von John Papa oder was ich mir noch ansehen werde ist, das neue Projekt Angular2-JumpStart von Dan Wahlin).

  • Mein eigenes Template

Aber so richtig schnell ist so ein Einstieg auch nicht.
Hat man mal ein Starttemplate, dann kann man das immer wieder anlegen oder einfach kopieren. Meist wird man es aber wieder anpassen, da sich die Welt inzwischen weitergedreht hat und man schlauer geworden ist und andere Komponenten nun verwendet, bzw. Einstellungen inzwischen angepasst hat.

Aus diesem Grund finde ich es wichtig, dass man das Template leichtgewichtig hält und versteht.

Ich will ein Template, dass einen funktionsfähigen Code enthält, also kompiliert und ausführbar ist. Es soll TypeScript Type Declarations verwenden und eine externe Library als Beispiel inkludieren. Da in JavaScript das Aufteilen des Codes in einzelne Module sehr verwirrend ist, wie ich finde, ist mir auch wichtig mindestens zwei ts Files im Template zu haben.

0. Vorbereitung - Packages installieren

Nur eine ganz kurze Anleitung:

  • Visual Studio Code installieren

  • Node.js installieren

  • npm updaten

  • TypeScript und tsd installieren:

      npm install -g typescript tsd
    

Näheres findet man in folgendem Blogeintrag:

  • Node.js und npm installieren

  • Bemerkung: Ich verwende noch tsd statt dem neueren typings. Nach der Bemerkung von Anders Hejlsberg auf der Build Konferenz (siehe unten im Abschnitt Links), kann man wohl typings übertauchen und auf Neueres warten.

1. Projektverzeichnis anlegen und Projekt initialisieren
mkdir template.typescript.1
cd template.typescript.1
npm init

Damit werden nun die Projektdaten abgefragt, einfach mal überall return tippen, man kann das später im package.json File noch eintragen.

2. TypeScript Compiler, Type Declarations, Dateistruktur, Library, VSCode starten

Als Beispiel library verwende ich lodash, eine Utility Bibliothek.
Auch dieser zweite Block kann einfach in die PowerShell kopiert werden:

tsc --init
tsd init

New-Item README.md -ItemType File
New-Item .gitignore -ItemType File
New-Item src -ItemType Directory
New-Item src\index.ts -ItemType File
New-Item src\common -ItemType Directory
New-Item src\common\utils.ts -ItemType File


tsd install node --save

npm install lodash --save
tsd install lodash --save

code .

Der letzte Befehl öffnet Visual Studio Code (VS Code) und damit werden nun ein paar Dateien verändert:

3. Files anpassen
  • src/common/utils.ts:
import * as _ from "lodash";
export class Utils {   
    public static kebapStyle(input: string): string {
        console.log(`kebapStyle(${input})`);
        return _.kebabCase(input);
    }
}
  • src/index.ts:
import {Utils} from "./common/utils";

let s = Utils.kebapStyle("Gurke Tomate Zwiebel");
console.log(s);
  • .gitignore:

      bower_components
      node_modules
      typings
      .vscode
      dist
    
  • tsconfig.json

Auschnitt, des anzupassenden Teils. (Das ganze File siehe unten.)

    "sourceMap": true,
    "rootDir": "src",
    "outDir": "dist",
4. Builden

Nun Builden, damit ein Task Runner config angelegt wird:

Ctrl + Shift + B
- Configure Task Runner:
  - TypeScript - tsconfig.json
  • .vscode/tasks.json

      "showOutput": "silent",
      => 
      "showOutput": "always",
    

Und nun nochmals builden (Ctrl + Shift + B).

Falls der Build Task nicht endet (der Propeller in der Statusleiste nicht aufhört sich zu drehen), dann am besten mal VS Code schließen, neu öffnen und neu compilieren.

5. Debuggen

Sind keine Fehler aufgetreten (Statuslieste zeigt 0 errors), dann starten mit F5.

Es wird nachgefragt (Select Environment) und wir wählen Node.js.

Damit wird eine weiter Datei angelegt, die wir wieder anpassen:

  • .vscode/launch.json

      "program": "${workspaceRoot}/src/index.ts",
      "externalConsole": true,
      "sourceMap": true,
      "outDir": "${workspaceRoot}/dist"
    

Jetzt aber:

F5

  • Programm sollte folgenden Output liefern (Debug Console):

VS Code - fertiges Projekt

6. Testen

Man kann einen Breakpoint in einem TypeScript File setzen oder stopOnEntry im .vscode/launch.json File auf true setzen und den Debugger neuerlich mit F5starten.

Auch sollte man testen, ob IntelliSense funktioniert für die importierte Klasse Utils und für die importierte library lodash (falls das nicht klappt, VS Code schließen und neu starten, hilft meist.):
VS Code - IntelliSense1
VS Code - IntelliSense1

Will man das Programm nur ausführen (und nicht debuggen): Ctrl + F5.


Damit bin ich nun mit meinem Projekt Gerüst fertig und kann mit dem eigentlichen Projekt starten.

  • Bemerkung:

Man kann dieses nun generierte Projekt auch nur als Template verwenden und es immer wieder kopieren. (Dazu am besten folgende Folder entfernen typings, node_modules und dist. Und im neuen Projekt dann npm install und tsd install aufrufen.)

Den Sourcecode findet man auch auf GitHub:
GitHub Repository template.typescript.1

Anhang

A.1 Command-line

Es ist immer gut zu wissen, wie es auch ohne Editor in der PowerShell funktioniert:

Hat man die tsconfig richtig gesetzt, dann reicht folgender Aufruf zum Kompilieren:

tsc

Und zum Ausführen des Programms:

node .\dist\index.js
A.2 VS Code Konfigurationsfiles

Meine Visual Studio Konfigurationsfiles (die sind ja nicht auf Github abgelegt)

  • .vscode/tasks.json

      {
      	// See http://go.microsoft.com/fwlink/?LinkId=733558
      	// for the documentation about the tasks.json format
      	"version": "0.1.0",
      	"command": "tsc",
      	"isShellCommand": true,
      	"args": ["-p", "."],
      	"showOutput": "always",
      	"problemMatcher": "$tsc"
      }
    
  • .vscode/launch.json

      {
      	"version": "0.2.0",
      	"configurations": [
      		{
      			"name": "Launch",
      			"type": "node",
      			"request": "launch",
      			"program": "${workspaceRoot}/src/index.ts",
      			"stopOnEntry": false,
      			"args": [],
      			"cwd": "${workspaceRoot}",
      			"preLaunchTask": null,
      			"runtimeExecutable": null,
      			"runtimeArgs": [
      				"--nolazy"
      			],
      			"env": {
      				"NODE_ENV": "development"
      			},
      			"externalConsole": true,
      			"sourceMaps": true,
      			"outDir": "${workspaceRoot}/dist"
      		},
      		{
      			"name": "Attach",
      			"type": "node",
      			"request": "attach",
      			"port": 5858,
      			"address": "localhost",
      			"restart": false,
      			"sourceMaps": false,
      			"outDir": null,
      			"localRoot": "${workspaceRoot}",
      			"remoteRoot": null
      		}
      	]
      }    
    
A.3 Verbesserungen:

Damit der Sourcecode noch restriktiver vom Compiler überprüft wird, kann man noch ein paar Settings machen.
Da es aber auch mühsam werden kann, den TypeScript Code so zu schreiben, will man diese Settings vielleicht später wieder entfernen.

// tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "noImplicitAny": false,
        "sourceMap": true,
        "rootDir": "src",
        "outDir": "dist",
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "suppressImplicitAnyIndexErrors": true,
        "allowJs": true
    },
    "exclude": [
        "node_modules"
    ]
}

Artikel in diesem Blog


Weitere Let's Code Artikel.