Dieses Kapitel beschreibt, wie man Web-Apps über TypeScript und webpack erstellt. Wir verwenden nur die DOM-API, kein bestimmtes Frontend-Framework.
GitHub Repository:
ts-demo-webpack
Das Repository ts-demo-webpack, mit dem wir in diesem Kapitel arbeiten, kann von GitHub heruntergeladen werden.
Sie sollten ungefähr vertraut sein mit
In diesem Kapitel bleiben wir bei dem, was von TypeScript am besten unterstützt wird: CommonJS-Module, gebündelt als Skriptdateien.
ts-demo-webpackSo ist das Repository ts-demo-webpack strukturiert
ts-demo-webpack/
build/ (created on demand)
html/
index.html
package.json
ts/
src/
main.ts
tsconfig.json
webpack.config.js
Die Web-App wird wie folgt gebaut
ts/html/build/ mit der vollständigen Web-Appbuild/main-bundle.js geschrieben. Dieser Prozess wird als Bundling bezeichnet und main-bundle.js ist eine Bundle-Datei.build/ kopiert.Beide Ausgabetasks werden von webpack gehandhabt
Das Kopieren der Dateien in html/ nach build/ erfolgt über das webpack Plugin copy-webpack-plugin.
Dieses Kapitel behandelt zwei verschiedene Workflows für das Bundling
ts-loader.dist/ (wie wir es im vorherigen Kapitel getan haben). Dann benötigt webpack keinen Loader und bündelt nur JavaScript-Dateien.Der Großteil dieses Kapitels befasst sich mit der Verwendung von webpack mit ts-loader. Am Ende betrachten wir kurz den anderen Workflow.
package.jsonpackage.json enthält Metadaten für das Projekt
{
"private": true,
"scripts": {
"tsc": "tsc",
"tscw": "tsc --watch",
"wp": "webpack",
"wpw": "webpack --watch",
"serve": "http-server build"
},
"dependencies": {
"@types/lodash": "···",
"copy-webpack-plugin": "···",
"http-server": "···",
"lodash": "···",
"ts-loader": "···",
"typescript": "···",
"webpack": "···",
"webpack-cli": "···"
}
}Die Eigenschaften funktionieren wie folgt
"private": true bedeutet, dass npm keine Beschwerden ausgibt, wenn wir keinen Paketnamen und keine Paketversion angeben.tsc, tscw: Diese Skripte rufen den TypeScript-Compiler direkt auf. Wir brauchen sie nicht, wenn wir webpack mit ts-loader verwenden. Sie sind jedoch nützlich, wenn wir webpack ohne ts-loader verwenden (wie am Ende dieses Kapitels gezeigt).wp: führt webpack einmal aus, kompiliert alles.wpw: führt webpack im Watch-Modus aus, wobei es die Eingabedateien überwacht und nur geänderte Dateien neu kompiliert.serve: startet den Server http-server und bedient das Verzeichnis build/ mit der vollständig zusammengestellten Web-App.webpack: der Kern von webpackwebpack-cli: eine Kommandozeilenschnittstelle für den Kernts-loader: ein Loader für .ts-Dateien, der sie zu JavaScript kompiliertcopy-webpack-plugin: ein Plugin, das Dateien von einem Ort zu einem anderen kopiertts-loader: typescripthttp-serverlodash, @types/lodashwebpack.config.jsSo konfigurieren wir webpack
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
···
entry: {
main: "./ts/src/main.ts",
},
output: {
path: path.resolve(__dirname, 'build'),
filename: "[name]-bundle.js",
},
resolve: {
// Add ".ts" and ".tsx" as resolvable extensions.
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{ test: /\.tsx?$/, loader: "ts-loader" },
],
},
plugins: [
new CopyWebpackPlugin([
{
from: './html',
}
]),
],
};Eigenschaften
entry: Ein Einstiegspunkt ist die Datei, an der webpack mit dem Sammeln der Daten für ein Ausgabebundle beginnt. Zuerst fügt es die Einstiegspunktdatei zum Bundle hinzu, dann die Importe des Einstiegspunkts, dann die Importe der Importe usw. Der Wert der Eigenschaft entry ist ein Objekt, dessen Eigenschaftsschlüssel die Namen der Einstiegspunkte angeben und dessen Eigenschaftswerte die Pfade der Einstiegspunkte angeben.
output gibt den Pfad des Ausgabebundles an. [name] ist hauptsächlich nützlich, wenn es mehrere Einstiegspunkte gibt (und damit mehrere Ausgabebundles). Es wird durch den Namen des Einstiegspunkts ersetzt, wenn der Pfad zusammengestellt wird.
resolve konfiguriert, wie webpack Specifiers (IDs) von Modulen in Dateipfade umwandelt.
module konfiguriert Loader (Plugins, die Dateien verarbeiten) und mehr.
plugins konfiguriert Plugins, die das Verhalten von webpack auf vielfältige Weise ändern und erweitern können.
Weitere Informationen zur Konfiguration von webpack finden Sie auf der webpack-Website.
tsconfig.jsonDiese Datei konfiguriert den TypeScript-Compiler
{
"compilerOptions": {
"rootDir": "ts",
"outDir": "dist",
"target": "es2019",
"lib": [
"es2019",
"dom"
],
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"sourceMap": true
}
}Die Option outDir wird nicht benötigt, wenn wir webpack mit ts-loader verwenden. Wir benötigen sie jedoch, wenn wir webpack ohne Loader verwenden (wie später in diesem Kapitel erklärt).
index.htmlDies ist die HTML-Seite der Web-App
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>ts-demo-webpack</title>
</head>
<body>
<div id="output"></div>
<script src="main-bundle.js"></script>
</body>
</html>Das <div> mit der ID "output" ist der Ort, an dem die Web-App ihre Ausgabe anzeigt. main-bundle.js enthält den gebündelten Code.
main.tsDies ist der TypeScript-Code der Web-App
import template from 'lodash/template';
const outputElement = document.getElementById('output');
if (outputElement) {
const compiled = template(`
<h1><%- heading %></h1>
Current date and time: <%- dateTimeString %>
`.trim());
outputElement.innerHTML = compiled({
heading: 'ts-demo-webpack',
dateTimeString: new Date().toISOString(),
});
}template() von Lodash, um einen String mit benutzerdefinierter Vorlagensyntax in eine Funktion compiled() zu verwandeln, die Daten zu HTML abbildet. Der String definiert zwei Lücken, die über Daten gefüllt werden sollen<%- heading %><%- dateTimeString %>compiled() auf die Daten an (ein Objekt mit zwei Eigenschaften), um HTML zu generieren.Zuerst müssen wir alle npm-Pakete installieren, von denen unsere Web-App abhängt
npm install
Dann müssen wir webpack (das im vorherigen Schritt installiert wurde) über ein Skript in package.json ausführen
npm run wpw
Von nun an überwacht webpack die Dateien im Repository auf Änderungen und baut die Web-App neu, wann immer es Änderungen erkennt.
In einer anderen Kommandozeile können wir nun einen Webserver starten, der den Inhalt von build/ auf localhost bereitstellt
npm run serve
Wenn wir die vom Webserver ausgegebene URL aufrufen, können wir die Web-App in Aktion sehen.
Beachten Sie, dass einfaches Neuladen möglicherweise nicht ausreicht, um die Ergebnisse nach Änderungen anzuzeigen – aufgrund von Caching. Möglicherweise müssen Sie einen erzwungenen Reload durchführen, indem Sie beim Neuladen die Umschalttaste drücken.
Anstatt über eine Kommandozeile zu bauen, können wir dies auch innerhalb von Visual Studio Code tun, über eine sogenannte Build Task
Wählen Sie „Configure Default Build Task…“ aus dem Menü „Terminal“.
Wählen Sie „npm: wpw“.
Ein Problem-Matcher kümmert sich um die Umwandlung von Tool-Ausgaben in Listen von Problemen (Infos, Warnungen und Fehler). Die Standardeinstellung funktioniert in diesem Fall gut. Wenn Sie explizit sein möchten, können Sie einen Wert in .vscode/tasks.json angeben
"problemMatcher": ["$tsc-watch"],Wir können webpack nun über „Run Build Task…“ aus dem Menü „Terminal“ starten.
webpack-no-loader.config.jsAnstatt ts-loader zu verwenden, können wir auch zuerst unsere TypeScript-Dateien in JavaScript-Dateien kompilieren und diese dann über webpack bündeln. Wie der erste dieser beiden Schritte funktioniert, wird im vorherigen Kapitel beschrieben.
Wir müssen ts-loader nun nicht mehr konfigurieren und unsere webpack-Konfigurationsdatei ist einfacher
const path = require('path');
module.exports = {
entry: {
main: "./dist/src/main.js",
},
output: {
path: path.join(__dirname, 'build'),
filename: '[name]-bundle.js',
},
plugins: [
new CopyWebpackPlugin([
{
from: './html',
}
]),
],
};Beachten Sie, dass entry.main anders ist. In der anderen Konfigurationsdatei lautet es
"./ts/src/main.ts"Warum sollten wir Zwischenprodukte produzieren, bevor wir sie bündeln? Ein Vorteil ist, dass wir Node.js verwenden können, um Unit-Tests für einige der TypeScript-Codes auszuführen.