【Heroku】Node.js × TypeScript で作成した API を Heroku にデプロイする。（なるべくCLIは使わない）

<!-- ============================================== -->
# 概要
<!-- ============================================== -->
表題の通り、Node.jsで作成したAPIを**Heroku**にデプロイする工程をまとめました。
CLIが苦手なので、なるべく使わない方向でデプロイします。

<!-- ============================================== -->
# 環境
<!-- ============================================== -->
- Windows10
- VSCode

グローバル環境に以下をインストールしているものとします。

- Node.js（npm）
- TypeScript

<!-- ============================================== -->
# API を作成する
<!-- ============================================== -->
Node.js、Express、TypeScriptを使用して、APIを作成します。
Herokuにデプロイすることが目的なので、単純なAPIです。

### パッケージ インストール
任意のプロジェクトフォルダを作成します。
VSCodeでプロジェクトフォルダを開いて、ターミナルから必要なパッケージをインストールします。

まず、package.jsonを作成します。

```.:ターミナル
npm init -y
```
scriptsの項目を以下のように変更します。

```package.json
"scripts": {
	"dev": "nodemon dist/main.js"
}
```

パッケージをインストールします。

```.:ターミナル
npm i express
npm i -D @types/node @types/express nodemon
```
`nodemon`：jsファイルの変更に応じて、サーバーを再起動してくれるパッケージ

### tsconfig.json
ターミナルで以下を実行し、tsconfig.jsonが作成します。

```.:ターミナル
tsc --init
```
```.js:tsconfig.json
{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2018", 
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",

    /* Strict Type-Checking Options */
    "strict": true,

    /* Module Resolution Options */
    "moduleResolution": "Node",
    "esModuleInterop": true,

    /* Experimental Options */
    "experimentalDecorators": true,

    /* Advanced Options */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
```
tsファイルを`src`フォルダに、コンパイル後のjsファイルを`dist`フォルダに格納する設定にしています。

### コーディング

```src/main.ts
import express from 'express';

const app = express()
// jsonデータを扱う
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// テスト用のエンドポイント
app.get('/', (req, res) => {
	res.status(200).send({ message: 'hello, api sever!' })
})

// サーバー接続
const port = process.env.PORT || 3001
app.listen(port, () => {
	console.log('listen on port:', port)
})
```
今回は使いませんが、jsonデータを受け取れるように設定しています。
ポートは、ローカル環境では`3001`（3000はクライアントアプリで使うので）、本番環境ではデプロイ先に依存するように設定します。

### 起動確認
TypeScriptを使う場合、サーバーを起動する前にJavaScriptファイルにコンパイルする必要があります。
ターミナルで以下を実行します。

```.:ターミナル1
tsc -w
```
`-w`：tsファイルの変更を監視して、変更があれば自動的にjsファイルに変換する
停止する場合は、`Ctrl + C`

ターミナルをもう一つ追加して、以下を実行します。

```.:ターミナル2
npm run dev
```
このようにすることで、
<font color="Blue">tsファイルを変更する → jsファイルが生成される（変更される） → サーバーが再起動する</font>
という環境ができます。

postmanやブラウザでローカルホストにアクセスして、メッセージが返ってくればOKです。

```
http://localhost:3001
```
```.json:
{
	"message": "hello, api sever!"
}
```

<!-- ============================================== -->
# Heroku にデプロイする
<!-- ============================================== -->
### 設定ファイルの追加・変更
Herokuにデプロイするための設定を追加します。

- **package.json**

```package.json
{
	"name": "heroku-node-demo",
	"version": "1.0.0",
	"description": "",
	"main": "dist/main.js",
	"engines": {
		"node": "14.17.x",
		"npm": "7.6.3"
	},
	"scripts": {
		"start": "node dist/main.js",
		"dev": "nodemon dist/main.js"
	},
	"author": "",
	"license": "ISC",
	"dependencies": {
		"express": "^4.17.1"
	},
	"devDependencies": {
		"@types/express": "^4.17.13",
		"@types/node": "^16.4.10",
		"nodemon": "^2.0.12"
	}
}
```
`main`、`engines`、`scripts`の項目を変更・追加します。
`engines`で、追記するnode、npmバージョンは、以下のコマンドで確認します。

```.:ターミナル
node -v
> v14.17.1
npm -v
> 7.6.3
```
nodeのバージョンは、パッチバージョンをそのまま追記するとHerokuのデプロイがうまくいかないことがあります。
その場合は、`14.17.x`のように記述します。

- **Procfile**

Herokuのエントリーポイント設定ファイル

```.txt:Procfile
web: npm start
```
`npm start`なので、`node dist/main.js`が実行されます。

### GitHub
HerokuプロジェクトをGitHubリポジトリと関連付けるために、作成したプロジェクトをGitHubに登録します。
GitHubへの登録方法は、まとめている方が多いので割愛します。以下などを参照にしてください。

https://bgt-48.blogspot.com/2019/12/visual-studio-codegit.html

### Herokuへのデプロイ
- **Heroku のアカウントを作成して、ダッシュボードを開きます。**

https://dashboard.heroku.com/apps

- **Crete new app でプロジェクトを作成します。**

![h1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/2161de94-a06e-68cb-44a9-7bb2e1247bcd.png)

- **App name を選択して、Create app を押します。**

![h2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/60c84c03-d8ab-fd42-a639-9279f1c5f296.png)
`App name`は、ユニークな名前である必要あります。
`region`は、アメリカかヨーロッパのどちらかなので、アメリカにします。

- **デプロイ方法で GitHub を選択し、作成したリポジトリを検索・選択します。**

![h3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/4db7b51a-c36f-bb15-e193-63caa1e7137d.png)

- **Deploy Branch を押すと、デプロイが始まります。**

![h4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/225a3d34-3522-3540-f0de-3c08bc0ac6c0.png)
`[Enable Automatic Deploys]`を押すと、GitHubのmainブランチに変更があったタイミングで、自動的にデプロイが行われるようになります。toggleボタンになっているので、好きにオンオフできます。

<!-- ============================================== -->
# 成果物
<!-- ============================================== -->

https://github.com/nemutas/heroku-node-api-demo

<!-- ============================================== -->
# Tips
<!-- ============================================== -->
### デバッグ方法
ローカルサーバーでのデバッグ方法についてまとめいてます。

https://qiita.com/nemutas/items/b6dcaea6aab9f64ecbe4