Next.js15 App RouterをCloudflare Pagesにデプロイする

:::note info
2025年1月16日現在での方法です。
:::

# はじめに
いつもはNext.jsのプロジェクトをVercelにデプロイしていたのですが、将来的に広告を入れる可能性を考え、Cloudflare Pagesにデプロイしてみました。

エラーなどが出て大変だったので手順をメモしておきます。

:::note warn
内容や言葉遣いが誤っている可能性があります。
:::

# 環境
- Next.js v15.1.4
- @cloudflare/next-on-pages v1.13.7
- yarn v4.6.0
- node.js v20.11.1

:::note info
Node.jsやNPM、Yarnの環境や、基本的なNext.jsの知識についてはある前提で進めます。
:::

# 手順
## 1. Next.jsプロジェクトを作成する
```shell
npx create-next-app@latest cloudflare-sample-app
```

## 2. ランタイムをEdgeに変更
Cloudflare PagesではランタイムはNode.jsではなくEdgeが使用されます。
サーバーサイドのファイル（page.tsxやroute.ts）に以下のコードを追加します。
```typescript
export const runtime = "edge";
```

## 3. @cloudflare/next-on-pagesをインストール
```shell
yarn add -D @cloudflare/next-on-pages
```
## 4. wrangler.tomlファイルを作成
```toml wrangler.toml
name = "my-app"
compatibility_date = "2024-07-29"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".vercel/output/static"
```
ドキュメントには上記のようになっていますが、私はエラーが起きたため、`compatibility_date`を`"2024-09-23"`に変更しました。
また、`name`は適宜変更してください。（後ほど作るCloudflareのプロジェクト名と同じにしておくと便利です。）

## 5. GithubとNext.jsプロジェクトを連携する
作成したNext.jsプロジェクトをGithubのリポジトリの`main`ブランチにプッシュしてください。

## 6. Cloudflareのプロジェクトを作成する
Cloudflareのダッシュボードで、左のメニューから、`Compute(Workers)`->`Workers & Pages'を開き、`作成`ボタンを押します。

![ScreenShot 2025-01-16 20.16.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871960/a509380c-265d-1704-3fa9-6f7caa37a093.png)

`Pages`のタブを開き、`Gitに接続`ボタンを押します。

![ScreenShot 2025-01-16 20.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871960/26e360b7-580d-f10d-6e6a-76cad9a6cc65.png)

Githubと接続するとリポジトリを選べるので、先ほど作成したリポジトリを選択します。

`フレームワークプリセット`を`Next.js`にし、環境変数に以下のものを追加します
| Name | Value |
|:-:|:-:|
| NODE_VERSION | 22.12.0  |
|  YARN_VERSION | 4.6.0  |

::::note info
`NODE_VERSION`は、ビルドに使用するNode.jsのバージョンです。
デフォルトは`18.17.1`ですが、これはエラーが起こるので20以上にしておきます。
:::

::::note info
`YARN_VERSION`はローカル環境の`yarn`のバージョンに合わせてください。
`yarn.lock`ファイルの書き方がバージョンによって異なることによるデプロイ時のエラーが発生します。
:::

環境変数はプロジェクト作成後も、設定のタブから編集できます。
`production`と`preview`の2つがあるので、両方とも設定するようにしてください。
~~`preview`に設定していなくて原因がわからず2時間溶かしました。~~

これでデプロイが成功するはずです。
（しなかった場合は再デプロイしてみてください。）

# エラー達
## ✘ [ERROR] Could not resolve "async_hooks"

```
✘ [ERROR] Could not resolve "async_hooks"


    <stdin>:596:680:
      596 │ ...umerable:!0})),e);_(exports,{default:()=>N});var R=A(require("async_hooks")),S="@next/request-context",f=Symbol.for(S),C=Symbol.for("i...
          ╵                                                                 ~~~~~~~~~~~~~

  The package "async_hooks" wasn't found on the file system but is built into node. Are you trying
  to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
  ```
このサイトを参考にした。

https://github.com/cloudflare/next-on-pages/issues/908

次の2つで解決した。

1. 上に書いた通り、`wrangler.toml`の`compatibility_date`を`"2024-09-23"`にする
2. `package.json`に
    ```
    {
        // existing code
        "overrides": {
            "vercel": "$vercel"
        },
        // existing code
    }
    ```
    とかく
    

# 終わりに
かなり遠回りをしてしまい、デプロイだけで5時間くらいかかってしまいました。
もし上記の方法でうまくいかない場合はコメントで教えていただきたいです。

# 参考にしたサイト等
https://zenn.dev/microcms/articles/1b4331eca6e512#cloudflare-pages%E3%81%B8%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4

https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/get-started/

https://zenn.dev/taiyou/articles/a5d0fbdd56b766

https://zenn.dev/masa5714/scraps/547865bac885ae

https://github.com/cloudflare/next-on-pages/issues/908

https://qiita.com/u_Hoshi/items/61497e71bc59a9b2167e