Next.jsで作成したWebアプリをAppRunnerで動かす際のテンプレート
Next.jsで作成したWebアプリをAppRunnerで動かす際のテンプレートです。以下の構成を想定しています。
なぜAppRunnerを利用するのか?
AWS環境でNext.jsで作成したWebアプリを動かす際にはAWS Amplifyを利用することが多いと思いますが、閉域網などでなるべくシンプルな構成で動かしたい場合には、AppRunnerを利用するのが便利です。本テンプレートはそのような環境でNext.js(で作成したWebアプリ)を動かすための最小限の構成を提供します。
なお、本テンプレートのAppRunnerはVPCを指定しないため、閉域網で利用する際にはCDK部分の変更が必要です。また、認証にCognitoを利用していますが、CognitoはVPC Endpointを利用できないため、完全に閉域内での通信にならない点は注意してください。
完全なコードは以下を参照してください。
デプロイ手順
- Cognitoのユーザープールを作成する
- Cognitoのユーザープールに、アプリクライアントを作成する
- aws-exports.jsを準備する
- CDKでデプロイする
Cognitoのユーザープールを作成する
AWSのコンソールからCognitoのユーザープールを作成します。
Cognitoのユーザープールに、アプリクライアントを作成する
Cognitoのユーザープールに、アプリクライアントを作成します。
aws-exports.jsを準備する
aws-exports.js
を作成します。以下のような内容になります。
const awsmobile = {
aws_project_region: 'ap-northeast-1',
aws_cognito_region: 'ap-northeast-1',
aws_user_pools_id: '[作成したユーザープールのIDで置き換えてください]',
aws_user_pools_web_client_id: '[作成したアプリクライアントのIDで置き換えてください]',
};
export default awsmobile;
aws-exports.js
は以下に配置します。
- app/nextjs-on-apprunner-demo/src/aws-exports.js
CDKでデプロイする
CDKを使用して、AppRunnerにデプロイします。
cd cdk
AWS_DEFAULT_REGION=ap-northeast-1 cdk synth # CFnが意図した通り出力されることを確認します。
AWS_DEFAULT_REGION=ap-northeast-1 cdk diff # 差分を確認します。
AWS_DEFAULT_REGION=ap-northeast-1 cdk deploy
補足事項
Amplify UIのログイン画面利用する場合は、ClientComponentを使用する必要がある
Amplify UIのAuthenticatorを使用する場合、ServerComponentではなくClientComponentを使用する必要があります。
ServerComponentでCognitoの認証情報を取得する場合は、AmplifyのSSRを使用を指定する必要がある
ServerComponentで(Amplify UIのログイン画面利用を利用してログインをした)Cognitoの認証情報を取得する場合は、Amplifyのconfigureで、ssr=trueを指定する必要があります。これにより、認証情報がcookieに保存されるようになります。
Amplify.configure({ ...awsExports }, { ssr: true }); // ssrをtrueにすることで、Cognitoの認証情報をSSRで取得できるようにします。
Amplify.jsをServerComponentで使用する場合は、Next.js Adapterを導入する必要がある
ServerComponentでAmplify.jsを使用する場合は、Next.js Adapterを導入する必要があります。
npm add aws-amplify @aws-amplify/adapter-nextjs
今回の環境では、Next.js AdapterのrunWithAmplifyServerContextをcookieに保存された認証情報と共に呼び出し、SSR版のAmplify.js関数を呼び出します。
import { getCurrentUser } from 'aws-amplify/auth/server';
import { fetchAuthSession } from 'aws-amplify/auth/server';
import { fetchUserAttributes } from 'aws-amplify/auth/server';
export const { runWithAmplifyServerContext } = createServerRunner({
config,
});
[省略]
export async function requireCurrentUser() {
const currentUser = await runWithAmplifyServerContext({
nextServerContext: { cookies },
operation: (contextSpec) => getCurrentUser(contextSpec),
});
const session = await runWithAmplifyServerContext({
nextServerContext: { cookies },
operation: (contextSpec) => fetchAuthSession(contextSpec),
});
const attributes = await runWithAmplifyServerContext({
nextServerContext: { cookies },
operation: (contextSpec) => fetchUserAttributes(contextSpec),
});
return {
currentUser,
session,
attributes,
};
}
AppRunnerのデプロイでは、環境変数にHOSTNAME=0.0.0.0
を指定しないとヘルスチェックに失敗する
node.jsが待ち受けるhostnameの影響で、環境変数にHOSTNAME=0.0.0.0
を指定しないとAppRunnerのヘルスチェックに失敗します。
apprunner_service.add_environment_variable(
"HOSTNAME", "0.0.0.0"
) # node.jsが待ち受けるhostnameの影響で、この設定がないとAppRunnerのヘルスチェックに失敗します。
参考文献
- webpack4の記事を見ながら実装していくとエラーしたので載せておく
- AWS 規範ガイダンス - Amazon Cognito と AWS Amplify UI を使用して既存の React アプリケーションユーザーを認証する
- Qiita - Next.jsとAWSで認証つきサイトを爆速でホストする(Next.js + Cognito + S3 + Cloudfront)
- Amplify UI - Authenticator
- TypeScript と Amplify JavaScript v6 を利用して Next.js アプリを構築する
- Next.js - How to deploy your Next.js application
- Next.js v13.4をAWS App Runnerで動かそうとしてハマった話