AWS AmplifyGen2がGAされたので、Nxのmonorepo構成で作成したNext.jsプロジェクトを、バックエンドとフロントエンドで別個のAmplifyアプリとして分離して、デプロイしてみます。
茨の道
下記Gen2のドキュメントを参考に進めました。
記載されている内容が少なく、デプロイエラーで詰まると下記のドキュメントなどと併せて読む必要があり、全体像の理解に時間がかかりました。
Gen2のドキュメントには「バックエンドのみのコードをデプロイできる」とあるのですが、手順に従って進めてもリポジトリの構成を自動検出してくれない(自動検出結果がおかしい)、自動作成されるamplify.ymlのままだとデプロイエラーが出るなど、リポジトリのコードがおかしいのか、Amplifyのビルド&デプロイロジックに問題があるのか良く分からず、だいぶ混乱しました。
ここでは無事にフロント&バックエンドともにデプロイできた手順を、Nxのワークスペース作成から進めていきます。
なお、Node.jsはバージョン18(node:18-bullseye-slim)、パッケージ管理はnpmを使用しており、パッケージのバージョンは記事執筆時点(2024/05/10)での最新をインストールしています。
Node.jsのバージョン2x系ではAmplifyのサンドボックス作成時にエラーが出ることが報告1されており、ここでもバージョン18を使用しています。
Nx CLIのバージョンは18.3.4です。
数日前にNx 19.0がランチしてました。
https://www.youtube.com/watch?v=U6eO8-w9DR0
使用する名前
test-nx : GitHubリポジトリ名 & Nxワークスペース名 & Next.js アプリ名
Nxワークスペースのルートディレクトリ -> /workspace/services
Next.js アプリのルートディレクトリ -> /workspace/services/apps/test-nx
test-shared-backend : Amplifyシェアード(共有)バックエンド
バックエンドのルートディレクトリ -> /workspace/services/lib/test-shared-backend
test-nx-app : フロントアプリのAmplifyアプリ名
test-nx-shared-backend : シェアードバックエンドのAmplifyアプリ名
開発環境
開発用ローカルのコマンド実行はLinux(WSL2 Ubuntu上で動くDockerコンテナ)で実行しています。
シェルはzshで、あらかじめ、aws cliとnxがインストール済です。
# AWS CLIをインストール
$ apt-get update && apt-get install -y \
curl \
unzip \
&& curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& rm -rf awscliv2.zip ./aws
# NXをインストール
$ npm i -g nx@latest
AWS SSO
AmplifyのCLIコマンド ampx 〜をAWS SSO認証で実行する場合、コマンドオプション --profile を指定します。(aws configure sso コマンドでSSO設定済前提で)
(例) npx ampx generate outputs --branch shared-main --app-id d10c0qxxx... --profile sso...
Nxワークスペース作成
空のtest-nxリポジトリを新規作成&クローンして、Nxワークスペースを新規作成します。
$ npx create-nx-workspace@latest --preset=next
NX Let's create a new workspace [https://nx.dev/getting-started/intro]
✔ Where would you like to create your workspace? · org
✔ Application name · test-nx
✔ Would you like to use the App Router (recommended)? · Yes
✔ Would you like to use the src/ directory? · Yes
✔ Test runner to use for end to end (E2E) tests · playwright
✔ Default stylesheet format · tailwind
✔ Set up CI with caching, distribution and test deflaking · skip
✔ Would you like remote caching to make your build faster? · skip
NX Creating your v19.0.2 workspace.
✔ Installing dependencies with npm
✔ Successfully created the workspace: org.
NX Directory is already under version control. Skipping initialization of git.
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
NX First time using Nx? Check out this interactive Nx tutorial.
https://nx.dev/react-tutorial/1-code-generation
リポジトリルート/orgにNxワークスペースが作成されるので、ワークスペースのファイルをリポジトリルートへ移動します。
# 隠しファイルを含めて、カレントディレクトリへ全て移動
# zshを使用しているので、bashでは動作しない。
$ rm -rf .nx # Nxキャッシュディレクトリをまず削除
$ mv org/*(D) .
$ rmdir org
リポジトリルートのサブディレクトリにNxワークスペースを配置した場合、Amplifyのプロジェクト自動検出が動作しない。
npx create-nx-workspace..でGitリポジトリも初期化してくれるようなので、先にワークスペースを作ってからGitHubにpushするのがいいかも知れない。
ワークスペースの作成が完了後、コミットしておきます。
$ git add .
$ git commit -m "Initial commit"
Amplifyシェアードバックエンドの作成
NxでJavaScript用テンプレートを自動作成します。
ここではライブラリ用のディレクトリに lib を指定しています。
(AmplifyのMonorepo setupドキュメントでは packages にあたる部分)
$ nx g @nx/js:library test-shared-backend --directory lib
NX Generating @nx/js:library
✔ Which unit test runner would you like to use? · none
✔ Which bundler would you like to use to build the library? Choose 'none' to skip build setup. · tsc
✔ What should be the project name and where should it be generated? · lib--test-shared-backend @ lib/test-shared-backend
In Nx 20, generating projects will no longer derive the name and root.
Please provide the exact project name and root in the future.
Example: nx g @nx/js:library lib--test-shared-backend --directory lib/test-shared-backend
CREATE lib/test-shared-backend/tsconfig.json
CREATE lib/test-shared-backend/src/index.ts
CREATE lib/test-shared-backend/src/lib/lib--test-shared-backend.ts
CREATE lib/test-shared-backend/tsconfig.lib.json
CREATE lib/test-shared-backend/README.md
CREATE lib/test-shared-backend/package.json
UPDATE nx.json
CREATE lib/test-shared-backend/project.json
CREATE lib/test-shared-backend/.eslintrc.json
UPDATE tsconfig.base.json
NX 👀 View Details of lib--test-shared-backend
Run "nx show project lib--test-shared-backend --web" to view details about this project.
完了すると、リポジトリルート/lib/test-shared-backendが作成され、中にpackage.jsonなど作成されています。
続いて、作成されたディレクトリの中でamplifyをインストールします。
$ cd lib/test-shared-backend/
$ npm create amplify@latest
? Where should we create your project? .
Installing devDependencies:
- @aws-amplify/backend
- @aws-amplify/backend-cli
- aws-cdk@^2
- aws-cdk-lib@^2
- constructs@^10.0.0
- typescript@^5.0.0
- tsx
- esbuild
Installing dependencies:
- aws-amplify
✔ DevDependencies installed
✔ Dependencies installed
✔ Template files created
Successfully created a new project!
Welcome to AWS Amplify!
- Get started by running npx ampx sandbox.
- Run npx ampx help for a list of available commands.
Amplify Gen 2 collects anonymous telemetry data about general usage of the CLI. Participation is optional, and you may opt-out by using npx ampx configure telemetry disable. To learn more about telemetry, visit https://docs.amplify.aws/gen2/reference/telemetry
ここで一度コミットしておきます。
$ cd ../../
$ git add .
$ git commit -m "Add amplify"
Nxで管理する場合、package.jsonがリポジトリルート直下の1つのみになるので、test-shared-backend直下のpackage.jsonのdependenciesとdevDependenciesを、リポジトリルートのpackage.jsonへ手動マージします。
マージ後のpackage.json↓
{
"name": "@org/source",
"version": "0.0.0",
"license": "MIT",
"scripts": {},
"private": true,
"dependencies": {
"next": "14.0.4",
"react": "18.3.1",
"react-dom": "18.3.1",
"aws-amplify": "^6.3.0",
"tslib": "^2.3.0"
},
"devDependencies": {
"@nx/devkit": "19.0.2",
"@nx/eslint": "19.0.2",
"@nx/eslint-plugin": "19.0.2",
"@nx/jest": "19.0.2",
"@nx/js": "19.0.2",
"@nx/next": "19.0.2",
"@nx/playwright": "19.0.2",
"@nx/workspace": "19.0.2",
"@playwright/test": "^1.36.0",
"@swc-node/register": "~1.8.0",
"@swc/core": "~1.3.85",
"@swc/helpers": "~0.5.2",
"@types/jest": "^29.4.0",
"@types/node": "18.16.9",
"@types/react": "18.3.1",
"@types/react-dom": "18.3.0",
"@typescript-eslint/eslint-plugin": "^7.3.0",
"@typescript-eslint/parser": "^7.3.0",
"autoprefixer": "10.4.13",
"babel-jest": "^29.4.1",
"eslint": "~8.57.0",
"eslint-config-next": "14.0.4",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jsx-a11y": "6.7.1",
"eslint-plugin-playwright": "^0.15.3",
"eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0",
"jest": "^29.4.1",
"jest-environment-jsdom": "^29.4.1",
"nx": "19.0.2",
"postcss": "8.4.21",
"prettier": "^2.6.2",
"tailwindcss": "3.2.7",
"ts-jest": "^29.1.0",
"ts-node": "10.9.1",
"@aws-amplify/backend": "^1.0.1",
"@aws-amplify/backend-cli": "^1.0.2",
"aws-cdk": "^2.141.0",
"aws-cdk-lib": "^2.141.0",
"constructs": "^10.3.0",
"esbuild": "^0.21.1",
"tsx": "^4.9.3",
"typescript": "^5.4.5"
}
}
Nx初心者なので、他にいい手順があれば教えてほしいです。
マージ後、test-shared-backend直下のpackage.json、package-lock.json、node_modulesディレクトリを削除します。
test-shared-backend/amplify直下にもpackage.jsonがあり、{ "type": "module" }のみ書かれています。これも、nxのコマンドを使った時に下記エラーが出る原因になるため、削除します。
Failed to process project graph. Run "nx reset" to fix this. Please report the issue if you keep seeing it. See errors below.
削除後のディレクトリ↓
npm clean installして、問題が出ないことを確認します。
$ npm ci
問題なければコミットします。
$ git add .
$ git commit -m "Merge packages"
Amplifyシェアードバックエンドのデプロイ
Next.jsのパッケージ削除
ここで小細工をします。
事前準備として、package.jsonのdependenciesからNext.jsのパッケージを削除しておきます。
削除せずAWSコンソールからAmplifyアプリを作成した場合、[Next.js][Amplify Gen 2]リポジトリとして認識されてしまい、デプロイ時に下記のエラーが出て失敗します。
[ERROR]: !!! CustomerError: Can't find required-server-files.json in build output directory
Next.jsとしてリポジトリが認識されてしまうと、ビルド結果のファイル「required-server-files.json」が必須となるようです。
削除して、コミット&プッシュしておきます。
$ git add .
$ git commit -m "Fix packages"
$ git push
Nxワークスペースを最初に作る時に、テンプレートをNext.jsではなくts(TypeScript)やnodeなどで作成しておくと、回避できる。
# ワークスペース作成
$ npx create-nx-workspace@latest --preset=ts
# バックエンドの作成
$ nx g @nx/node:library --name=test-shared-backend --directory=lib
# Nxのジェネレートで対応テンプレートが見つからない場合、インストールする。
$ npm i -D @nx/node # Node.js
$ npm i -D @nrwl/next # Next.js
Amplifyアプリの作成(バックエンド)
AWSコンソールからAmplifyを開き、GitHubのリポジトリと接続して、monorepoを有効にして、ルートディレクトリのパスを入力し、次へ進みます。
モノレポルートディレクトリ→
lib/test-shared-backend
/lib/..と、パスの先頭に / をつけても次へ進めますが、デプロイ時にエラーになるため注意
自動検出されたフレームワークが「Amplify Gen 2」のみになっていれば成功です。
ここで「Next.js」など、フロントのフレームワークが表示されていた場合、前の手順に戻ってpackage.jsonの修正内容を確認します。
フロントエンドビルドコマンドは、特にビルドするものがないので、公式ドキュメント(Separate frontend and backend teams)に記載の通り、distディレクトリとindex.htmlを作成するに留めます。
アプリケーションの名前->
test-nx-shared-backend
フロントエンドビルドコマンド->
mkdir ./dist && touch ./dist/index.html
出力ディレクトリをビルド->
dist
他、デフォルト値を使用
次へ進み、設定内容を確認します。
問題なければ、保存してデプロイします。
IAMサービスロールとポリシーが自動作成されます。Amplifyアプリを削除しただけではこのサービスロールとポリシーが削除されないため、アプリが不要になったら、手動の削除が必要です(自動作成した場合、タグをつけておくと管理しやすいか)。余談ですが、Amplifyアプリ削除時に求められる「削除」の文字入力は、現時点では、日本語ではなく英語で「delete」と入力しないとアプリを削除できないです。
デプロイ実行結果で、エラーが出ます。
エラー対処「CustomerError: Build path does not exist, please check the 'buildPath' value in BuildSpec」
Amplifyコンソールから本アプリのホスティング→ビルドの設定を開き、amplify.ymlをダウンロードして、lib/test-shared-backend直下へ配置します。
配置後、amplify.ymlの中身を下記のように書き換えます。
version: 1
applications:
- backend:
phases:
build:
commands:
[
'npm ci --cache .npm --prefer-offline',
'cd lib/test-shared-backend',
'npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID',
]
frontend:
phases:
build:
commands: ['mkdir ./dist && touch ./dist/index.html']
artifacts:
baseDirectory: lib/test-shared-backend/dist
files:
- '**/*'
cache:
paths:
- '.npm/**/*'
buildPath: .
appRoot: lib/test-shared-backend
色々デフォルト状態から変更していますが、buildPath以外にも、エラーが色々出るので、最終的にデプロイできたamplify.ymlの中身がこのようになりました。
これが正しいのかは・・分からず、試行錯誤の結果です。
正しい方法があれば教えてほしいです。
更新したamplify.ymlをリポジトリへ上げます。
$ git add .
$ git commit -m "Fix amplify.yml"
$ git push
再デプロイが実行され、デプロイが成功することを確認します。
デプロイ後の確認
認証(Auth)とデータ(Data)のAWSリソースが作成されていることを確認します。
CDKをデフォルトから変えていないので、Authはメールアドレスによるユーザー作成、DataにはTodoテーブルが作成されています。
今後、バックエンドの構成を変更するときは、lib/test-shared-backend/amplify以下のCDKを修正します。
Next.jsフロントエンドのデプロイ
Next.jsのパッケージ復元
package.jsonのdependenciesに、削除したNext.jsパッケージを追加して、元に戻します。
"dependencies": {
"next": "14.0.4",
"react": "18.3.1",
"react-dom": "18.3.1",
"aws-amplify": "^6.3.0",
"tslib": "^2.3.0"
},
$ npm i
Next.jsのローカル起動
最初にNxテンプレートを作成したタイミングで、リポジトリルート/apps/test-nxにNext.jsアプリが作成されていると思います。
下記コマンドをワークスペースのルートで実行することで、Next.jsアプリをローカル実行できますが、test-nx/project.jsonにビルド用のコンフィグがないのでエラーになります。
$ nx serve test-nx
NX Failed to process project graph. Run "nx reset" to fix this. Please report the issue if you keep seeing it.
Pass --verbose to see the stacktraces.
project.jsonにNext.jsビルド用のターゲットを追加して、保存します。
(内容は、下記のNxレシピを参考に、targetsへとりあえず貼り付けています)
{
"name": "test-nx",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/test-nx",
"projectType": "application",
"tags": [],
"// targets": "to see all targets run: nx show project test-nx --web",
"targets": {
"build": {
"executor": "@nx/next:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"outputPath": "dist/apps/test-nx"
},
"configurations": {
"development": {
"outputPath": "apps/test-nx"
},
"production": {}
}
},
"serve": {
"executor": "@nx/next:server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "test-nx:build",
"dev": true
},
"configurations": {
"development": {
"buildTarget": "test-nx:build:development",
"dev": true
},
"production": {
"buildTarget": "test-nx:build:production",
"dev": false
}
}
},
"export": {
"executor": "@nx/next:export",
"options": {
"buildTarget": "test-nx:build:production"
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/test-nx/jest.config.ts"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/test-nx/**/*.{ts,tsx,js,jsx}"]
}
}
}
}
再度、serveを実行します。
$ nx serve test-nx
> nx run test-nx:serve:development
▲ Next.js 14.0.4
- Local: http://localhost:4200
We detected TypeScript in your project and reconfigured your tsconfig.json file for you. Strict-mode is set to false by default.
The following suggested values were added to your tsconfig.json. These values can be changed to fit your project's needs:
- include was updated to add '.next/types/**/*.ts'
✓ Ready in 2.1s
○ Compiling / ...
✓ Compiled / in 3.1s (427 modules)
✓ Compiled in 248ms (216 modules)
http://localhost:4200 へアクセスして、テンプレートページが表示されることを確認します。
最新のコードを上げておきます。
$ git add .
$ git commit -m "Confirm front serve"
$ git push
Amplifyアプリの作成(フロントエンド)
AWSコンソールからAmplifyを開き、GitHubのリポジトリと接続して、monorepoを有効にして、フロントのルートディレクトリのパスを入力し、次へ進みます。
モノレポルートディレクトリ→
apps/test-nx
自動検出されたフレームワークが「Next.js」「Amplify Gen 2」のみになっていればOKです。アプリケーションの名前を変更します。
アプリケーションの名前->
test-nx-app
他、デフォルト値を使用
次へ進み、設定内容を確認します。
問題なければ、保存してデプロイします。
デプロイ実行結果で、エラーが出ます。
エラー対処「CustomerError: Build path does not exist, please check the 'buildPath' value in BuildSpec」
バックエンドと同じく、フロントエンドでもbuildPathのエラーが出ます。
前回と同じように、Amplifyコンソールから本アプリのホスティング→ビルドの設定を開き、amplify.ymlをダウンロードして、apps/test-nx直下へ配置します。
配置後、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
- npx ampx generate outputs --branch $AWS_BRANCH --app-id BACKEND-APP-ID
# バックエンド接続情報のファイルコピー。generate を実行する場所間違えているかな・・。
- cp ./amplify_outputs.json ./apps/test-nx
frontend:
phases:
preBuild:
commands:
- mkdir -p dist/apps/test-nx
build:
commands:
- npx nx build test-nx
artifacts:
baseDirectory: dist/apps/test-nx/.next
files:
- '**/*'
cache:
paths:
- .next/cache/**/*
- .npm/**/*
buildPath: .
appRoot: apps/test-nx
buildPathなどパス系のエラー回避に加えて、公式ドキュメントに記載がある、フロントからバックエンドへ接続するためのコマンドも、backend: build: commands: へ加えておきます。
この時、BACKEND-APP-ID を、すでにデプロイ済のバックエンドアプリのAppIDと置換します。(画像中、d10c0q〜 から始まる部分が、バックエンドアプリのAppIDです)
もともと記載があった npx ampx pipeline-deploy の行はコメントアウトして、無効化しています。
applications:
- backend:
phases:
build:
commands:
- npm ci --cache .npm --prefer-offline
# - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
- npx ampx generate outputs --branch $AWS_BRANCH --app-id d10c0qxxx...
このコマンドの編集を行わないと、下記のエラーが出てビルドが通らないです。
FileConventionError: Amplify Backend not found in /codebuild/output/src1934378443/src/test-nx.
更新したamplify.ymlをリポジトリへ上げます。
$ git add .
$ git commit -m "Fix amplify.yml"
$ git push
再デプロイが実行され、デプロイが成功することを確認します。
デプロイ後の確認
デプロイ成功後、ドメインのURLを参照し、無事にNextJSのフロント画面が表示されることを確認します。
デプロイブランチ
今回は main ブランチのみ使用したため、main ブランチをプッシュするとバックエンド、フロントともに再デプロイ処理が走ります。
このため、バックエンドとフロントでブランチを分けて、それぞれ個別にAmplifyアプリに紐づけておくと再デプロイを制御できて便利です。
バックエンドをshared-mainブランチ、フロントをfront-mainブランチなど異なるブランチ名を使用する場合、フロント側のビルド設定npx ampx generate outputs --branch $AWS_BRANCH --app-id BACKEND-APP-ID
の $AWS_BRANCH を、対応するバックエンドのブランチ名(shared-mainなど)へ変更が必要です。
Amplifyアプリへ紐付けるブランチは、AWSコンソールから簡単に追加/削除でき、本番稼働ブランチの変更もできます。
Basic認証などアクセス制御はブランチごとのため、設定している場合、ブランチを追加したら忘れずに設定しておきます。
サンドボックスの作成
バックエンドのディレクトリ(lib/test-shared-backend)へ移動して、下記コマンドを実行して、package.jsonとAmplifyサンドボックスを作成します。
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (test-shared-backend) amplify-backend
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /workspace/services/lib/test-shared-backend/package.json:
{
"name": "amplify-backend",
"version": "1.0.0",
"description": "This library was generated with [Nx](https://nx.dev).",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
続いて、ampxコマンドの実行です。
$ npx ampx sandbox --outputs-out-dir ../../apps/test-nx
Amplify Sandbox
Identifier: node
Stack: amplify-amplifybackend-node-sandbox-1ad730e7d3
To specify a different sandbox identifier, use --identifier
✨ Synthesis time: 0.49s
⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments
⚠️ They should only be used for development - never use them for your production Stacks!
amplify-amplifybackend-node-sandbox-1ad730e7d3: start: Building 4adc3952616d06259c60d1953b9de7868b262e9618cbccd819760c1c2a83c8fe:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: success: Built 4adc3952616d06259c60d1953b9de7868b262e9618cbccd819760c1c2a83c8fe:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: start: Building f6bf6a2c43df9880a1e61f0771a573d91474f7a5b5e6210b55da505511dca2e2:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: success: Built f6bf6a2c43df9880a1e61f0771a573d91474f7a5b5e6210b55da505511dca2e2:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: start: Publishing 4adc3952616d06259c60d1953b9de7868b262e9618cbccd819760c1c2a83c8fe:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: start: Publishing f6bf6a2c43df9880a1e61f0771a573d91474f7a5b5e6210b55da505511dca2e2:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: success: Published 4adc3952616d06259c60d1953b9de7868b262e9618cbccd819760c1c2a83c8fe:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: success: Published f6bf6a2c43df9880a1e61f0771a573d91474f7a5b5e6210b55da505511dca2e2:current_account-current_region
amplify-amplifybackend-node-sandbox-1ad730e7d3: deploying... [1/1]
⚠️ The following non-hotswappable changes were found:
logicalID: deploymentType, type: Stack Output, reason: output was changed
logicalID: region, type: Stack Output, reason: output was changed
logicalID: userPoolId, type: Stack Output, reason: output was changed
logicalID: webClientId, type: Stack Output, reason: output was changed
logicalID: identityPoolId, type: Stack Output, reason: output was changed
logicalID: authRegion, type: Stack Output, reason: output was changed
logicalID: allowUnauthenticatedIdentities, type: Stack Output, reason: output was changed
logicalID: signupAttributes, type: Stack Output, reason: output was changed
logicalID: usernameAttributes, type: Stack Output, reason: output was changed
logicalID: verificationMechanisms, type: Stack Output, reason: output was changed
logicalID: passwordPolicyMinLength, type: Stack Output, reason: output was changed
logicalID: passwordPolicyRequirements, type: Stack Output, reason: output was changed
logicalID: awsAppsyncApiId, type: Stack Output, reason: output was changed
logicalID: awsAppsyncApiEndpoint, type: Stack Output, reason: output was changed
logicalID: awsAppsyncAuthenticationType, type: Stack Output, reason: output was changed
logicalID: awsAppsyncRegion, type: Stack Output, reason: output was changed
logicalID: amplifyApiModelSchemaS3Uri, type: Stack Output, reason: output was changed
logicalID: awsAppsyncAdditionalAuthenticationTypes, type: Stack Output, reason: output was changed
logicalID: auth179371D7, type: AWS::CloudFormation::Stack, reason: resource 'auth179371D7' was created by this deployment
logicalID: data7552DF31, type: AWS::CloudFormation::Stack, reason: resource 'data7552DF31' was created by this deployment
logicalID: CDKMetadata, type: AWS::CDK::Metadata, reason: resource 'CDKMetadata' was created by this deployment
Could not perform a hotswap deployment, as the stack amplify-amplifybackend-node-sandbox-1ad730e7d3 contains non-Asset changes
Falling back to doing a full deployment
amplify-amplifybackend-node-sandbox-1ad730e7d3: creating stack...
amplify-amplifybackend-node-sandbox-1ad730e7d3-auth179371D7-124WX4RQYOKMO | 0 | 5:12:49 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | amplify-amplifybackend-node-sandbox-1ad730e7d3-auth179371D7-124WX4RQYOKMO User Initiated
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 0 | 5:12:45 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | amplify-amplifybackend-node-sandbox-1ad730e7d3 User Initiated
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 0 | 5:12:49 AM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | auth/CDKMetadata/Default (CDKMetadata)
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 0 | 5:12:49 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | auth.NestedStack/auth.NestedStackResource (auth179371D7)
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 0 | 5:12:49 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | auth.NestedStack/auth.NestedStackResource (auth179371D7) Resource creation Initiated
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 0 | 5:12:50 AM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | auth/CDKMetadata/Default (CDKMetadata) Resource creation Initiated
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 1 | 5:12:50 AM | CREATE_COMPLETE | AWS::CDK::Metadata | auth/CDKMetadata/Default (CDKMetadata)
1 Currently in progress: amplify-amplifybackend-node-sandbox-1ad730e7d3-auth179371D7-124WX4RQYOKMO, amplify-amplifybackend-node-sandbox-1ad730e7d3, auth179371D7
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 2 | 5:13:36 AM | CREATE_COMPLETE | AWS::CloudFormation::Stack | auth.NestedStack/auth.NestedStackResource (auth179371D7)
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 2 | 5:13:37 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | data.NestedStack/data.NestedStackResource (data7552DF31)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:37 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G User Initiated
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | data/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::AppSync::GraphQLApi | data/amplifyData/GraphQLAPI (amplifyDataGraphQLAPI42A6FA33)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | auth/CDKMetadata/Default (CDKMetadata)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::Lambda::LayerVersion | data/amplifyData/AmplifyCodegenAssets/AmplifyCodegenAssetsDeployment/AwsCliLayer (amplifyDataAmplifyCodegenAssetsAmplifyCodegenAssetsDeploymentAwsCliLayerE322F905)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::S3::Bucket | data/amplifyData/AmplifyCodegenAssets/AmplifyCodegenAssetsBucket (amplifyDataAmplifyCodegenAssetsAmplifyCodegenAssetsBucket9CCB4ACA)
amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G | 2 | 5:13:42 AM | CREATE_IN_PROGRESS | AWS::IAM::Role | data/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C1536MiB/ServiceRole (CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C1536MiBServiceRoleA41FC8C2)
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 2 | 5:13:38 AM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | data.NestedStack/data.NestedStackResource (data7552DF31) Resource creation Initiated
2 Currently in progress: amplify-amplifybackend-node-sandbox-1ad730e7d3-auth179371D7-124WX4RQYOKMO, amplify-amplifybackend-node-sandbox-1ad730e7d3, data7552DF31, amplify-amplifybackend-node-sandbox-1ad730e7d3-data7552DF31-2V55EXWEYM7G, CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092, amplifyDataGraphQLAPI42A6FA33, CDKMetadata, amplifyDataAmplifyCodegenAssetsAmplifyCodegenAssetsDeploymentAwsCliLayerE322F905, amplifyDataAmplifyCodegenAssetsAmplifyCodegenAssetsBucket9CCB4ACA, CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C1536MiBServiceRoleA41FC8C2
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 3 | 5:16:15 AM | CREATE_COMPLETE | AWS::CloudFormation::Stack | data.NestedStack/data.NestedStackResource (data7552DF31)
amplify-amplifybackend-node-sandbox-1ad730e7d3 | 4 | 5:16:16 AM | CREATE_COMPLETE | AWS::CloudFormation::Stack | amplify-amplifybackend-node-sandbox-1ad730e7d3
✅ amplify-amplifybackend-node-sandbox-1ad730e7d3
✨ Deployment time: 212.53s
Outputs:
amplify-amplifybackend-node-sandbox-1ad730e7d3.allowUnauthenticatedIdentities = true
amplify-amplifybackend-node-sandbox-1ad730e7d3.amplifyApiModelSchemaS3Uri = s3://amplify-amplifybackend-no-amplifydataamplifycodege-yzgdz5sruxai/model-schema.graphql
amplify-amplifybackend-node-sandbox-1ad730e7d3.authRegion = ap-northeast-1
amplify-amplifybackend-node-sandbox-1ad730e7d3.awsAppsyncAdditionalAuthenticationTypes = AMAZON_COGNITO_USER_POOLS
amplify-amplifybackend-node-sandbox-1ad730e7d3.awsAppsyncApiEndpoint = https://k5zwi573yjckdgmgd5km4zunzy.appsync-api.ap-northeast-1.amazonaws.com/graphql
amplify-amplifybackend-node-sandbox-1ad730e7d3.awsAppsyncApiId = bjceldto2zgnlntet6yqoyfjle
amplify-amplifybackend-node-sandbox-1ad730e7d3.awsAppsyncAuthenticationType = AWS_IAM
amplify-amplifybackend-node-sandbox-1ad730e7d3.awsAppsyncRegion = ap-northeast-1
amplify-amplifybackend-node-sandbox-1ad730e7d3.deploymentType = sandbox
amplify-amplifybackend-node-sandbox-1ad730e7d3.identityPoolId = ap-northeast-1:f88e12e0-8ac8-4697-9472-4d841ef93269
amplify-amplifybackend-node-sandbox-1ad730e7d3.passwordPolicyMinLength = 8
amplify-amplifybackend-node-sandbox-1ad730e7d3.passwordPolicyRequirements = ["REQUIRES_NUMBERS","REQUIRES_LOWERCASE","REQUIRES_UPPERCASE","REQUIRES_SYMBOLS"]
amplify-amplifybackend-node-sandbox-1ad730e7d3.region = ap-northeast-1
amplify-amplifybackend-node-sandbox-1ad730e7d3.signupAttributes = ["email"]
amplify-amplifybackend-node-sandbox-1ad730e7d3.userPoolId = ap-northeast-1_hCuBi9Ztx
amplify-amplifybackend-node-sandbox-1ad730e7d3.usernameAttributes = ["email"]
amplify-amplifybackend-node-sandbox-1ad730e7d3.verificationMechanisms = ["email"]
amplify-amplifybackend-node-sandbox-1ad730e7d3.webClientId = 69r5bnrsipc6gujkn74u6mfq2q
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:637423527734:stack/amplify-amplifybackend-node-sandbox-1ad730e7d3/6d75afa0-159e-11ef-b373-06ae7934c5cb
✨ Total time: 213.02s
[Sandbox] Watching for file changes...
File written: ../../apps/test-nx/amplify_outputs.json
これで、フロントのNext.jsアプリのディレクトリに amplify_outputs.json (旧amplifyconfiguration.json2)が作成され、バックエンドへの接続情報が出力されます。
amplify_outputs.json 出力後、このファイルが誤ってホスティングのコードや他の開発者のコードに紛れ込まないように、.gitignore へ追加しておきます。
# Amplify
amplify_outputs.json
AWSコンソールからバックエンドのサンドボックスを確認すると、無事にサンドボックスが1つ作成されていることが確認できます。
Nxワークスペースの場合、package.json はワークスペースルートにただ一つ配置するはずなのですが、ワークスペースルートでnpx ampx sandbox --dir-to-watch lib/test-shared-backend --outputs-out-dir apps/test-nx
を実行した場合、監視ディレクトリにバックエンドのディレクトリを指定していても、Amplify Backend not found in /workspace/services.
とエラーが発生するため、バックエンドのルートでnpx ampx sandbox
するためにnpm init
して package.json を作成しています。
このpackage.jsonをNxワークスペースに含めても問題ないか、引き続き検証予定です。
この状態で、ワークスペースルートでnx serve test-nx
を実行すると、Next.jsアプリが起動し、Authなどサンドボックスのバックエンドと接続した状態で、アプリケーションが動きます。
Next.jsアプリでAuthなど認証系のコンポーネントを実装する場合、公式マニュアルもありますが、下記のYouTube動画なども参考になります。(GA前の録画なので、amplifyconfiguration.json など古い名称が使われていますが)
動画の1時間25分すぎに、AmplifyUIライブラリのボタンが表示されない問題(AmplifyUIとTailwind CSSを同時に使用している場合に発生する問題)の修正方法(global.cssの修正)も示されているので、もしお困りの方がおられれば確認してみるといいかもです。
ホスティングバックエンドへの接続
サンドボックスではなく、本番環境など直接ホスティングのバックエンドへ接続したい場合、npx ampx generate
コマンドをフロントエンドのルートディレクトリで実行すると、ホスティングへの接続情報を記した
amplify_outputs.json が出力されるため、(たぶん)ホスティングのバックエンドへアプリを接続できると思います。(検証予定)
# (例) 環境変数 $AWS_BRANCH は、実際のバックエンドブランチの値へ変更しておく。
$ npx ampx generate outputs --branch shared-main --app-id d10c0qxxx...
おわり
ここまでで、バックエンド、フロントともにデプロイが成功することを確認できました。
引き続き検証して、記事を更新予定です。
ご覧いただきありがとうございました。