TypeScript-Tooling

TypeScript-Tooling mit npm und Webpack

Avatar von Christopher Stock

In diesem Beitrag beschäftige ich mich mit dem TypeScript-Tooling. Ich werde zeigen, wie einfach und komfortabel man ein Webprojekt mit TypeScript als Compiler und Webpack als Bundler unter Verwendung des Node Package Managers npm installieren und betreiben kann.

Darüber hinaus zeige ich an einem praktischen Beispiel, wie sich externe JavaScript-Bibliotheken mit den dazugehörigen TypeScript-Definitionsdateien via npm importieren und typisiert einsetzen lassen.

TypeScript-Tooling mit npm und Webpack

Um nachvollziehen zu können worum es in diesem Beitrag geht, möchte ich auch auf die einzelnen Schritte in der Vorbereitung eingehen – dazu zählt natürlich auch die Grundlage für unser TypeScript-Tooling: Die Installation von Node.js.

1. Installation von Node.js

Alles was wir für unser Testprojekt benötigen ist eine funktionierende Installation von Node.js. Dieses Paket installiert die Node.js-Laufzeitumgebung sowie den Node Package Manager npm. Installationsanweisungen für Node.js gibt es auf der offiziellen Webseite.

2. Einrichten eines neuen Webprojekts

Für unser Lernprojekt erstellen wir uns einen neuen Ordner, in dem sich unser gesamtes Webprojekt befinden soll. Alle hier definierten Datei- und Pfadangaben verstehen sich relativ zu diesem Projektordner.

2.1. Erstellen einer minimalen HTML-Datei

Unsere fertige und deploybare Webseite wollen wir in dem Unterordner dist/ ablegen. Damit wir unser Projekt im Browser begutachten können, erstellen wir die Datei dist/index.html mit dem folgenden minimalen Inhalt:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    </head>
    <body>
    </body>
</html>

Diese Datei können wir in einem Browser mit guten Entwicklerwerkzeugen, beispielsweise Google Chrome, öffnen. Aktuell werden hier natürlich weder Inhalte noch Konsolenausgaben angezeigt.

2.2. Einrichten des Projekts als Node.js-Projekt

Damit unser Projektordner als ein Node.js-Projekt eingerichtet wird, müssen wir auf der Kommandozeile in unseren Projektordner wechseln und dort den folgenden Befehl ausführen:

npm init -f

Daraufhin wird eine neue Datei package.json im Root unseres Projektverzeichnisses erstellt; damit wird dieses Projekt als Node.js-Projekt gekennzeichnet. Der Parameter -f überspringt dabei die üblichen Nachfragen zu weiteren Projektdetails wie beispielsweise den Projektnamen, die Versionsnummer oder den Autor des Projekts und setzt hierfür Standardwerte ein.

Die erstellte Datei package.json besitzt dabei den folgenden Aufbau:

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

2.3. Installation des TypeScript-Compilers

Als erstes Tool wollen wir nun den TypeScript-Compiler mithilfe des folgenden npm-Befehls installieren:

npm install typescript --save-dev

Durch die Angabe der Option –save-dev wird das Paket typescript im Bereich devDependencies unserer package.json gespeichert. Somit wird ausgedrückt, dass dieses Node.js-Paket zwar nicht für den Betrieb unseres Projektes, wohl aber für dessen Entwicklung benötigt wird.

Um dem TypeScript-Compiler bei jedem Kompiliervorgang den gleichen Satz an Optionen mitzugeben, legen wir im Root unseres Projekts nun die Datei tsconfig.json ab, die als Konfigurationsdatei für den TypeScript-Compiler fungiert:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./tmp",
    "declaration": false,
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": false,
    "typeRoots": [
      "node_modules/@types"
    ],
    "downlevelIteration": true
  },

  "include": [
    "src/**/*"
  ]
}

Im Bereich include wird festgelegt, dass alle TypeScript-Quellcodedateien im Unterordner src/ vom TypeScript-Compiler kompiliert werden sollen. Komplementär dazu spezifiziert die Angabe outDir, wo die erzeugten JavaScript-Dateien abgelegt werden sollen.

Da der Aufruf des TypeScript-Compilers in den folgenden Schritten über Webpack und den hierfür eingerichteten Builder erfolgt, können wir als Ausgabepfad einfach ein beliebiges temporäres Verzeichnis angeben.

Wir erstellen nun unsere erste TypeScript-Datei und legen sie unter src/index.ts ab. Die Datei beinhaltet vorerst lediglich eine einfache Konsolenausgabe:

console.log( "src/index.ts being invoked" );

2.4. Installation von Webpack

Webpack ist ein Tool, das alle in unserem Projekt verwendeten JavaScript-Sourcecodes zu einer einzigen JavaScript-Datei vereint – egal, ob es sich dabei um eigene Quellcodes oder um externe Bibliotheken handelt. Somit muss lediglich eine einzige JavaScript-Datei in unsere Webseite inkludiert werden. Außerdem wird hierdurch das Auftreten von Namenskollisionen beim Einsatz gleich lautender JavaScript-Bezeichner kategorisch ausgeschlossen.

