カスタムリソース
Amplify Gen 2では、AWS Cloud Development Kit (AWS CDK)を使用してカスタムAWSリソースをAmplifyアプリに追加できます。AWS CDKは、create-amplifyワークフローの一部としてデフォルトでインストールされます。AWS CDKはオープンソースソフトウェア開発フレームワークであり、TypeScriptなどの使い慣れたプログラミング言語を使用してクラウドアプリケーションリソースを定義します。
AWS CDKはAmplifyアプリ内で使用して、Amplifyが標準でサポートしていない以上のカスタムリソースと構成を追加できます。例えば、開発者はCDKを使用してRedisキャッシュをセットアップし、カスタムセキュリティルールを実装し、AWS Fargate上にコンテナをデプロイしたり、その他のAWSサービスを使用したりできます。
AWS CDKコードを通じて定義されたインフラストラクチャは、Amplifyアプリバックエンドと一緒にデプロイされます。これはAmplifyのシンプルさとCDKの柔軟性を組み合わせて、さらなるカスタマイズが必要な状況に対応します。
Amplifyコードファーストの開発者体験を使用して、既存またはカスタムCDKコンストラクトをAmplifyアプリのバックエンドに追加できます。
既存のCDKコンストラクトの追加
AWS CDKには多くの既存コンストラクトが付属しており、Amplifyバックエンドに直接追加できます。例えば、Amazon Simple Queue Service (Amazon SQS)キューとAmazon Simple Notification Service (Amazon SNS)トピックをバックエンドに追加するには、amplify/backend.tsファイルに以下を追加します。
import * as sns from 'aws-cdk-lib/aws-sns';import * as sqs from 'aws-cdk-lib/aws-sqs';import { defineBackend } from '@aws-amplify/backend';import { auth } from './auth/resource';import { data } from './data/resource';
const backend = defineBackend({ auth, data});
const customResourceStack = backend.createStack('MyCustomResources');
new sqs.Queue(customResourceStack, 'CustomQueue');new sns.Topic(customResourceStack, 'CustomTopic');backend.createStack()の使用に注意してください。このメソッドはバックエンドに、カスタムリソース用の新しいCloudFormationスタックを作成するよう指示します。複数のカスタムスタックを作成でき、任意のスタックに複数のリソースを配置できます。
CDKコンストラクトの定義
上記のように、既存のAWS CDKコンストラクトをAmplifyバックエンドで直接使用できます。ただし、一般的なコンストラクトのいくつかのパターンを繰り返す可能性があります。カスタムコンストラクトを使用すると、共通パターンを再利用可能なコンポーネントにカプセル化できます。これにより、ベストプラクティスを実装し、開発を加速し、アプリケーション全体で一貫性を保つことができます。
一般的なユースケースは、Lambda関数とAmazon SNS、Amazon Simple Email Service (Amazon SES)を組み合わせたカスタム通知コンストラクトを作成することです。
このAWS CDKコンストラクトはAmazon SNSとLambdaを使用した疎結合通知システムを実装します。1つのLambda関数からSNSトピックに通知メッセージをパブリッシュでき、トピックにサブスクライブされた別のLambdaを使用して非同期でメッセージを処理できます。
主なコンポーネントは以下の通りです:
- 通知メッセージを受信するAmazon SNSトピック
- Amazon SNSトピックにメッセージをパブリッシュするLambda関数
- トピックにサブスクライブされた2番目のLambdaで、メッセージを処理してAmazon SES経由でメールを送信します
パブリッシャーLambdaは、メールの件名、本文テキスト、および受信者アドレスを含むメッセージをパブリッシュできます。メーラーLambdaはSNSトピックからメッセージを取得し、実際のメール送信を処理します。
CustomNotificationsカスタムCDKコンストラクトは次のように定義できます:
import * as url from 'node:url';import { Runtime } from 'aws-cdk-lib/aws-lambda';import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';import * as sns from 'aws-cdk-lib/aws-sns';import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';import { Construct } from 'constructs';
// message to publishexport type Message = { subject: string; body: string; recipient: string;};
type CustomNotificationsProps = { /** * The source email address to use for sending emails */ sourceAddress: string;};
export class CustomNotifications extends Construct { public readonly topic: sns.Topic; constructor(scope: Construct, id: string, props: CustomNotificationsProps) { super(scope, id);
const { sourceAddress } = props;
// Create SNS topic this.topic = new sns.Topic(this, 'NotificationTopic');
// Create Lambda to publish messages to SNS topic const publisher = new lambda.NodejsFunction(this, 'Publisher', { entry: url.fileURLToPath(new URL('publisher.ts', import.meta.url)), environment: { SNS_TOPIC_ARN: this.topic.topicArn }, runtime: Runtime.NODEJS_18_X });
// Create Lambda to process messages from SNS topic const emailer = new lambda.NodejsFunction(this, 'Emailer', { entry: url.fileURLToPath(new URL('emailer.ts', import.meta.url)), environment: { SOURCE_ADDRESS: sourceAddress }, runtime: Runtime.NODEJS_18_X });
// Subscribe emailer Lambda to SNS topic this.topic.addSubscription(new subscriptions.LambdaSubscription(emailer));
// Allow publisher to publish to SNS topic this.topic.grantPublish(publisher); }}PublisherのLambda関数コードは以下の通りです:
// amplify/custom/CustomNotifications/publisher.tsimport { PublishCommand, SNSClient } from '@aws-sdk/client-sns';import type { Handler } from 'aws-lambda';import type { Message } from './resource';
const client = new SNSClient({ region: process.env.AWS_REGION });
// define the handler that will publish messages to the SNS Topicexport const handler: Handler<Message, void> = async (event) => { const { subject, body, recipient } = event; const command = new PublishCommand({ TopicArn: process.env.SNS_TOPIC_ARN, Message: JSON.stringify({ subject, body, recipient }) }); try { const response = await client.send(command); console.log('published', response); } catch (error) { console.log('failed to publish message', error); throw new Error('Failed to publish message', { cause: error }); }};EmailerのLambda関数コードは以下の通りです:
// amplify/custom/CustomNotifications/emailer.tsimport { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';import type { SNSHandler } from 'aws-lambda';import type { Message } from './resource';
const sesClient = new SESClient({ region: process.env.AWS_REGION });
// define the handler to process messages from the SNS topic and send via SESexport const handler: SNSHandler = async (event) => { for (const record of event.Records) { const message: Message = JSON.parse(record.Sns.Message);
// send the message via email await sendEmail(message); }};
const sendEmail = async (message: Message) => { const { recipient, subject, body } = message;
const command = new SendEmailCommand({ Source: process.env.SOURCE_ADDRESS, Destination: { ToAddresses: [recipient] }, Message: { Body: { Text: { Data: body } }, Subject: { Data: subject } } });
try { const result = await sesClient.send(command); console.log(`Email sent to ${recipient}: ${result.MessageId}`); } catch (error) { console.error(`Error sending email to ${recipient}: ${error}`); throw new Error(`Failed to send email to ${recipient}`, { cause: error }); }};CustomNotificationsCDKコンストラクトは、各インスタンスに異なるプロパティを使用して、Amplifybackendに1回以上追加できます。
// amplify/backend.tsimport { defineBackend } from '@aws-amplify/backend';import { auth } from './auth/resource';import { data } from './data/resource';import { CustomNotifications } from './custom/CustomNotifications/resource';
const backend = defineBackend({ auth, data});
const customNotifications = new CustomNotifications( backend.createStack('CustomNotifications'), 'CustomNotifications', { sourceAddress: 'sender@example.com' });
backend.addOutput({ custom: { topicArn: customNotifications.topic.topicArn, topicName: customNotifications.topic.topicName, },});コミュニティCDKリソース
Construct Hubは、再利用可能なインフラストラクチャコンポーネントのコミュニティ駆動カタログです。これは開発者がAWS CDKの再利用可能なパターンを発見して共有する場所で、AWSによって管理されています。
さらに、AWS CDKを使用したサンプルプロジェクトリポジトリには、再利用可能なCDKコンストラクトの多くの例が含まれています。
これらのリソースを使用して、Amplifyアプリで使用できるカスタムCDKコンストラクトを作成できます。