TypeScript meistern
Bitte unterstützen Sie dieses Buch: kaufen Sie es oder spenden Sie
(Werbung, bitte nicht blockieren.)

8 Erstellen von CommonJS-basierten npm-Paketen mit TypeScript



Dieses Kapitel beschreibt, wie man mit TypeScript Pakete für den Paketmanager npm erstellt, die auf dem CommonJS-Modulformat basieren.

  GitHub-Repository: ts-demo-npm-cjs

In diesem Kapitel untersuchen wir das Repository ts-demo-npm-cjs, das von GitHub heruntergeladen werden kann. (Ich habe es bewusst nicht als Paket bei npm veröffentlicht.)

8.1 Erforderliches Wissen

Sie sollten ungefähr vertraut sein mit

8.2 Einschränkungen

In diesem Kapitel verwenden wir das, was TypeScript derzeit am besten unterstützt

Insbesondere unter Node.js unterstützt TypeScript derzeit nicht wirklich ECMAScript-Module und Dateiendungen außer .js.

8.3 Das Repository ts-demo-npm-cjs

So ist das Repository ts-demo-npm-cjs strukturiert

ts-demo-npm-cjs/
  .gitignore
  .npmignore
  dist/   (created on demand)
  package.json
  ts/
    src/
      index.ts
    test/
      index_test.ts
  tsconfig.json

Neben der package.json für das Paket enthält das Repository

package.json enthält Skripte zum Kompilieren

Hier werden die Kompilierungsergebnisse für die beiden TypeScript-Dateien abgelegt

ts/src/index.ts       --> dist/src/index.js
ts/test/index_test.ts --> dist/test/index_test.js

8.4 .gitignore

Diese Datei listet die Verzeichnisse auf, die wir nicht in Git einchecken wollen

node_modules/
dist/

Erläuterungen

8.5 .npmignore

Wenn es darum geht, welche Dateien zum npm-Registry hochgeladen werden sollen und welche nicht, haben wir andere Anforderungen als bei Git. Daher benötigen wir zusätzlich zu .gitignore auch die Datei .npmignore

ts/

Die beiden Unterschiede sind

Beachten Sie, dass npm das Verzeichnis node_modules/ standardmäßig ignoriert.

8.6 package.json

package.json sieht so aus

{
  ···
  "type": "commonjs",
  "main": "./dist/src/index.js",
  "types": "./dist/src/index.d.ts",
  "scripts": {
    "clean": "shx rm -rf dist/*",
    "build": "tsc",
    "watch": "tsc --watch",
    "test": "mocha --ui qunit",
    "testall": "mocha --ui qunit dist/test",
    "prepack": "npm run clean && npm run build"
  },
  "// devDependencies": {
    "@types/node": "Needed for unit test assertions (assert.equal() etc.)",
    "shx": "Needed for development-time package.json scripts"
  },
  "devDependencies": {
    "@types/lodash": "···",
    "@types/mocha": "···",
    "@types/node": "···",
    "mocha": "···",
    "shx": "···"
  },
  "dependencies": {
    "lodash": "···"
  }
}

Werfen wir einen Blick auf die Eigenschaften

Die nächsten beiden Unterabschnitte behandeln die restlichen Eigenschaften.

8.6.1 Skripte

Die Eigenschaft scripts definiert verschiedene Befehle, die über npm run aufgerufen werden können. Zum Beispiel wird das Skript clean über npm run clean aufgerufen. Die vorherige package.json enthält die folgenden Skripte

Beachten Sie, dass wir bei der Verwendung einer IDE die Skripte build und watch nicht benötigen, da wir die IDE die Artefakte erstellen lassen können. Sie werden jedoch für das Skript prepack benötigt.

8.6.2 dependencies vs. devDependencies

dependencies sollten nur die Pakete enthalten, die beim Importieren eines Pakets benötigt werden. Dies schließt Pakete aus, die zum Ausführen von Tests usw. verwendet werden.

Pakete, deren Namen mit @types/ beginnen, stellen TypeScript-Typdefinitionen für Pakete bereit, die keine eigenen haben. Ohne erstere können wir letztere nicht verwenden. Sind dies normale Abhängigkeiten oder Dev-Abhängigkeiten? Das hängt davon ab

8.6.3 Weitere Informationen zu package.json

8.7 tsconfig.json

{
  "compilerOptions": {
    "rootDir": "ts",
    "outDir": "dist",
    "target": "es2019",
    "lib": [
      "es2019"
    ],
    "module": "commonjs",
    "esModuleInterop": true,
    "strict": true,
    "declaration": true,
    "sourceMap": true
  }
}

Die übrigen Optionen werden von der offiziellen Dokumentation für tsconfig.json erklärt.

8.8 TypeScript-Code

8.8.1 index.ts

Diese Datei liefert die eigentliche Funktionalität des Pakets

import endsWith from 'lodash/endsWith';

export function removeSuffix(str: string, suffix: string) {
  if (!endsWith(str, suffix)) {
    throw new Error(JSON.stringify(suffix)} + ' is not a suffix of ' +
      JSON.stringify(str));
  }
  return str.slice(0, -suffix.length);
}

Sie verwendet die Funktion endsWith() der Bibliothek Lodash. Deshalb ist Lodash eine normale Abhängigkeit – sie wird zur Laufzeit benötigt.

8.8.2 index_test.ts

Diese Datei enthält einen Unit-Test für index.ts

import { strict as assert } from 'assert';
import { removeSuffix } from '../src/index';

test('removeSuffix()', () => {
  assert.equal(
    removeSuffix('myfile.txt', '.txt'),
    'myfile');
  assert.throws(() => removeSuffix('myfile.txt', 'abc'));
});

Wir können den Test wie folgt ausführen

npm t dist/test/index_test.js

Wie Sie sehen, führen wir die kompilierte Version des Tests (im Verzeichnis dist/) aus, nicht den TypeScript-Code.

Weitere Informationen zum Unit-Test-Framework Mocha finden Sie auf seiner Homepage.