みなさんは普段Node.jsをどのように使っていますか? サーバーサイドで動くJavaScriptであるNode.jsは、Socket.IOと連携してリアルタイムなウェブコンテンツを作ったり、webpackgulpのようなフロントエンドエンジニアのツールとして使われたりとさまざまな場面で活用されています。

Node.jsで大規模な開発をする場合、TypeScriptを採用して開発の生産効率性・保守性を上げるのもオススメです。WebStormVisual Studioを使えばコード補完が効くためプログラミングの効率が劇的に向上し、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 -S @types/node

-Sはモジュールのインストール場所(dependencies)を指定する--saveのショートカットです。

これでpackage.jsonファイルの中身が仕上がりました。npm scriptsにはTypeScriptのビルドコマンドも記述しておくといいでしょう。npm scriptsについては記事「npm-scriptsのタスク実行方法」を参照ください。

▼package.json ファイル

{
  "scripts": {
    "build": "tsc",
    "watch": "tsc --watch"
  },
  "devDependencies": {
    "typescript": "^2.4.2"
  },
  "dependencies": {
    "@types/node": "^8.0.20"
  }
}

つづいて、TypeScriptのコンパイル設定もしておきましょう。package.jsonと同階層に、tsconfig.jsonファイルを次の内容で用意します。

▼tsconfig.json ファイル

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2017",
    "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にコンパイルされます。

# Macでの移動(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

Node.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');
  }

  /*
  * サーバーにリクエストがあった時に実行される関数
  */
  private requestHandler(request: http.IncomingMessage,
                         response: http.ServerResponse): void {
    response.end('Hello! Node.js with TypeScript');
  }
}

const main = 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キーで停止できます

Node.jsによって文字が出力されている例

これで簡易なhttpサーバーが構築できましたが、実際のサーバーはリクエストに応じてHTMLファイルや画像ファイルを返す処理(ルーティング処理)が必要になります。参考までに、これらのルーティング処理を行ってhttpサーバーでHTMLとCSSと画像が読み込まれるサンプルコードをGitHubにアップしています。

※モジュールには、CommonJS方式とAMD方式、ES Modulesなど様々な種類があります。CommonJSはNode.jsで外部モジュールを扱う方式であり、Node.jsではCommonJSを使うのが一般的です。

外部モジュールを作って長い処理を複数のファイルに分けよう

処理が増える毎に長くなっていくスクリプトの見通しを良くするためには、機能毎に処理を分けて外部ファイル化してオリジナルの外部モジュールをつくるといいです。上記のhttpサーバーを立てる処理をServerAPIクラスという名前で定義し、app.tsと同じ階層にserverModule.tsという外部ファイルを作ってapp.tsMainクラスから読み込みます。ここで注意したいのは、外部から読み込まれるクラスには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');
  }

  /*
   * サーバーにリクエストがあった時に実行される関数
   */
  private requestHandler(request: http.IncomingMessage,
                         response: http.ServerResponse): void {
    response.end('Call From ServeAPI Class');
  }
}

これを読み込む側のapp.tsの処理ですが、Node.jsのモジュール読み込みと同じようにimport文とrequire()メソッドを使います。

▼app.ts

import {ServerAPI} from './serverModule';

class Main {
  constructor() {
    // serverModuleの中のServerAPIクラスのインスタンスを作成
    const serverAPI = new ServerAPI();
    // ServerAPIの関数を実行
    serverAPI.initServer();
  }
}

const main = new Main();

サンプル:httpサーバーの処理を外部モジュール化

このファイルをコンパイルし実行します。http://localhost:5000にアクセスして「Call From ServeAPI Class」と表示されていたら成功です(※)。外部ファイルserverModule.tsに記述したクラスをメインのクラスから実行できました。

外部モジュールの文字列が表示される例

※ サーバーを複数起動しようとするとうまくいかないことがあるので、その場合は不要なサーバーをショートカットCtrl+Cキーで停止したりコマンドラインやブラウザの再起動を試してみてください。

最後に

Node.jsをTypeScriptで記述すると静的型付けの恩恵に預かることができ、大規模な開発やメンテナンスがやりやすくなります

この他にも、記事「最新版TypeScript 2.4+Webpack 3の環境構築まとめ」や記事「HTML5デモを作って分かったCreateJSとTypeScriptでの効率的な開発手法」でTypeScriptの使い方を紹介しています。あわせてご覧ください。

(編集部注*この記事は2015年1月30日に公開された記事を再編集したものです)