Deploy Next.js Monorepo using Turborepo on AWS Amplify Gen 2

AWS Amplify Gen 2 (Amplify) について。

この記事を書くにあたり、前提は以下の通り。
- Amplify の検証中です。
- Monorepo を検討中です。
- 開発言語は Monorepo 全体で TypeScript を使います。
- Monorepo tool の Nx[^2] を検証済みです。

Nx の場合、 Amplify の Framework 自動検出で課題がある。

Amplify の挙動から root の `package.json` をもとに Framework を判定しているように見える。5月22日時点。

しかし、Monorepo の場合、Frontend と Backend で異なる Framework を選択することも考えられる。

そこで Turborepo[^1] を検証する。

https://turbo.build/repo

Code はこちら。

https://github.com/danny-yamamoto/coconut

## tl;dr
- Turborepo で問題なく構築できた。（5月22日時点）
- Amplify の Framework 自動検出の課題についてはサポートに問い合わせ中。
- Nx でも Deploy の順番と `package.json` の修正を行えば、Deploy は可能。今のやり方は、どちらかというと Hack ぽくなるので解決策を探したい。

## Create a workspace
- Package manager は `npm` を選択。
- `pnpm` の場合は、Amplify の build で一工夫必要らしい。[^4]
- `coconut` と名付けたのは、リンゴ飴の Flavor から。この数年、家族がリンゴ飴にハマっている。どうでもいい話。🍎
- Workspace の作成は Quickstart[^5] を参照。

```bash
vscode ➜ /workspaces/stool/tourborepo (main) $ npx create-turbo@latest
Need to install the following packages:
create-turbo@1.13.3
Ok to proceed? (y) y

>>> TURBOREPO

>>> Welcome to Turborepo! Let's get you set up with a new codebase.

? Where would you like to create your turborepo? coconut
? Which package manager do you want to use? npm workspaces

Downloading files. This might take a moment.

>>> Created a new Turborepo with the following:

apps
 - apps/docs
 - apps/web
packages
 - packages/eslint-config
 - packages/typescript-config
 - packages/ui

Installing packages. This might take a couple of minutes.

>>> Success! Created a new Turborepo at "coconut".
Inside that directory, you can run several commands:

  npm run build
     Build all apps and packages

  npm run dev
     Develop all apps and packages

  npm run lint
     Lint all apps and packages

Turborepo will cache locally by default. For an additional
speed boost, enable Remote Caching with Vercel by
entering the following command:

  npx turbo login

We suggest that you begin by typing:

  cd coconut
  npx turbo login

vscode ➜ /workspaces/stool/tourborepo (main) $ 
```

## Frontend
- Generate された `web` App をそのまま Deploy する。

### Amplify Manual Settings
- Amplify の Offical docs[^3] を参考にする。
- `workspace` に `web` Project を指定する。
```bash
npm install --save-dev @aws-amplify/backend@latest @aws-amplify/backend-cli@latest typescript --workspace=web
npm install --save-dev @aws-amplify/backend-cli aws-amplify @aws-amplify/ui-react --workspace=web
```

### Run Next.js
```bash
cd /workspaces/coconut/apps/web
npm run dev
```

```bash
node ➜ /workspaces/coconut/apps/web (main) $ npm run dev

> web@1.0.0 dev
> next dev

  ▲ Next.js 14.2.3
  - Local:        http://localhost:3000

 ✓ Starting...
 ✓ Ready in 6.2s
 ○ Compiling / ...
(node:29092) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
 ✓ Compiled / in 7.2s (552 modules)
 GET / 200 in 7416ms
```

![nextjs](/images/d65ad82ffea052-a.png)

## Backend
### Setup NestJS
- CLI で Project を作成する。
```bash
cd /workspaces/coconut/
npm i -g @nestjs/cli
nest new backend
```

### Amplify Manual Settings
- `workspace` に `backend` Project を指定する。
```bash
npm install --save-dev @aws-amplify/backend@latest @aws-amplify/backend-cli@latest typescript --workspace=backend
npm install --save-dev @aws-amplify/backend-cli aws-amplify @aws-amplify/ui-react --workspace=backend
```

### Run NestJS
```bash
cd /workspaces/coconut/apps/backend
npm run start
```

```bash
node ➜ /workspaces/coconut/apps/backend (main) $ npm run start

> backend@0.0.1 start
> nest start

[Nest] 61511  - 05/22/2024, 10:40:58 AM     LOG [NestFactory] Starting Nest application...
[Nest] 61511  - 05/22/2024, 10:40:58 AM     LOG [InstanceLoader] AppModule dependencies initialized +23ms
[Nest] 61511  - 05/22/2024, 10:40:58 AM     LOG [RoutesResolver] AppController {/}: +45ms
[Nest] 61511  - 05/22/2024, 10:40:58 AM     LOG [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 61511  - 05/22/2024, 10:40:58 AM     LOG [NestApplication] Nest application successfully started +3ms
```

## Deploy to Amplify
- Amplify の Console から Deploy する。Nx の場合とは異なり、Framework の自動判定は問題ない。
- Nx の場合は、`artifacts` `buildPath` の修正が必要だった。

```yaml:Frontend | amplify.yml
version: 1
applications:
  - backend:
      phases:
        build:
          commands:
            - npm ci --cache .npm --prefer-offline
            - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
    frontend:
      phases:
        preBuild:
          commands:
            - npx npm install
        build:
          commands:
            - npx turbo run build --filter=web
      artifacts:
        baseDirectory: .next
        files:
          - '**/*'
      cache:
        paths:
          - .next/cache/**/*
          - node_modules/**/*
      buildPath: apps/web
    appRoot: apps/web
```

```yaml:Backend | amplify.yml
version: 1
applications:
  - backend:
      phases:
        build:
          commands:
            - npm ci --cache .npm --prefer-offline
            - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
    frontend:
      phases:
        preBuild:
          commands:
            - npx npm install
        build:
          commands:
            - npx turbo run build --filter=backend
      artifacts:
        baseDirectory: dist
        files:
          - '**/*'
      cache:
        paths:
          - node_modules/**/*
      buildPath: apps/backend
    appRoot: apps/backend
```

## BTW
最近はこの考え方になった。

自分に集中する。自分に期待する。

他人に期待しない。他人が出来ることを知る。他者を労う。

目指す方向が同じ人と成果を祝いながら時には軌道修正し目標に向かう。

要するに自分がコントロール出来ることに集中すること。


[^1]: https://turbo.build/repo
[^2]: https://nx.dev/
[^3]: https://docs.amplify.aws/react/start/manual-installation/#manual-setup
[^4]: https://docs.aws.amazon.com/amplify/latest/userguide/monorepo-configuration.html#turborepo-pnpm-monorepo-configuration
[^5]: https://turbo.build/repo/docs/getting-started/create-new