Mit dem folgenden Befehl können wir Webpack für unser npm Projekt installieren. Auch diese Node.js-Erweiterung halten wir mithilfe der Option –save-dev als Development-Dependency in unserer package.json fest:

npm install webpack@3.10.0 --save-dev
ACHTUNG! Da es bei der aktuellen Webpack-4-Version Breaking Changes gibt, ist es für diesen Workshop zwingend erforderlich, durch die explizite Angabe der Versionsnummer Webpack 3 zu installieren!

Damit für Webpack vorgesehene TypeScript-Sprachkonstrukte vom TypeScript-Compiler verstanden werden können, müssen die zu Webpack zugehörigen TypeScript-Definitionen installiert werden. Das erfolgt mittels folgendem Befehl:

npm install @types/webpack --save-dev

Auch für das Tool Webpack wollen wir nun unsere gleichbleibenden Optionen in einer Konfigurationsdatei festhalten. Daher speichern wir den folgenden Inhalt in der Datei webpack.config.js im Root unseres Projektes ab:

var path = require('path');

module.exports = {
  entry: [
    './src/index.ts'
  ],
  output: {
    filename: 'bundle.js',
    path:     path.resolve(__dirname, 'dist/js')
  }
};

Die Angabe entry definiert hier den Einstiegspunkt in unser Projekt. Von dieser Datei ausgehend ermittelt Webpack selbstständig alle benötigten Quellcodes, die in unserem Webprojekt verwendet werden. Sofern erforderlich können hier auch mehrere Einstiegspunkte definiert werden.

Analog dazu legt der Bereich output fest, in welcher Datei all diese JavaScript-Quellcodes vereint werden sollen. In unserem Fall wird der gesamte JavaScript-Quellcode in der Datei dist/js/bundle.js zusammengeführt.

2.5. Einrichten des TypeScript-Loaders

Damit Webpack im Vorfeld an das Zusammenfassen der JavaScript-Quellcodes direkt den TypeScript-Kompilierungsvorgang ausführt, muss im dritten Schritt für unser TypeScript-Tooling ein sogenannter Loader über npm installiert und anschließend in unserer Webpack-Konfigurationsdatei angegeben werden. Dadurch wird es Webpack ermöglicht, Sourcemaps zu generieren, mit denen zur Laufzeit unseres Webprojekts ein direktes Debuggen durch die ursprünglichen TypeScript-Quellcodes möglich ist.

Installieren können wir das npm Paket awesome-typescript-loader mit dem folgenden Befehl:

npm install awesome-typescript-loader --save-dev

Die Konfigurationsdatei für Webpack – webpack.config.js – muss anschließend folgendermaßen erweitert werden:

var path = require('path');

module.exports = {
  entry: [
    './src/index.ts'
  ],
  output: {
    filename: 'bundle.js',
    path:     path.resolve(__dirname, 'dist/js')
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'awesome-typescript-loader'
      }
    ]
  },
  resolve: {
    extensions: [
      '.ts',
      '.js'
    ]
  }
};

Durch die Angaben devtool und resolve wird Webpack nun explizit angewiesen, die Source Maps für alle JavaScript- und TypeScript-Quellcodes zu erstellen. Der zuletzt installierte Loader awesome-typescript-loader wird als Loader in unserer Konfigurationsdatei für Webpack angegeben.

Somit haben wir alle Komponenten beisammen, die wir für das TypeScript-Tooling unseres Webprojekts benötigen. Im nächsten Schritt müssen wir lediglich noch den Aufruf des Webpack-Tools via npm festhalten und das fertig gebundelte Kompilat in unsere Webseite einbinden.

3. Kompilieren, Bundeln und Einbinden des Kompilats

Im Bereich scripts unserer Datei package.json können vorkonfektionierte Aufrufe der via npm installierten Tools definiert werden. Wir können nun ein Skript start durch die folgende Erweiterung in der Datei package.json definieren, welches unser Tool Webpack aufruft:

  "scripts": {
    "start": "webpack --watch"
  },

Durch die Angabe der Option –watch etabliert Webpack einen Filewatcher, sodass sich das Tool bei jeder Veränderung einer involvierten TypeScript-Quelldatei selbstständig neu startet.

Anschließend können wir unsere kleine Toolchain durch einen Aufruf des soeben definierten npm-Skripts in Gang bringen:

npm start

Nach dem Durchlauf des Webpack-Tools befinden sich nun alle JavaScript-Sources in der generierten Datei dist/js/bundle.js.

Damit unsere Webseite diese Datei nutzen kann, müssen wir sie natürlich noch in unsere Webseite unter dist/index.html durch Hinzufügen eines Skript-Tags einbinden:

    
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <script src="js/bundle.js" type="text/javascript"></script>
    </head>
    <body>
    </body>
