動的な Next.js を Azure App Service に Deploy する

## はじめに

とある案件の Deploy 先が Azure でした。ググると、静的な Next.js アプリを Azure Static App Service に Deploy する方法は出てきたけど、API Route を持つ Next.js アプリの Azure App Service への Deploy 方法は、あんまり見つかりませんでした。少なくとも条件がぴったり一致するようなものはなかったので、やってみました。そのまま Deploy しても動きません。

[Deploy Next.JS App on for Azure App Service](https://parveensingh.com/next-js-deployment-on-azure-app-service/)

Windows OS のサーバにペライチの静的な Next-App を Deploy する手順ですが、こちらを参考にしました。今回は、Linux サーバに、最終的に TypeScript で API Route も追加した Next App を Deploy します。

## Local 実行環境など
OS: MacOS Monterey Version 12.1
node.js: v16.13.1
yarn: 1.22.17
VSCode: 1.63.2

next: 12.0.8

## 手順

1. Azure 管理画面で、App Service のインスタンスを作る
1. 適当な Next-App を作る
1. server.js を追加する
1. VS Code から Deploy する

最初は、github と接続してやってたんですが、あまりにも時間がかかるので、やめました。今回は Deploy して動くことを確認するのが目的なので、VS Code からやります。

## Azure 管理画面で App Service を立ち上げる

こちらは特に注意点はないので、割愛。Node.js のバージョンを使ってるものにしてください。今回は 16。

## 適当な Next-App を作る

まずは、参考にした記事と同じものをつくります。記事にある example の URL は移動していました。

```bash
$ npx create-next-app next-app-js --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
```

```npm run dev```, ```npm run build``` などして問題なく動くことを確認します。

## server.js を追加する

ドキュメントルートに以下を追加します。

```javascript:server.js
const { createServer } = require("http");
const next = require("next");

const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  createServer((req, res) => {
    handle(req, res);
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});

```

記事では、web.config も設定していますが、IIS は使わないので必要ないです。環境変数の Node のバージョンもいらないです。

## VS Code から Deploy する

Azure App Service の Extension をインストールし、リソースが確認できるようにセットアップしてください。後は、Deploy to Web App を選ぶだけです。

![Screen Shot 2022-01-31 at 17.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/1204c719-08f1-3c73-c73c-9c812f2a1c16.png)

1〜2分で反映されます。

![Screen Shot 2022-01-31 at 11.46.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/220a788c-3ae2-2576-e3d1-bd44d0a5d68b.png)


Azure Portal のデプロイセンターのログからも成功したか失敗したか確認できます。

これだけか…というくらいアッサリ Deploy できました！

## TypeScript にして API Route も追加してみる

前述のサンプルは Static なので、API Route もちゃんと動くか確認します。
いつも yarn なので、yarn にて。

```bash
$ yarn create next-app next-app-ts --typescript
```

これで出来上がったものに、先程の ```server.js``` を放り込みます。
ここで出来上がる ```pages/api/hello.ts``` は、John Doe って固定のテキストを返すだけなので、JavaScript になんかさせる API を適当に作って入れたいと思います。
今回は、乱数を発生させて返すだけの簡単なものにしました。

```typescript:pages/api/mathrand.ts
import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
  number: number
}

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  const mathrand = Math.random();
  res.status(200).json({ number: mathrand })
}
```

この状態で build すると、

```bash
$ yarn build
yarn run v1.22.17
$ next build
info  - Checking validity of types
info  - Creating an optimized production build
info  - Compiled successfully
info  - Collecting page data
info  - Generating static pages (3/3)
info  - Finalizing page optimization

Page                                       Size     First Load JS
┌ ○ /                                      5.45 kB        76.5 kB
├   └ css/149b18973e5508c7.css             655 B
├ ○ /404                                   194 B          71.3 kB
├ λ /api/hello                             0 B            71.1 kB
└ λ /api/mathrand                          0 B            71.1 kB
+ First Load JS shared by all              71.1 kB
  ├ chunks/framework-6e4ba497ae0c8a3f.js   42 kB
  ├ chunks/main-a56127814584ab09.js        26.9 kB
  ├ chunks/pages/_app-ba0d1cdf43a37972.js  1.37 kB
  └ chunks/webpack-69bfa6990bb9e155.js     769 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
```

こんな感じになります。server-side と static の両方が含まれた Next App の完成。先程と同様に VS Code から Deploy します。

終わったら、POSTMAN などで叩いてみます。
![Screen Shot 2022-01-31 at 17.56.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/29952dd2-1f99-9b53-da27-58e10c11effd.png)

ちゃんと動きました。


一点注意としては、```.env``` がアップロードされてしまうので、嫌な場合は、Deploy 作業中にできる ```.vscode/settings.json``` を編集しましょう。通常は、環境変数を使うので、```.env``` がアップロードされる必要はないです。

```json:.vscode/settings.json
{
  "appService.zipIgnorePattern": [
    "node_modules{,/**}",
    ".vscode{,/**}",
    ".env{,/**}"
  ],
  "appService.defaultWebAppToDeploy": "None"
}
```

![Screen Shot 2022-01-31 at 18.15.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/a7d86fd5-79aa-f9ec-b95a-0b20d0299f3b.png)

なくなりました。他にも必要ないものは、同様にして ```settings.json``` に追加。

あとは、Pipeline の設定をしたりなどすると良いかも知れません。

なお、Next.js + TypeScript + Prisma2 + Azure MySQL + Azure Storage のアプリケーションを Deploy してみましたが、特に変更なく Deploy できました。

以上。おしまい。