🐁

AWS LambdaでSPAを配信する

2022/08/27に公開

はじめに

Goの go:embed を使うとファイルを埋め込んでバイナリを作ることができると知りました。
単一バイナリにできるってことはLambdaにデプロイしてSPAを配信することできるんじゃない?と思い作ってみました。

AWSLambdaとは

簡単に説明を。
FaaS(Function as a Service)と呼ばれるものでサーバー管理が不要でアプリ開発に集中できちゃうよというものです。(だと思っています。)
詳しい説明はぜひ公式ドキュメントをご確認お願いします。

SPA

お試しなのでSPAはちゃちゃっとviteを使います。
以下のコマンドでReact×TypeScriptの初期状態を利用します。

yarn create vite

(私はあまりクライアント詳しくないですのでもろもろの説明とかは割愛で...)

Lambda実装

ディレクトリ構成は以下になります。

lambda
├── frontend
│   ├── dist <- 成果物 
│   ├── index.html
│   ├── node_modules
│   ├── package.json
│   ├── public
│   ├── src
│   ├── tsconfig.json
│   ├── tsconfig.node.json
│   ├── vite.config.ts
│   └── yarn.lock
├── go.mod
├── go.sum
└── main.go

frontend配下にてyarn buildを実施するとfrontend/distにSAPアプリが生成されます。
それをmain.goにて以下のように記述することでgo build時にバイナリとして含まれるように設定します。

package main

//go:embed frontend/dist/*
var assets embed.FS

AWSCDKで管理

以下のコマンドでAWSCDKプロジェクトを作成します。

cdk init app --language typescript

ディレクトリ構成は以下のようになります。
lambdaというディレクトリにGoによる実装を含めます。

lambdspa
├── README.md
├── bin
├── cdk.json
├── cdk.out
├── jest.config.js
├── lambda <- Lambda本体実装
├── lib
├── node_modules
├── package.json
├── test
├── tsconfig.json
└── yarn.lock

今回はお試し実装なのでお手軽に lambda-urlsを使うことにします。

ちゃんとやる?ならAPI Gateway通してキャッシュを有効にするとよさそうですね。

デプロイ

cdk deploy

https://<url-id>.lambda-url.<region>.on.awsという形式でアクセス可能となります。

いざアクセス

Vite + Reactの画面が表示されました!

計6回にかけてjsやらcssやらsvgやら取得できていますね。

たまたまだと思いますがLambdaのログを見ると1起動で全部配信してくれたみたいです。

コールドスタート51.85ms
jsファイル78.21ms
svgファイルは1msの実行になっていますね。
(パフォーマンス的に良いか悪いかはよくわかりません!笑)

お掃除

cdk destroy

おわりに

無事デプロイでき動くことが確認できました!

ま、Lambda使うならNest.jsの方が良さそうですし、
AWS使ってSPAアプリ配信するならS3×CloudFrontの方が良いですよね。
(コスト計算していないのでなんとも言えませんが...)

コードはこちらに置いておきます。 takokun778/lambdspa

おまけ

BrotliとかGzipで圧縮すればバイナリサイズもうちょっと小さくできるかなぁ...

参考

Discussion