AWS SAMをTypeScriptにて利用する際のつまづきポイント
AWS Lambdaでアプリケーションを構築する際に、構成管理ツールとしてAWS SAMの利用は一般的かと思います。
今回AWS SAMを本格的に利用する機会がありましたが、いくつか、つまずくポイントがありました。
問題の直接的な解決となる記事も多くなかったため、まとめて残しておきたいと思います。
以下、私が遭遇した問題点と、その解決方法を列挙します。
TypeScriptが前提となりますが、他のプログラミング言語でも問題の構造は同じかと思います。
※なお、記事執筆時点(2025/11)時点の情報ですので、将来的に課題が解決されている可能性もあります。
AWS SAM は内部でnpmを利用している。そのため、pnpmやyarnに特化した設定でビルドが失敗する可能性がある。
仕様
AWS SAM利用時には、アプリケーションのbuildでsam buildコマンドが実行されます。
このコマンドは、内部ではnpmを利用しています。
そのため、プロジェクトの構成管理ツールでpnpmやyarnなどを利用している場合、npmで使えない設定が存在すると、sam buildは失敗します。
問題
私のケースでは、pnpmでmonorepoを構成していました。
pnpmでの共通パッケージを定義し、その共通パッケージを読み込む場合、以下のようにpackage.jsonに記載します。 (共通packageとして、foo,barを、アプリケーションにて読み込む場合)
この時workspaceという設定は、npmでは存在しないため、ビルドに失敗します
{
"dependencies": {
"foo": "workspace:*",
"bar": "workspace:*",
}
}
対処方法
AWS SAMの公式ドキュメントに設定が記載されていますが、build方法にて、makefileの方式を採用します。
内部でnpmを利用するAWS SAMのbuild方法ではなく、独自でビルド方式を定義するということです。
Makefileを準備します。Makefileの設定には命名規則があり、build-${template.ymlで定義した関数名}とする必要があります。
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.12
Metadata:
BuildMethod: makefile
build-HelloWorldFunction: #←命名を揃える必要あり
cp *.py $(ARTIFACTS_DIR)
cp requirements.txt $(ARTIFACTS_DIR)
python -m pip install -r requirements.txt -t $(ARTIFACTS_DIR)
rm -rf $(ARTIFACTS_DIR)/bin
sam buildのartifactがローカルに存在すると、sam localコマンドで起動した際にそのartifacnを参照する
仕様
sam では、ローカル開発時にはsam local、deploy時にはsam deployコマンドを実行します。
これらのコマンドを実行する前に、sam buildコマンドが必須となります。
sam buildコマンドにより生成される、.aws-samディレクトリ配下のartifactを参照するためです。(sam localについては、このディレクトリが存在しない場合には、アプリリソースそのものを参照します。)
公式ドキュメントには以下の通りに記載されています。
When using sam deploy, the AWS SAM CLI deploys your application’s build artifacts located in the .aws-sam directory. When you make changes to your application's original files, run sam build to update the .aws-sam directory before deploying.
If your application doesn’t have a .aws-sam directory and your function uses an interpreted language, the AWS SAM CLI will automatically update your function by creating a new container and hosting it.
If your application does have a .aws-sam directory, you need to run sam build to update your function. Then run sam local start-api again to host the function.
問題
利用開始当初、この参照先リソースの関係性が理解できておらず、sam local実行前のsam build実行を忘れておりました。
そのため、アプリケーションソースコードに変更反映->sam localで起動をしても、ソースコードに加えた変更が反映されません。
この課題は当初本当に原因がわからず、aws samの利用をやめようかと考えました笑
対処方法
結局、上記の.aws-samディレクトリを削除することで対応しました。
また、Makefile方式に切り替えたことで、この問題は発生しなくなりました。
localでは再現できないAWS本番の機能がある。API GatewayへのBinaryData送信や、API GatewayでのCognitoの認証検証など
仕様
AWSクラウド上で動作する機能のうち、aws samでのローカルでは利用できない機能があります。どのような機能が利用できないのか全体はわかっていません。
ですが、AWS SAMでは、AWSクラウドの機能全てをローカルで利用できるわけではないと頭の片隅に置いておくだけでも、スタックする可能性が低くなると思います。
私の場合には、以下のような機能が、ローカルでは利用できませんでした。
API Gatewayでの認証機能
Cognitoと連携し、Cognito未認証のユーザーにはAPI Gatewayにてリクエストを拒否する機能です。
Binary Dataの処理
API Gatewayに対して、multipart/form-data を指定して、音声データをアップロードしようとしましたが、ローカルでは、502のエラーが発生します。
$ sam local start-api
[snipped]
UnicodeDecodeError while processing HTTP request: 'utf-8' codec can't decode byte 0xff in position 5782: invalid start byte
2023-05-16 07:15:50 127.0.0.1 - - [16/May/2023 07:15:50] "POST /whatever HTTP/1.1" 502 -
※補足
- 一般的にはAPI Gatewayに直接ではなく、S3にアップロードが推奨されますが、処理時間の短縮とアップロードサイズが大きくないため、直接API Gatewayへのファイル添付でアップロードする方式としています
- 私が利用していたAPI Gateway HTTP APIでは、BinaryDataのuploadは対応しています。同じくREST APIの場合にも、追加設定をすることで直接のBinaryDataのuploadに対応します。
対処方法
それぞれワークアラウンドとして次のような方法を採用しました。
-
API Gatewayでの認証機能
→ local実行時のみ有効となる認証フローを作成し代替 -
Binary Dataの処理
→ AWS SAMの起動ではなく、Honoアプリケーションを起動して対応
※補足)
- 詳細は割愛しますが、API Gateway + Lambdaの方式で、TypeScriptの関数を実行するのではなく、Lambda上でHonoを起動する方式としていたため、このワークアラウンドが採用可能でした。
- また、以下の設定を採用すると、BinaryDataも処理できる模様です(私の環境では処理できませんでした。)
内容は以上となります。
少しでも参考になれば幸いです!
Discussion