💪

monorepo構成のnextjsをamplifyへデプロイする方法

に公開

1. はじめに

Next.jsで構築したアプリをどこかしらの環境にデプロイしよう!となった時、

  • Vercel
  • Firebase Hosting
  • AWS Amplify
  • AWS S3 + Lambda

といった選択肢があると思います。

今回はAWSかつ手軽にデプロイできるという制約(?)もと、AWS Amplifyを利用してアプリケーションデプロイまでやってみました。

また最近のトレンドとしてMonorepo構成にするプロダクトも増えてきた感じもするので、Monorepo管理を想定してやってみました。

2. 技術構成

今回使用する主な技術とそのバージョン

  • NEXT.js v16
  • Nodejs v22
  • npm workspaces
  • AWS Amplify

3. ディレクトリ構成

今回のディレクトリ構成は以下のようになります

myApp/
├─ package.json              # ← npm workspaces 定義
├─ amplify.yml               # ← Amplify ビルド設定(成功したやつ)
├─ app/                      # ← Next.js アプリ(Amplify でデプロイ)
│   ├─ package.json
│   ├─ next.config.ts
│   └─ app/page.tsx
└─ packages/                 # ← 共通モジュール群
    └─ ui/
        ├─ package.json
        └─ src/
            ├─ Button.tsx
            └─ index.ts

以降、上記ディレクトリを作成する手順から解説します。

4. Monorepo構築手順

まずは Monorepo のルートディレクトリを作成します。

$ mkdir myApp && cd myApp
$ npm init -y

ルートの package.json を編集して、npm workspaces を定義します。

# package.json
{
  "name": "myApp",
  "private": true,
  "workspaces": [
    "app",
    "packages/*"
  ]
}

次にNext.jsアプリを作成します。
今回はapp/というディレクトリの下に作ることにしました。

$ npx create-next-app@latest app --ts

次に共通コンポーネントを管理するためにpackagesディレクトリを作成します。

$ mkdir -p packages/ui/src
$ cd packages/ui
$ npm init -y

packages/ui/package.jsonは以下の通りです。

{
  "name": "@packages/ui",
  "version": "0.0.1",
  "main": "src/index.ts",
  "types": "src/index.ts",
  "private": true
}

今回はお試し実装なので、Buttonコンポーネントだけ作っておきます。

// packages/ui/src/Button.tsx
import React from "react";

export const Button = ({ children }: { children: React.ReactNode }) => (
  <button style={{ padding: "8px 12px", borderRadius: "8px" }}>
    {children}
  </button>
);

エントリーポイントの設定もしておきます。

// packages/ui/src/index.ts
export * from "./Button";

上記コンポーネントを/app配下で読み込むための設定をします。

// app/next.config.ts
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  transpilePackages: ["@packages/ui"],
};

export default nextConfig;

ではNext.js側でButtonコンポーネントを呼び出してみます。
app/app/page.tsxを以下のようにします。

// app/app/page.tsx
import { Button } from "@packages/ui";

export default function Page() {
  return <Button>Hello from monorepo!</Button>;
}

これでアプリケーションの構築は完了です。
さいごに動作確認をしてみましょう。

$ cd app
$ npm run dev

「Hello from monorepo!」と表示されれば成功です!

5. Amplifyへデプロイ

今回はAWSの管理画面上からポチポチっと作ってみます。

AWS Amplifyの画面で「新しいアプリを作る」というボタンがあるのでそれを押して下さい。

次にプロバイダーとしてGithubを選び、「次へ」を押しましょう。するとGitのリポジトリを連携する画面が開くので、画面に沿って設定をして下さい。

その後、以下のような画面になるはずです。ここでは対象になるリポジトリとブランチを選択し、「私のアプリケーションはモノレポです」にチェックを入れて下さい。
終わったら「次へ」を押しましょう

amplifyの初期設定-Monorepoにチェック

次の画面ではビルドの設定を行います。
ビルドコマンドの設定等を行えますが、今回はAmplify.ymlを使って設定してみます。

以下画面の赤丸のボタンを押すとymlを編集する画面が開くと思います。

ここに以下内容を記載しましょう。

version: 1
applications:
  - frontend:
      phases:
        preBuild:
          commands:
            - npm install
        build:
          commands:
            - npm run build
      artifacts:
        baseDirectory: app/.next
        files:
          - '**/*'
      cache:
        paths:
          - node_modules/**/*
      buildPath: /
    appRoot: app

ymlの保存ができたら「次へ」を押しましょう。

すると確認画面が開くので、そのままデプロイを実行して下さい。
これで完了です!

6. おまけ

個人的にはawsを使ったアプリケーション構築って結構ハードル高いイメージがあったんですが、Amplifyを使ってのデプロイは比較的簡単だったと思います。

軽く調べて触ってみた感じですと、

  • GitHub連携で自動デプロイが簡単
  • 環境変数・ブランチ別デプロイに対応している
  • SSRに対応している

という感じで、実運用でも使えそうでした。
(まあこの辺りは他サービスでも対応してそうですが)

ただし、

  • Amplifyの中身自体がブラックボックスに近い

ということもあり、例えばスケーリング戦略をカスタム設定したい、みたいなことは難しそうに感じました。

手軽に設定できる分、できないことも多そうですね。。

こういった需要がある場合、AWSの場合、

  • AWS S3+CloudFront
  • AWS AppRunner
  • AWS ECS Fargate

といった選択肢もあるので、機能要求に合わせて検討する必要がありそうです。

7. さいごに

今回はAWS Amplifyを使ってNext.jsのデプロイをやってみました。
個人開発や比較的軽量なアプリケーションであれば、手軽に構築できるので結構良さそうだなーと思いました!

この記事が、Monorepo × Amplify 構成を検討している方の参考になれば幸いです。

Discussion