みなさんは普段Node.jsをどのように使っていますか? サーバーサイドで動くJavaScriptであるNode.jsは、Socket.IOと連携してリアルタイムなウェブコンテンツを作ったり、webpackやgulpのようなフロントエンドエンジニアのツールとして使われたりとさまざまな場面で活用されています。
Node.jsで大規模な開発をする場合、TypeScriptを採用して開発の生産効率性・保守性を上げるのもオススメです。WebStormやVisual Studio Codeを使えばコード補完が効くためプログラミングの効率が劇的に向上し、TypeScriptの静的型付けによってコンパイル時型チェックが行われるので安全性が増します。Node.jsを使って中・大規模なシステムを構築するときはTypeScriptを検討するといいでしょう。
今回はNode.jsをTypeScriptで記述する基本設定から、TypeScriptの外部モジュール機能を使ってウェブサーバーを立ち上げる手順までを紹介します。今回のサンプルコードはGitHubで公開してるので、ダウンロードして読み進めてください。
Node.jsとTypeScriptをインストールしよう
今回解説するセットアップの手順は次の2分ほどの動画に記録しています。まっさらの状態から、TypeScriptの開発環境を構築し、ウェブサーバーを立ち上げるまでの手順を解説。記事を読み進めてわからない箇所があったら動画を参照ください。
TypeScript環境の構築
使用環境を整えましょう。まずNode.jsをインストールします。Node.jsは公式サイトのインストーラーを使って手順にしたがってインストールします。インストール後コマンドライン(macOSだとターミナル。app、Windowsだとコマンドプロンプト)にてnode -v
と実行し、Nodeのバージョンが表示されていればインストール成功です。
つづいて、作業フォルダーで次のコマンドを入力します。すると、package.json
ファイルが作られます。
npm init -y
つづいて、TypeScriptをインストールします。コマンドラインから以下のコマンドを実行します。
npm i -D typescript
※コマンドのi
はモジュールをインストールするコマンドinstall
のショートカット、-D
はモジュールのインストール場所(devDependencies)を指定する--save-dev
のショートカットです。
また、Node.jsの型定義ファイルを用意しておきます。TypeScriptだけだとNode.jsのモジュールにどんなメソッドや変数があるかという情報を持っていないため、コンパイルが通りません。型定義ファイルを読み込むとWebStorm等のTypeScriptのコーディングに対応したエディターでコード補完が効くようになるというメリットもあります。
npm i @types/node
これでpackage.json
ファイルの中身が仕上がりました。npm scriptsにはTypeScriptのビルドコマンドも記述しておくといいでしょう。npm scriptsについては記事「npm-scriptsのタスク実行方法」を参照ください。
▼package.json ファイル
{
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
},
"devDependencies": {
"typescript": "^4.0.5"
},
"dependencies": {
"@types/node": "^14.14.7"
}
}
つづいて、TypeScriptのコンパイル設定もしておきましょう。package.json
と同階層に、tsconfig.json
ファイルを次の内容で用意します。
▼tsconfig.json ファイル
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"sourceMap": true,
"types": [
"node"
]
},
"exclude": [
"node_modules"
]
}
以上でNode.jsをTypeScriptで記述する環境の構築は終了です。
TypeScriptファイルの作成
Node.jsをTypeScriptで記述していきましょう。さきほど作成したフォルダーの中に新規テキストファイルを作成してapp.ts
という名前にします。app.ts
の中にテキストエディターで以下のようなコードを記述します。
console.log("Hello! Node.js × TypeScript");
コマンドラインでこのpackage.json
があるフォルダーに移動してTypeScriptをコンパイルするためのnpm run build
コマンドを実行するとTypeScriptのapp.ts
がJavaScriptのapp.js
にコンパイルされます。
# macOSでの移動(Windowsの場合は読み替えてください)
cd /Users/MyName/sample_server
# app.tsのコンパイル
npm run build
app.js
ができたらそれをNode.jsとして実行ます。コマンドラインでNode.jsを実行するためのnode
コマンドを実行します。コマンドラインに「Hello! Node.js × TypeScript」と出力されるのが確認できます。
node sample1/app.js
処理を機能毎にひとまとめにしてクラス化しておくとコードの見通しがよくなります。上記の処理をクラス化しておきましょう。
// classを指定してクラス化
class Main {
// コンストラクター
constructor() {
console.log("Hello! Node.js × TypeScript from Class");
}
}
// Mainクラスのインスタンスを作る
const main = new Main();
(サンプル:TypeScriptで記述したNode.jsで文字列出力)
httpモジュールを使ってhttpサーバーを立ててみよう
Node.jsをTypeScriptで記述して簡単なhttpサーバーを立ててみましょう。ここで作るのはブラウザでアクセスがあったら文字列を表示するシンプルなhttpサーバーです。Node.jsにおけるさまざまな処理は「モジュール」という単位に分けられています。たとえばhttpサーバーを立てるための機能はhttpモジュール、ファイルの読み書きを行うための機能はfsモジュールにて定義されています。TypeScriptでこのようなモジュールを使用するためにはimport文を使います。
import * as http from "http";
httpサーバーを設定するcreateServer()
メソッド、サーバーを起動してリクエストを待ち受け状態にするlisten()
メソッドを使って、httpサーバーは以下のようにして構築できます。
import * as http from "http";
class Main {
constructor() {
// httpサーバーを設定する
const server: http.Server = http.createServer(
(request: http.IncomingMessage, response: http.ServerResponse) =>
this.requestHandler(request, response)
);
// サーバーを起動してリクエストを待ち受け状態にする
server.listen("5000");
// ログを出力する
console.log("http://localhost:5000 へアクセスください");
}
/**
* サーバーにリクエストがあった時に実行される関数
*/
private requestHandler(
request: http.IncomingMessage,
response: http.ServerResponse
): void {
response.end("Hello! Node.js with TypeScript");
}
}
new Main();
imort
文とrequire()
メソッドを使ってモジュールを読み込んだ場合、モジュールはcommonjs仕様に則る必要があります。そのため、tsconfig.jsonファイルで"module": "commonjs"
と指定していました。
コンパイルが終了したらコマンドラインからnode sample3/app.js
コマンドを実行し、ブラウザでhttp://localhost:5000にアクセスすると「Hello! Node.js with TypeScript」と表示されています。これはNode.jsによってhttpサーバーが起動してクライアントのリクエストを待っている状態であることを示します。この待ち受け状態はショートカットCtrl+Cキーで停止できます。
これで簡易なhttpサーバーが構築できましたが、実際のサーバーはリクエストに応じてHTMLファイルや画像ファイルを返す処理(ルーティング処理)が必要になります。参考までに、ルーティング処理のサンプルコードをGitHubにアップしています。
※モジュールには、CommonJS方式とAMD方式、ES Modulesなどさまざまな種類があります。CommonJSはNode.jsで外部モジュールを扱う方式であり、Node.jsではCommonJSを使うのが一般的です。
外部モジュールを作って長い処理を複数のファイルに分けよう
処理が増える毎に長くなっていくスクリプトの見通しを良くするためには、機能毎に処理を分けて外部ファイル化してオリジナルの外部モジュールをつくるといいです。上記のhttpサーバーを立てる処理をServerAPI
クラスという名前で定義し、app.ts
と同じ階層にserverModule.ts
という外部ファイルを作ってapp.ts
のMain
クラスから読み込みます。ここで注意したいのは、外部から読み込まれるクラスにはclassの前にexportを指定する必要があることです。
▼serverModule.ts
import * as http from "http";
export class ServerAPI {
public initServer(): void {
const server = http.createServer(
(request: http.IncomingMessage, response: http.ServerResponse) =>
this.requestHandler(request, response)
);
server.listen("5000");
// ログを出力する
console.log("http://localhost:5000 へアクセスください");
}
/**
* サーバーにリクエストがあった時に実行される関数
*/
private requestHandler(
request: http.IncomingMessage,
response: http.ServerResponse
): void {
response.end("Call From ServeAPI Class");
}
}
これを読み込む側のapp.tsの処理ですが、Node.jsのモジュール読み込みと同じようにimport
文を使います。
▼app.ts
import { ServerAPI } from "./serverModule";
class Main {
constructor() {
// serverModuleの中のServerAPIクラスのインスタンスを作成
const serverAPI = new ServerAPI();
// ServerAPIの関数を実行
serverAPI.initServer();
}
}
new Main();
このファイルをコンパイルし実行します。http://localhost:5000にアクセスして「Call From ServeAPI Class」と表示されていたら成功です(※)。外部ファイルserverModule.ts
に記述したクラスをメインのクラスから実行できました。
※ サーバーを複数起動しようとするとうまくいかないことがあるので、その場合は不要なサーバーをショートカットCtrl+Cキーで停止したりコマンドラインやブラウザの再起動を試してみてください。
最後に
Node.jsをTypeScriptで記述すると静的型付けの恩恵に預かることができ、大規模な開発やメンテナンスがやりやすくなります。
この他にも、記事「最新版TypeScript+webpackの環境構築まとめ」や記事「HTML5デモを作って分かったCreateJSとTypeScriptでの効率的な開発手法」でTypeScriptの使い方を紹介しています。あわせてご覧ください。
※この記事が公開されたのは5年12ヶ月前ですが、 2020年11月に内容をメンテナンスしています。