Closed4

Next.js を Cloudflare Pages にデプロイする with App Router, Terraform, モノレポ

9sako69sako6

runtime 指定

サーバーコンポーネントに export const runtime = 'edge'; を追記した。

なお、parallel routes を使っており、children にあたる page.tsx がなく layout.tsx しかないルートがあったが、これにも edge 指定をする必要があった。解決のために null を返す page.tsx を置いた。

page.tsx
export const runtime = 'edge';

export default function Page() {
  return null;
}

Cloudflare Pages の作成

アプリ側の準備は一旦終了。Terraform で Cloudflare Pages を作っていく。
なお、Cloudflare のプロジェクト作成、tfstate をリモート管理するなどの設定は済み。
sops で secrets.yaml に機密情報を暗号化して保存してある。

main.tf
terraform {
  required_version = "~> 1.8.0"

  backend "gcs" {
    bucket = "example-tfstate"
    prefix = "services/example"
  }

  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }

    sops = {
      source  = "carlpett/sops"
      version = "~> 1.0"
    }
  }
}

provider "cloudflare" {}

provider "sops" {}

resource "cloudflare_pages_project" "default" {
  account_id        = data.sops_file.secrets.data["cloudflare.account_id"]
  name              = "example"
  production_branch = "main"
}
data.tf
data "sops_file" "secrets" {
  source_file = "secrets.yaml"
}
export CLOUDFLARE_EMAIL=<YOUR_EMAIL>
export CLOUDFLARE_API_KEY=<YOUR_API_KEY>
terraform init
terraform plan
terraform apply

まだデプロイされていない Pages ができた。

作成された未デプロイの Pages

9sako69sako6

ローカルでビルド

@cloudflare/next-on-pages の README を参考に進める。

npm install -D @cloudflare/next-on-pages

ローカルでビルドする。

npx @cloudflare/next-on-pages

ローカルでプレビュー

プレビュー用に localhost でアプリを立ち上げる。もろもろの動作を確認する。E2E テストが全て通ったので動作は大丈夫そう。

npx wrangler pages dev .vercel/output/static --compatibility-flag=nodejs_compat --port 3000
9sako69sako6

デプロイ

wrangler コマンドでデプロイする。

wrangler pages deploy .vercel/output/static

デプロイはできたが、ページを開くと Node.JS Compatibility Error と表示された。Cloudflare Pages 側には Next.js 用の設定をまだ何もしていないので、Terraform に戻って必要な設定を足していく。

nodejs_compat を足して terraform apply した。

main.tf
resource "cloudflare_pages_project" "default" {
  account_id        = data.sops_file.secrets.data["cloudflare.account_id"]
  name              = "example"
  production_branch = "main"

  deployment_configs {
    production {
      compatibility_flags = ["nodejs_compat"]
    }
  }
}

再度デプロイするとページが開いた。 🎉

参考

このスクラップは13日前にクローズされました