</html>

Beim Aktualisieren unserer im Browser geöffneten Datei wird unsere Ausgabe nun in der Konsole der Entwicklerwerkzeuge angezeigt.

Mit diesem Schritt ist unser TypeScript-Tooling abgeschlossen. Wir können nun unser Webprojekt komplett in TypeScript schreiben. Bei jeder Änderung unserer TypeScript-Quelldateien werden durch den Webpack-Filewatcher die Quellcodes neu kompiliert und im Anschluss automatisiert in der JavaScript-Datei dist/js/bundle.js zusammengefasst.

[smartblock id=6354]

4. Hinzufügen und Nutzen einer externen JavaScript-Bibliothek

Im letzten Schritt dieses Artikels möchte ich zeigen, wie schnell und komfortabel wir nun externe JavaScript-Bibliotheken samt deren zugehörigen TypeScript-Definitionsdateien via npm installieren und typisiert nutzen können.

Die externe Bibliothek Matter.js repräsentiert eine 2D-Physik-Engine, mit der sich schnell und einfach physikalische Berechnungen im zweidimensionalen Raum darstellen lassen.

Diese Bibliothek kann via npm mit dem folgenden Befehl installiert werden:

npm install matter-js --save

Da diese Bibliothek zum Betrieb unseres Webprojektes benötigt wird, verwenden wir hier die die Option –save. Somit wird diese Dependency als Abhängigkeit des Projektes in der Datei package.json festgehalten und erscheint daher in der Sektion dependencies anstatt in der Sektion devDependencies.

Die zur Bibliothek Matter.js zugehörigen TypeScript-Definitionsdateien befinden sich in dem gleichnamigen npm-Paket, das mit dem Präfix @types ausgestattet ist. Mit dem folgenden Befehl werden diese TypeScript-Definitionen installiert und wiederum als Development-Dependency festgehalten:

npm install @types/matter-js --save-dev

Jetzt können wir den Inhalt unserer einzigen TypeScript-Quelldatei src/index.ts folgendermaßen abändern, um eine minimale Demo der Matter.js-Bibliothek mit allen Vorteilen der Sprache TypeScript verwenden zu können:

    import * as Matter from 'matter-js';

    /**
    *   Demonstrates the usage of the MatterJS engine.
    */
    class MatterJsDemo
    {
        /**
        *   Represents the entry point to our MatterJs demo.
        *   This method creates a new MatterJs engine, adds two boxes along
        *   with a static ground and starts the MatterJs physics simulation.
        */
        public static main()
        {
            let body:HTMLBodyElement = document.querySelector("body");
            let engine:Matter.Engine = Matter.Engine.create( body );

            let boxA:Matter.Body   = Matter.Bodies.rectangle( 400, 200, 80,  80 );
            let boxB:Matter.Body   = Matter.Bodies.rectangle( 450, 50,  80,  80 );
            let ground:Matter.Body = Matter.Bodies.rectangle( 400, 610, 810, 60, { isStatic: true } );

            // add all bodies to the engine's world
            Matter.World.add
            (
                engine.world,
                [
                    boxA,
                    boxB,
                    ground,
                ]
            );

            // start the MatterJS simulation
            Matter.Engine.run( engine );
        }
    }

    /**
    *   Being invoked when all components of the website are loaded.
    */
    window.onload = function()
    {
        MatterJsDemo.main();
    };

Nach dem Speichern der Datei wird sie von Webpack neu kompiliert und gebundelt. Danach können wir das Resultat unserer Demo im Browser durch einen Refresh der Seite begutachten:

Conclusion

Auch wenn man sich als Softwareentwickler in erster Linie auf das Schreiben qualitativ hochwertiger Quellcodes konzentrieren möchte, so kommt man in der Webentwicklung nicht um das Thema “Tooling“ herum.

Daher würde ich mich sehr freuen, wenn ich mit meinem Blogbeitrag zum Thema TypeScript-Tooling einen schnellen und verständlichen Einstieg zum Aufsetzen eines Webprojektes mittels npm unter Verwendung der Technologien TypeScript und Webpack geben konnte.

Der Projektcode des Workshops „TypeScript-Tooling“ ist auf GitHub zu finden.

Für Feedback, Anregungen sowie Kritik bin ich wie immer gerne unter meiner E-Mail-Adresse christopher.stock@mayflower.de erreichbar.

 

Ricky Kharawala

Avatar von Christopher Stock

Kommentare

3 Antworten zu „TypeScript-Tooling mit npm und Webpack“

  1. npm + Webpack = TypeScript-Tooling für Fortgeschrittene. Mehr dazu von unserem @jenetic1980 – https://t.co/vrMbCITc5K

  2. Unser @jenetic1980 über das Tooling mit #typescript: https://t.co/vrMbCITc5K

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.