TypeScript のコンパイルと Node.js 実行の流れ
はじめに
新規プロジェクトで Node.js のベース実装をしているのですが...
tsconfig.json の設定がよくわからない、そもそもどう動いているのかから怪しいと思い、TypeScript にわかだなと反省したので調べました。
TypeScript のコンパイルと Node.js 実行の流れについてや tsconfig.json について、実際に手を動かしてコンパイルをしながら学んだことをまとめた内容になっています!
TypeScript のコンパイルと Node.js 実行の流れ
そもそも Node.js と TypeScript とは
Node.js とは Javascript の実行環境で、サーバーサイドで JavaScript を実行できるようにしたものです。TypeScript とは JavaScript を拡張したプログラミング言語であり、静的型付け(型チェック)によってコードの安全性を向上させます。
TypeScript は開発用のコードであり、そのままでは Node.js で実行できないため、JavaScriptに変換(コンパイル)する必要があります。
TypeScript で開発してから Node.js で実行までのフロー
以下のような流れです。
- TypeScript で開発する。
- TypeScriptのコンパイラーである
tsc
でコンパイル (TypeScript → JavaScript)- TypeScript の型チェック。
- エラーがない場合は JavaScript ファイルを生成。
- 生成された JavaScript を Node.js で実行。
実際に TypeScript をコンパイルしてNode.js で実行してみます。
① 新規フォルダを作成し、以下コマンドでpackage.json
を作成
$ npm init
② TypeScript のコンパイラをインストール
$ npm install typescript
これにより、tsc
というコマンドが使用できるようになります。
③ hello.tsを作成
const message: string = "Hello! TypeScript!";
console.log(message);
④ TypeScriptをコンパイル
$ tsc hello.ts
コンパイルが成功するとhello.js
ファイルが作成されます。
⑤ JavaScriptをNode.jsで実行
$ node hello.js
ターミナルにHello! TypeScript!
と表示されます。
tsconfig.json とは
tsconfig.json とは TypeScript から JavaScript にコンパイルするための設定ファイルです。
プロジェクト内の TypeScript ファイルをどのようにJavaScript に変換するかを指定することができます。
tsconfig.json が作成されます。
$ tsc --init
よく使用するオプションを紹介します。※オプションを紹介してくれている記事がたくさんあるのでここではあまり詳しく書かないです。
include
コンパイルする対象ファイルを記述します。
ワイルドカード (* ) や再帰パターン (**/*) を使うことができます。
ファイル名は tsconfig.json ファイルを含んでいるディレクトリからの相対パスとして解決されます。
exclude
include
で指定したファイルから特別に除外するファイルを記述します。
extends
他の tsconfig.json 設定ファイルを継承 するためのプロパティです。
特にモノレポリポジトリで共通設定をまとめた ベースの tsconfig.json を作成し、それを各プロジェクトで継承する場合に使われます。
compilerOptions
TypeScript のコンパイル動作を制御します。一部だけ紹介します。
オプション | 説明 | 例 |
---|---|---|
target |
トランスパイル後の JavaScript のバージョンを指定。 |
"ESNext" , "ES2023"
|
module |
モジュールの形式を指定(Node.js 用なら "CommonJS" , ESM 用なら "ESNext" )。 |
"CommonJS" ,"ESNext"
|
moduleResolution |
モジュール解決方法を指定。 |
"Node" ,"NodeNext"
|
strict |
厳密な型チェックを有効化。複数の設定をまとめてオンにする便利なオプション。 | true |
outDir |
生成される JavaScript の出力先ディレクトリを指定。 | "dist" |
rootDir |
ソースファイルのルートディレクトリを指定。 | "src" |
compilerOptions
には型チェックに関する設定やモジュール解決に関する設定、型定義ファイルやJavaScriptファイルをどのように出力するかの設定などの様々な設定があります。これらの設定を使うことで、プロジェクトごとに統一したルールを適用し、型安全性やモジュール管理、出力コードのフォーマットを細かく調整できます。
参考
実際に tsconfig.json に従って TypeScript をコンパイルしてみます。
① 以下コマンドで tsconfig.json を作成します。
$ tsc --init
このようなディレクトリ構成です。
.
├── node_modules
├── package-lock.json
├── package.json
├── src
│ └── greet.ts
└── tsconfig.json
② tsconfig.json の中身を記述します。
{
"compilerOptions": {
"target": "ESNext", // トランスパイル後の JavaScript のバージョンを指定
"module": "NodeNext", // モジュール形式を指定
"moduleResolution": "NodeNext", // モジュール解決方法を指定
"outDir": "dist", // 出力先ディレクトリを指定
"rootDir": "src" // ソースファイルのルートディレクトリを指定
},
"include": ["src/**/*"], // コンパイル対象ファイルを指定
"exclude": ["node_modules", "dist"] // 除外するディレクトリを指定
}
③ TypeScript をコンパイルします。
$ tsc
"outDir": "dist"
の設定に従ってdist
ファイル配下にJavaScriptファイルが出力されました。
target
を古いもの(ES5)に変更して TypeScript をコンパイルしてみます。
続いて① tsconfig.json の中身を記述します。
{
"compilerOptions": {
- "target": "ESNext", // トランスパイル後の JavaScript のバージョンを指定
+ "target": "ES5", // トランスパイル後の JavaScript のバージョンを指定 (ES5に変更)
"module": "ESNext", // モジュール形式を指定
"moduleResolution": "NodeNext", // モジュール解決方法を指定
"outDir": "dist", // 出力先ディレクトリを指定
"rootDir": "src" // ソースファイルのルートディレクトリを指定
},
"include": ["src/**/*"], // コンパイル対象ファイルを指定
"exclude": ["node_modules", "dist"] // 除外するディレクトリを指定
}
② TypeScript をコンパイルします。
$ tsc
ES5 は古い JavaScript バージョンで、アロー関数や let
/ const
、テンプレートリテラルなどを含まない仕様です。そのため、出力されたgreet.js
は以下のように変換されて出力されます。
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var greet = function (name) {
return "Hello, ".concat(name, "!");
};
var name = "TypeScript";
console.log(greet(name));
-
const
がvar
に変換 - アロー関数 (=>) が通常の関数 (function) に変換
-
${name}
などのテンプレートリテラルが"Hello, " + name + "!"
のように文字列結合に変換
開発時は TypeScript を直接実行するツールを用いる
TypeScript ファイルをtsc
でコンパイルしてから生成された JavaScript ファイルをnode
で実行するのは、毎回手動で行うと手間がかかります。開発時には、このプロセスを簡略化するために、ts-node
やtsx
のような TypeScript ファイルをコンパイルせずに直接実行できるツールを利用すると便利です。
tsx
をインストールします。
$ npm install tsx --save-dev
package.json
のscriptsに記載します。
{
"name": "typescript-compile",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
+ "dev": "tsx watch src/index.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"typescript": "^5.6.3"
},
"devDependencies": {
"tsx": "^4.19.2"
}
}
src/index.ts
ファイルの中身は以下です。
const greet = (name: string): string => {
return `Hello, ${name}!`;
};
const name = "TypeScript";
console.log(greet(name));
実行します。
$ npm run dev
ターミナルにHello, TypeScript!
が表示されました。
src/index.ts
ファイルの中身を以下のように変更してみます。
const greet = (name: string): string => {
- return `Hello, ${name}!`;
+ return `こんにちは, ${name}!`;
};
const name = "TypeScript";
console.log(greet(name));
変更を保存すると、リアルタイムでこんにちは, TypeScript!
と表示されました。
まとめ
- TypeScript は開発用のコードであり、そのままでは Node.js で実行できないため、JavaScriptに変換(コンパイル)する必要がある。
- tsconfig.json とは TypeScript から JavaScript にコンパイルするための設定ファイル。
- 開発時には、このプロセスを簡略化するために、
tsx
のような TypeScript ファイルをコンパイルせずに直接実行できるツールを利用すると開発効率が上がる。
既存のプロジェクトに途中から入っているとなんとなくで TypeScript 開発ができてしまうのでしっかりと理解する良い機会になりました。(間違っていたら教えてください...)
次回はCommonJSとESModulesについて書きたいと思います!
Discussion