Node.js + Express + Typescriptでプロジェクト作成


ExpressとTypescriptを使ってプロジェクトを立ち上げる手順を書き残します。
コードは[GitHub🐱](https://github.com/hinahinako/node-typescript-sample)で公開しています。

## 🗂 ディレクトリ構成
- 以下のようになる予定です。

```
- src
  - server.ts    ・・・Typescriptで実際に記述するコード
- dist
  - server.js    ・・・トランスパイル後に生成されるjsファイル
- tsconfig.json
- package.json
- package-lock.json
- node_modules
```

- src配下に`.ts`ファイル
- dist配下に`.js`ファイル

が生成される想定です。


## 🌱 プロジェクト作成

以下のコマンドを実行します。
```
mkdir myapp
cd myapp
npm init -y
```

以下のようにプロジェクトができます。
```

{
  "name": "myapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```

## 📚 パッケージをインストール
必要なパッケージをインストールします。
```
npm i typescript ts-node express
```

```
npm i @types/node @types/express -D
```

以下のパッケージがインストールされます。
- [typescript](https://www.npmjs.com/package/typescript)
- [ts-node](https://www.npmjs.com/package/ts-node)
- [express](https://www.npmjs.com/package/express)

## 🫐 Typescriptの設定

tsconfig.jsonを生成します。
```
npx tsc --init
```

`include`を追加してコンパイル対象ファイルを明記します。
```json
{
  "compilerOptions": {
    ...略
  },
  "include": ["./src/**/*"],
}
```
ルート直下にsrcディレクトリとdistディレクトリも作っておきます。
```
mkdir src
mkdir dist
```


## 🔧 コードを用意

### server.tsの配置
src配下にserver.tsを作成し、以下をコピペします。
```js
import express from "express";
const app: express.Express = express();

// サーバ起動
app.listen(3000, () => {
  console.log("Start on port 3000.");
});

// GETテスト
app.get("/test", (req: express.Request, res: express.Response) => {
  res.send("OK");
});

```

### 起動コマンドを追加
nodemonという便利なツールを使います。
使用は必須ではありませんが、ファイル変更を検知したら自動的にサーバを再起動してくれる超便利なやつなので是非使ってください。
グローバルインストールしておきます。
```
npm install -g nodemon
```

package.jsonのscriptsに `"ts"` コマンドを追加します。

```json
{
  ...

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "ts": "nodemon --files --watch 'src/**/*.ts' --exec 'ts-node' src/server.ts"
  },

  ...
}
```

`--files --watch 'src/**/*.ts'` でsrcディレクトリ配下のファイル変更を検知し、
`--exec 'ts-node' src/server.ts` で、上の変更があればts-nodeを実行する、
という命令になっています。


## 🏃‍♀️ ts-nodeで動かしてみる

ターミナルで以下を実行します
```
npm run ts
```

ブラウザで以下にアクセスすると・・
```
http://localhost:3000/test
```

「OK」が表示されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284077/063219e4-5b37-76a1-d5b9-a68506104878.png)


##  🏃‍♂️ トランスパイルして動かしてみる
トランスパイルしたファイルはdist配下に入ってほしいので、tsconfig.jsonの`outDir`を明記します。
```
  "compilerOptions": {
    ...
    "outDir": "./dist"
    ...
}
```

トランスパイルします。
```
npx tsc
```

するとdistディレクトリ配下にserver.jsができていると思います。
(tsconfig.jsのoutDirを指定しなかった場合は `server.ts`と同じ階層にファイルができていると思います。)


これを実行します。
```
node ./dist/server.js
```


ブラウザで以下にアクセスしたら・・・
```
http://localhost:3000/test
```

先ほどと同じように「OK」が表示されるはずです。


## 🔍 ちなみに
トランスパイルされたjsファイルの中身は以下のようになっています。
```js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const app = (0, express_1.default)();
// サーバ起動
app.listen(3000, () => {
    console.log("Start on port 3000.");
});
// GETテスト
app.get("/test", (req, res) => {
    res.send("OK");
});
```

詳しくは理解できなかったのですが、
前半部分はES Modules(import/export)の互換性を持たせるための実装らしいです。

以上。

## 終わりに
今回はこれだけ。ほぼ最小構成です。
今後はここから
- sequelizeでDB接続
- inversifyでDI導入
- Dockerコンテナ化してECSで起動

など試してみたいと思います。