AmplifyだけでWebアプリを作ろうとしたが、バックエンドの開発体験が悪かったのでServerless Frameworkも併用した話
Qiita Advent Calendar 2023 「AWS AmplifyとAWS×フロントエンド」 11日目の記事です。
タイトル詐欺ですがServerless Frameworkにはほとんど触れません。ひたすらAmplifyを語ります。
Amplifyとバックエンド
AWS Amplify というとフロントエンドのイメージが強いと思います。Advent Calendarのタイトルにもフロントエンドと書いてあります。ですが、Amplifyは非常に多くの機能を持っており、バックエンドを含めWeb開発に必要な機能が一通り揃っています。
Google BardにAmplifyの機能を聞いたら次のように答えてくれました。
AWS Amplifyの機能を全て教えてください
AWS Amplifyは、モバイル、ウェブ、バックエンド開発を迅速かつ簡単に行うためのフルスタック開発プラットフォームです。Amplifyは、AWSの各種サービスと連携して、開発者がバックエンドのコードを記述することなく、モバイルアプリやウェブアプリを構築できるようにします。
Amplifyの主要機能は、以下のとおりです。
- バックエンド: Amplifyは、AWS Lambda、Amazon API Gateway、Amazon Cognito、Amazon DynamoDBなどのAWSの各種サービスを使用したバックエンド機能を提供します。これにより、開発者はバックエンドのコードを記述することなく、モバイルアプリやウェブアプリに認証、データベース、ストレージなどの機能を追加できます。
- フロントエンド: Amplifyは、AWS Amplify Console、AWS Amplify CLI、AWS Amplify JavaScript SDKなどのツールとライブラリを提供することによって、モバイルアプリやウェブアプリのフロントエンドの開発を支援します。これらのツールとライブラリは、認証、データベースアクセス、UIコンポーネントなどの機能を簡単に実装できるようにします。
- CI/CD: Amplifyは、AWS CodePipeline、AWS CodeDeployなどのサービスを使用したCI/CDパイプラインを提供します。これにより、開発者はモバイルアプリやウェブアプリのビルド、テスト、デプロイを自動化できます。
Amplifyの具体的な機能は、以下のとおりです。
- 認証: Amplifyは、Amazon Cognitoを使った認証機能を提供します。Amazon Cognitoは、モバイルアプリやウェブアプリのユーザー認証を簡単に行うためのサービスです。
- データベース: Amplifyは、Amazon DynamoDBを使ったデータベース機能を提供します。Amazon DynamoDBは、スケーラブルで耐久性のあるNoSQLデータベースサービスです。
- ストレージ: Amplifyは、Amazon S3を使ったストレージ機能を提供します。Amazon S3は、セキュートでスケーラブルなオブジェクトストレージサービスです。
- プッシュ通知: Amplifyは、Amazon Pinpointを使ったプッシュ通知機能を提供します。Amazon Pinpointは、モバイルアプリやウェブアプリへのプッシュ通知を送信するためのサービスです。
- マネージドサーバー: Amplifyは、AWS Lambdaを使ったマネージドサーバー機能を提供します。AWS Lambdaは、サーバーを管理することなく、コードを実行するためのサービスです。
- CI/CD: Amplifyは、AWS CodePipeline、AWS CodeDeployを使ったCI/CDパイプラインを提供します。
Amplifyは、モバイルアプリやウェブアプリの開発を迅速かつ簡単に行うための強力なツールです。Amplifyを使用することで、開発者はバックエンドのコードを記述することなく、モバイルアプリやウェブアプリにさまざまな機能を追加できます。
ということで、次のような構成のwebアプリを、Amplifyだけで構築することが出来ます。
ですが、残念ながら実際にやってみると開発体験がよろしくなかったので、最終的にはフロントエンドと一部のリソースはAmplifyで構築しましたが、バックエンドはServerless Frameworkを使って構築しました。
なぜ、Amplifyでバックエンドを作ることは開発体験が悪いのか
それでは、なぜAmplifyのバックエンド開発がツラいのかを個人的な偏見に基づき書いていきたいと思います。
バックエンドのコードが書きにくい。特にLambda
とにかくコレです。
Lambdaの階層深すぎ問題
Amplifyのバックエンドリソースはamplifyディレクトリの下に作られます。
そして、Lambdaのソースは以下のような場所に作られます。
- (root)/amplify/backend/function/[function name]/src
深くて触りづらいよ!
開発始める際にソースコードまでたどり着くのにうんざりします。
フォルダ構成が固定される問題
AmplifyのLambdaのフォルダ構成はこんな感じになります
[function name]
└── src/
├── index.js
└── package.json
package.json
をsrc
下に置きたくないですが、これは恐らく必須です。
場所を変える方法を知っている人がいたら教えて欲しいです。
TypeScriptでもindex.jsをsrc配下に置く必要がある問題
TypeScriptの場合、jsファイルはsourceではなくビルドした成果物になります。しかし、上記の構成は守る必要があるのでindex.js
をsrc
配下に出力することを強いられます。意味不明です。
公式ドキュメントでは、lib
配下にts
を作りsrc
配下にjs
を出力するように書いてありますが、かなり分かりにくいと感じています。
ビルドコマンドを書く場所が分かりにくい問題
TypeScriptの場合、前述の通りビルドしてjsファイルを出力する必要がありますが、ビルドコマンドを書く場所がプロジェクトルート直下のpackage.json
です。
階層の深いところで作業をさせておいて、ビルドコマンドだけは一番上なので、非常に混乱します。
(root)/
├── package.json <--- ここにビルドコマンドを書く
└── amplify/
└──backend/
└──function/
└──[function name]
└──/src
├── index.js
└── package.json
ビルドコマンドはこんな感じで書きます。
{
"scripts": {
"amplify:[function name]": "cd amplify/backend/function/[function name] && npx --package typescript tsc && cd -"
},
}
一番上に書くんですけど結局は深い所に移動してビルドして戻るのですよねぇ、、、
勝手にyarnする問題
amplify push
したときに、src配下のpackage.json
からパッケージをインストールしてくれるのですが、npm install
ではなくyarn
します。なんで?
どうして、こういう作りなのか?
これは私の想像ですが、Amplifyではバックエンドのコードを書くことはあまり想定していないのではないかと思います。最初にAIに聞いた回答にこう書いてあります。
開発者がバックエンドのコードを記述することなく、モバイルアプリやウェブアプリを構築できるようにします。
実際にAmplify StudioというWeb画面上の機能を使えば、簡単なAPIであればコードを書かずに構築できます。
つまり、人がコードを書かない前提なら人が開発しづらくてもいいよねってことです。
Amplifyのどの機能を使えばよいのか?
Amplifyでの開発に批判的なことを書いてきましたが、一部の機能が使いにくいだけで他の機能も使わないのはもったいないです。なので、個人的に使えると思う順にAmplifyの機能について書いていきます。(あまり知見がない機能には触れません)
フロントエンドのホスティング(Amplify Hosting)
- Amplifyといえばコレとも言える機能
- GitHubと連携して簡単にアプリを公開できるのが便利
- GitHubと連携しなくても、zipで固めてコンソール上でD&Dで投げ込むだけでも公開出来る
- GitHubのプルリクに対して簡単にプレビュー環境を作れるのも便利
- 裏でCloudFront+S3を使っているはずだけど隠蔽されている。このため素のCloudFrontと異なり、WAFをつけられない点は注意が必要
- 個人的にはCognitoにWAFをつけて認証時に不正アクセスを弾けばセキュリティを確保できると考えていますが、企業によってはセキュリティポリシーを満たせないかもしれません
- Amplify CLIで明示的にCloudFront+S3にホスティングすることも出来できますが、Amplifyを使うメリットがかなり失われるので微妙
- 最初期から要望として上がっているが未だにOpenなissue
aws-amplify
Node.jsのパッケージの
- フロントエンドのアプリ内で使用するNode.jsのパッケージ
- 以下のパッケージとは別物なので間違えないように注意
- @aws-sdk/client-amplify
- AWS-SDK。コード上からAmplifyのリソースを操作したいときに使う
- @aws-amplify/cli
- Amplify-CLI。コマンドラインで主にAmplifyのバックエンドのリソースを操作したりデプロイするときに使う
- @aws-sdk/client-amplify
- Auth(認証機能)が特に有用で、フロントエンドからCognitoで認証したい時によく使う
- Auth機能で認証して、Strage機能やAPI機能に対して認証情報付きで接続するのが基本になるかと
- 便利ではあるが拡張性は高くないので、細かい要件が求められる場合は汎用的なAWS-SDKを使ったほうがよい場合もある
ユーザー認証用のCognitoを作る機能 (Amplify Auth)
- ユーザー認証用にCognitoを作る機能
- 前述のNode.jsのパッケージがフロントエンド側の認証機能を提供するに対して、バックエンド側のリソースを作る機能
- Cognitoを作るだけなので自力で作れるなら恩恵は少ないかもしれないが、認証周りはある程度知識が必要なので、自動で作成と設定をしてくれるのはありがたい機能
- フロントエンド側で
aws-amplify
をセット使えば連携も簡単にできる
個人的には、ここから上の機能はあえて外す理由がなければ基本使う方針で問題ないと思います。
ストレージ用のS3を作る機能 (Amplify Strage)
- S3のバケットを作る機能
- 一元管理という意味では便利だし、Amplifyで作れば認証の設定等も自動でやってくれるので楽
- 欠点としては1環境で1バケットしか作れないので足りなくなるケースが多い。また、S3はAWSの基本的な機能であり簡単に作れるし世の中の知見も多いので、Cognitoと比べるとAmplifyで作成することにこだわるメリットは薄い
API機能
- AppSync + Lambda、API Gateway + Lambda、API Gateway + ECSなどでAPIを作れる機能
- 前述の通りコードを書くと辛い。コードを書かないor最小限の簡単なAPIならありだと思う
Function機能
- Lambdaを単体で作る機能
- API同様にコードを書くので辛いが、APIと違ってコードを書かないで済むユースケースは無いと思うので、使うケースはかなり限られると思う
カスタムAWSリソース機能
- CDKを使ってAWSリソースを自由に作れる機能
- やはりコードを書くので辛い
- 個人的な意見としては、Amplifyの中でCDKを書くほどのスキルがあるなら、CDKをメインで使いその中でAmplifyを作るほうが開発しやすいと思う
まとめ
少なくともフロントエンドのホスティングはとても便利なので、Amplifyの使いやすいところをいい感じに使って開発を楽にしよう!
また、Amplify Gen2では改善されている項目も多いと思うので、別途使ってみて記事にしたいです。(未定です)
宣伝
宣伝です。12/13にAWSのウェビナーで発表をさせていただきます。Amplifyを使った事例を紹介します。
※ この記事のような後ろ向きな内容は自重するので、ご安心ください。
過去に書いたAmplify記事
参考に貼っておきます。思ったより多かったので閉じておきます
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion