Amplify Gen 2 と npm workspaces で monorepo を構成する
これは何
- Amplify Gen 2 のドキュメントを読んでいたら monorepo のページがあったので、試してみた
- npm workspaces で以下のような構成の monorepo を構築した
- my-shared-backend: Amplify Gen 2 を使用してクラウドリソースを管理するパッケージ
- my-react-app: 管理されているクラウドリソースを使用するフロントエンドアプリ
├── apps/
│ ├── my-react-app/
│ │ └── package.json
├── packages/
│ └── my-shared-backend/
│ ├── amplify/
│ │ ├── auth/
│ │ │ └── resource.ts
│ │ ├── data/
│ │ │ └── resource.ts
│ │ └── backend.ts
│ |── package.json
└── tsconfig.json
└── package.json
Amplify Gen 2 の monorepo について
- そもそも Amplify Hosting に monorepo に対応したデプロイ機能がある
- Amplify Gen 2 の monorepo は、 Amplify Hosting で monorepo をデプロイする際にアプリ側で行うセットアップのナレッジという感じ
- Amplify Gen 2 においてクラウドリソースは
/amplify
ディレクトリに作成される TypeScript ファイルなどで管理される- monorepo では
/amplify
ディレクトリを共有のワークスペースで管理することが推奨されている
- monorepo では
Amplify Gen 2 supports monorepo workflows for fullstack builds with monorepo tools such as Nx and yarn workspaces. When building with Gen 2, we recommend creating the amplify/ folder in a shared workspace.
- 今回は monorepo と言いつつもシンプルに試したいので、以下のような構成にする
├── apps/
│ ├── my-react-app/
│ │ └── package.json
├── packages/
│ └── my-shared-backend/
│ ├── amplify/
│ │ ├── auth/
│ │ │ └── resource.ts
│ │ ├── data/
│ │ │ └── resource.ts
│ │ └── backend.ts
│ |── package.json
└── tsconfig.json
└── package.json
npm workspaces とは
- npm workspaces は npm に標準で含まれている機能
- 複数のパッケージを管理する機能で monorepo を構築できる
npm workspaces で monorepo を作る
monorepo のディレクトリを作成して初期化
mkdir mymonorepo && cd mymonorepo
npm init -y
適宜 GitHub など Amplify Hosting と連携可能な Git Provider にアップロードしておく
Amplify Gen 2 でバックエンドを構築する
npm workspaces で workspace を追加
npm init -y -w ./packages/my-shared-backend
cd ./packages/my-shared-backend
Amplify Gen 2 を使ってプロジェクトをセットアップする
npm create amplify@latest
プロジェクトのセットアップについては以下のドキュメントに詳細がある
バックエンドをデプロイする
- マネジメントコンソールで Amplify Hosting 画面を開いて、バックエンド用に新規で Amplify Hosting App を作成する
- あとは Git プロバイダーと連携し、 monorepo としてデプロイするオプションを選択し、
packages/my-shared-backend
ディレクトリを指定して進めればデプロイできる - 以下のドキュメントにスクリーンショットが掲載されている
これで最低限のバックエンド環境は構築完了
フロントエンドアプリのデプロイを行う際に Amplify Hosting App の ID が必要になるので控えておく
フロントエンドアプリを構築する
npm workspaces で workspace を追加
npm init -y -w ./apps/my-react-app
cd ./apps/my-react-app
vite で React アプリをセットアップ
# npm init -w で作成された package.json は使用しないので削除しておく
rm package.json
npm create vite@latest ./ -- --template react
# 動くか確認
npm install
npm run dev
フロントエンドアプリからバックエンドリソースを参照する
バックエンドをデプロイした Amplify Hosting App ID を指定して以下のコマンドを実行する
BACKEND-APP-ID=hogehoge
npx ampx generate outputs --branch main --app-id ${BACKEND-APP-ID}
これで amplify_outputs.json が生成されるので、フロントエンドアプリから読み込むことで、バックエンドリソースを参照できる
最小限のフロントエンドアプリを実装するため、以下のパッケージもインストールする
npm install aws-amplify @aws-amplify/ui-react
apps/my-react-app/src/App.jsx
を以下のように編集する
import { Authenticator } from '@aws-amplify/ui-react';
import { Amplify } from 'aws-amplify';
import '@aws-amplify/ui-react/styles.css';
import outputs from "../amplify_outputs.json";
Amplify.configure(outputs)
function App() {
return (
<Authenticator>
{({ signOut, user }) => (
<main>
<h1>Hello {user?.username}</h1>
<button onClick={signOut}>Sign out</button>
</main>
)}
</Authenticator>
);
}
export default App
npm run dev
でログイン動作を確認し、問題無さそうならデプロイに進む
フロントエンドアプリをデプロイする
- マネジメントコンソールで Amplify Hosting を開いて、フロントエンドアプリ用に新規で Amplify Hosting App を作成する
- 再度 Git プロバイダーと連携し、 monorepo としてデプロイするオプションを選択し、
apps/my-react-app
ディレクトリを指定して進めればデプロイできる
クリーンアップ
以下を削除する
- 作成した 2つ の Amplify Hosting App
- バックエンドを管理している Amplify Hosting App を削除すると、クラウドリソースを管理している CloudFormation Stack も合わせて削除される
- Git プロバイダーに作成したリポジトリ
感想とか注意点とか
- ドキュメントを読み解くのが大変だったが、一度動かせてしまえば後は結構楽だった
- Amplify Gen 2 で Cognito などの認証リソースを定義することが可能だが、これはアプリケーションと同じ寿命とは限らないため、 1つ のアプリコードと共存するのはアンマッチなケースがある
- バックエンドを共有してフロントエンドアプリとモバイルアプリを開発する場合など
- monorepo では Cognito を含むバックエンドリソースを monorepo 内の 1 パッケージとして管理できるので、バックエンドリソースを使う複数アプリと共存できる
- バックエンドを使うアプリと同じリポジトリでコードを管理できるため、リソースの見通しが良い
Webhook 数の制限に注意
- GitHub を使用する場合の注意点として Webhook の制限がある
- GitHub には現状 1つ の repository に作成可能な Webhook の数は 20 までという制限がある
- Amplify Hosting と連携する場合、 Amplify Hosting App 1つ に対して 1つ の Webhook が作成される
- monorepo の場合、当たり前だが git repository は 1つ なので、例えば monorepo で 21 個のアプリを管理したい場合 Webhook が足りなくなってしまう
- GitHub のドキュメントには Webhook が 20 以上必要になった場合、 GitHub から Webhook を受信してよしなに処理する Proxy を構築すれば良い的なことが書いてあるが、 Amplify Hosting の Webhook は Amplify Hosting が自動的に作成するものなので、ユーザー側で対処するのは難しそうな印象
- Amplify Hosting 側に Issue が上がっているが、現状良い感じの解決策は無さそう
- GitHub の Webhook でなく Amplify Hosting 側の Webhook を作成し、 GitHub 側に自動作成される Webhook をプロキシするという案がコメントされているが、パッと動かせるものでは無さそう
よって GitHub で monorepo を管理する場合、 Webhook 数が 20 以下で足りそうか見積もっておく必要がある
試した環境
% sw_vers
ProductName: macOS
ProductVersion: 14.6.1
BuildVersion: 23G93
% npm --version
10.8.1
% node --version
v20.16.0
% npx ampx --version
1.2.5
% npx ampx info
System:
OS: macOS 14.6.1
CPU: (11) arm64 Apple M3 Pro
Memory: 119.22 MB / 18.00 GB
Shell: /bin/zsh
Binaries:
Node: 20.16.0 - /usr/local/bin/node
Yarn: undefined - undefined
npm: 10.8.1 - /usr/local/bin/npm
pnpm: undefined - undefined
NPM Packages:
@aws-amplify/auth-construct: 1.3.0
@aws-amplify/backend: 1.2.1
@aws-amplify/backend-auth: 1.1.3
@aws-amplify/backend-cli: 1.2.5
@aws-amplify/backend-data: 1.1.3
@aws-amplify/backend-deployer: 1.1.0
@aws-amplify/backend-function: 1.4.0
@aws-amplify/backend-output-schemas: 1.2.0
@aws-amplify/backend-output-storage: 1.1.1
@aws-amplify/backend-secret: 1.1.1
@aws-amplify/backend-storage: 1.1.2
@aws-amplify/cli-core: 1.1.2
@aws-amplify/client-config: 1.3.0
@aws-amplify/deployed-backend-client: 1.4.0
@aws-amplify/form-generator: 1.0.1
@aws-amplify/model-generator: 1.0.5
@aws-amplify/platform-core: 1.1.0
@aws-amplify/plugin-types: 1.2.1
@aws-amplify/sandbox: 1.2.1
@aws-amplify/schema-generator: 1.2.1
aws-amplify: 6.6.0
aws-cdk: 2.155.0
aws-cdk-lib: 2.155.0
typescript: 5.5.4
AWS environment variables:
AWS_STS_REGIONAL_ENDPOINTS = regional
AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables
Discussion