Open3

Amplify Console で Next.js SSR を monorepo

doutoridoutori

Amplify Console はフルマネージドな静的ホスティングサービス。
フルマネージドなだけあって、 AWS の管理画面から対象とするリポジトリを選択するだけであっという間にホスティングまで賄ってしまう。
https://aws.amazon.com/jp/amplify/hosting/

Amplify Console は monorepo にも対応している。
https://aws.amazon.com/jp/blogs/mobile/set-up-continuous-deployment-and-hosting-for-a-monorepo-with-aws-amplify-console/

また、 Next.js の SSR にも対応している。
https://aws.amazon.com/jp/blogs/mobile/host-a-next-js-ssr-app-with-real-time-data-on-aws-amplify/

doutoridoutori

monorepo での組み合わせ

Nx は monorepo でアプリケーション開発を行うためのフレームワークになるのだが、これと組み合わせると Amplify Console にうまく Deploy ができない。

Next.js monorepo Amplify Console 可否
SSG npm(yarn) workspace
SSG Nx
SSR + SPA npm(yarn) workspace
SSR + SPA Nx ×

もう少し具体的に言うと、 Amplify Console はリポジトリの構成(主に package.json だと思う)から、SSG と SSR の構成かを判断して Build の処理をわけて実行している(ここら辺はフルマネージド故、完全に隠蔽されている)
SSG は完全に静的なサイトになるので単純なホスティングだが、 SSR の場合は Lambda + CloudFront + S3 のサーバレス構成になる。

https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/server-side-rendering-amplify.html#deploy-nextjs-app

monorepo の package.json

Nx を利用する場合 package.json はプロジェクトのルートに1つできるだけ。
npm (yarn) workspace や lerna などの場合は、ルートの他に monorepo 構成になっている各アプリケーション単位にも package.json が構築される。

どうも Amplify Console は、各アプリケーションのディレクトリにある package.json を見て Build 形式の判定を行なっているよう。
Nx の場合は、プロジェクトルートにしか package.json が存在しないため、 Nx で Next.js の SSR 構成でアプリケーションを構築してしまっても、対応する Build が走っていないように思える。

最近にはなるが、Issue はすでに上げられて問題提起はされているので、 Nx を利用したい場合は改善されるのを待つことになるやも...
https://github.com/aws-amplify/amplify-console/issues/1866
https://github.com/aws-amplify/amplify-console/issues/2259

doutoridoutori

Amplify Console の Issue にワークアラウンド的な解決策が出されている。

Amplify Console は、各アプリケーションのディレクトリにある package.json を見て Build 形式の判定を行なっているよう。
Nx の場合は、プロジェクトルートにしか package.json が存在しないため

やはり原因はこれのようで、各モノレポのアプリケーションのルートに以下の package.json を置くことで Build 方式を SSR 用に切り替えさせて対応する。

npm や yarn の workspace の構成に近い形になり、本来の Nx のフレームワークの出力からは少し一手間加える形になる。

package.json
{
    "version": "0.1.0",
    "scripts": {
      "dev": "next dev",
      "build": "next build",
      "start": "next start"
    },
    "dependencies": {
      "next": "^11.0.0"
    }
}
amplify.yaml
version: 1
applications:
  - frontend:
      phases:
        build:
          commands: 
            # This step will build app with Nx framework 
            - cd ../../
            - npm install
            - npm run build:prod
            # This step will build/update SSR resources(S3, Cloudfront, Lambda@Edge)
            - cd apps/mono-repro
            - npm install
      artifacts:
        baseDirectory: ../../dist/apps/mono-repro/.next
        files:
          - '**/*'
      cache:
        paths: 
            - node_modules/**/*
    appRoot: apps/mono-repro