本章では、TypeScriptとwebpackを使用してウェブアプリを作成する方法について説明します。特定のフロントエンドフレームワークではなく、DOM APIのみを使用します。
GitHubリポジトリ:`ts-demo-webpack`
本章で扱うリポジトリ`ts-demo-webpack`は、GitHubからダウンロードできます。
大まかに以下の知識が必要です。
本章では、TypeScriptで最もよくサポートされているもの、つまりCommonJSモジュールをスクリプトファイルとしてバンドルすることに重点を置いています。
リポジトリ`ts-demo-webpack`の構造は以下のとおりです。
ts-demo-webpack/
build/ (created on demand)
html/
index.html
package.json
ts/
src/
main.ts
tsconfig.json
webpack.config.js
ウェブアプリは次のようにビルドされます。
両方の出力タスクはwebpackによって処理されます。
`html/`内のファイルを`build/`にコピーする作業は、webpackのプラグイン`copy-webpack-plugin`によって行われます。
本章では、バンドルするための2つの異なるワークフローについて説明します。
本章の大部分は、`ts-loader`を使用したwebpackの使い方についてです。最後に、もう1つのワークフローを簡単に見ていきます。
`package.json`には、プロジェクトのメタデータが含まれています。
{
"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": "···"
}
}
プロパティの動作は以下のとおりです。
webpackは次のように設定します。
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
.exports = {
module
···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',
},
]),
]; }
プロパティ
`entry`:エントリポイントは、webpackが出力バンドルのデータの収集を開始するファイルです。まず、エントリポイントファイルをバンドルに追加し、次にエントリポイントのインポート、さらにインポートのインポートなどを追加します。`entry`プロパティの値は、プロパティキーがエントリポイントの名前を指定し、プロパティ値がエントリポイントのパスを指定するオブジェクトです。
`output`は、出力バンドルのパスを指定します。`[name]`は、複数のエントリポイント(したがって複数の出力バンドル)がある場合に主に役立ちます。パスを組み立てるときに、エントリポイントの名前に置き換えられます。
`resolve`は、webpackがモジュールの指定子(ID)をファイルの場所にどのように変換するかを設定します。
`module`は、ローダー(ファイルを処理するプラグイン)などを設定します。
`plugins`は、さまざまな方法でwebpackの動作を変更および拡張できるプラグインを設定します。
webpackの設定の詳細については、webpackのウェブサイトを参照してください。
このファイルはTypeScriptコンパイラを設定します。
{
"compilerOptions": {
"rootDir": "ts",
"outDir": "dist",
"target": "es2019",
"lib": [
"es2019",
"dom"
],
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"sourceMap": true
}
}
`ts-loader`と共にwebpackを使用する場合は、`outDir`オプションは必要ありません。ただし、ローダーなしでwebpackを使用する場合は(本章で後述するように)、必要になります。
これはウェブアプリのHTMLページです。
<!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>
IDが`output`の`<div>`は、ウェブアプリが出力を表示する場所です。`main-bundle.js`には、バンドルされたコードが含まれています。
これはウェブアプリのTypeScriptコードです。
import template from 'lodash/template';
= document.getElementById('output');
const outputElement if (outputElement) {
= template(`
const compiled <h1><%- heading %></h1>
Current date and time: <%- dateTimeString %>
`.trim());
.innerHTML = compiled({
outputElement: 'ts-demo-webpack',
heading: new Date().toISOString(),
dateTimeString;
}) }
<%- heading %>
<%- dateTimeString %>
まず、ウェブアプリが依存するすべてのnpmパッケージをインストールする必要があります。
npm install
次に、`package.json`内のスクリプトを使用して、(前のステップでインストールされた)webpackを実行する必要があります。
npm run wpw
以降、webpackはリポジトリ内のファイルの変更を監視し、変更を検出するたびにウェブアプリを再構築します。
別のコマンドラインで、`build/`の内容をlocalhostで提供するウェブサーバーを開始できます。
npm run serve
ウェブサーバーによって出力されたURLにアクセスすると、動作しているウェブアプリを見ることができます。
キャッシュのため、変更後の結果を見るには、単純なリロードだけでは不十分な場合があります。リロード時にShiftキーを押して強制リロードする必要がある場合があります。
コマンドラインからビルドする代わりに、いわゆるビルドタスクを使用して、Visual Studio Code内からビルドすることもできます。
「ターミナル」メニューから「デフォルトのビルドタスクの構成…」を実行します。
「npm: wpw」を選択します。
問題マッチャーは、ツールの出力を問題(情報、警告、エラー)のリストに変換します。デフォルト設定はこの場合でも問題なく機能します。明示的に指定する場合は、`.vscode/tasks.json`で値を指定できます。
"problemMatcher": ["$tsc-watch"],
これで、「ターミナル」メニューから「ビルドタスクの実行…」を使用してwebpackを開始できます。
`ts-loader`を使用する代わりに、まずTypeScriptファイルをJavaScriptファイルにコンパイルし、それらをwebpackでバンドルすることもできます。これらの2つのステップの最初のステップがどのように機能するかは、前の章で説明されています。
これで`ts-loader`を設定する必要がなくなり、webpackの設定ファイルが簡素化されます。
const path = require('path');
.exports = {
moduleentry: {
main: "./dist/src/main.js",
,
}output: {
path: path.join(__dirname, 'build'),
filename: '[name]-bundle.js',
,
}plugins: [
new CopyWebpackPlugin([
{from: './html',
},
]),
]; }
`entry.main`が異なることに注意してください。もう一方の設定ファイルでは、それは…です。
"./ts/src/main.ts"
バンドルする前に中間ファイルを生成するのはなぜでしょうか?1つの利点は、Node.jsを使用して一部のTypeScriptコードの単体テストを実行できることです。