🌐

SvelteKitをAWSでサーバーレスでSSRする方法

2024/05/03に公開

導入

SvelteKitアプリケーションをAWSにデプロイしたい!
そんな時に取れる選択肢はいくつかあります。

サーバーを常時稼働させるつもりであればEC2 + adapter-nodeの組み合わせで事足りるでしょう。
また、SPAであればAmplyfy + adpter-staticを使用すればサーバーレスで運用できます。

しかし、サーバーレスでSSRしたいとなると標準のadapterだけでは対応できません。
ここではコミュニティで作成された2つのadapterを紹介します。

なおいずれの方法もAWS-CDKを使用するため、マシンに事前にAWS CLIのセットアップアクセス認証を済ませておく必要があります。

MikeBild/sveltekit-adapter-aws

https://github.com/MikeBild/sveltekit-adapter-aws

architecture

AWS-CDKを用いてCloudfront,S3,API GateWay,Lambdaにリソースをデプロイします。
静的リソース(デフォルトでは/_app/*)はS3とCDNの組み合わせで高速に配信され、サーバー処理はLambdaが担います。

詳細な導入はREADMEを参照いただきたいのですが、手順は簡単です。

  1. 既存のSvelteKitプロジェクトに、adapterを下記のコマンドでインストールします。
npm i -D sveltekit-adapter-aws
  1. sveltekit-adapter-awsを使用するようにsvelte.config.jsを書き換えます。
+ import { adapter } from 'sveltekit-adapter-aws';
import preprocess from 'svelte-preprocess';

export default {
  preprocess: preprocess(),
  kit: {
+     adapter: adapter({
+       autoDeploy: true,
+     }),
  },
};
  1. npm run buildをすると自動的にデプロイが実行され、表示されたURLにアクセスするとページが表示されます。

…はずなのですが、試しに実行してみたところこんなエラーが出ました。

Resource handler returned message: "The runtime parameter of nodejs14.x is no longer supported for creating or updating AWS Lambda functions. We recommen
d you use the new runtime (nodejs20.x) while creating or updating functions. (Service: Lambda, Status Code: 400, Request ID: ...)" (RequestToken: ..., HandlerErrorCode: InvalidRequest)

以下のIssueでも言及されているようですが、古いバージョンのNodeを使用しているためエラーが発生する場合があるようです。

https://github.com/MikeBild/sveltekit-adapter-aws/issues/45

回避方法が分からなかったため、ここではもう一つのadapterを紹介しておきます。

jill64/sveltekit-adapter-aws

https://github.com/jill64/sveltekit-adapter-aws

私が作成したadapterです。

こちらも詳細な導入はREADMEを参照ください。

まずは最小構成から解説します。
導入手順は1つ目のadapterとほぼ同じです。

  1. 既存のSvelteKitプロジェクトに、adapterを下記のコマンドでインストールします。
npm i -D @jill64/sveltekit-adapter-aws
  1. @jill64/sveltekit-adapter-awsを使用するようにsvelte.config.jsを書き換えます。
+ import adapter from '@jill64/sveltekit-adapter-aws';
import preprocess from 'svelte-preprocess';

export default {
  preprocess: preprocess(),
  kit: {
+     adapter: adapter({
+       deploy: true,
+     }),
  },
};
  1. npm run buildをすると自動的にデプロイが実行され、表示されたURLにアクセスするとページが表示されます。

加えてこのadapterは利用シチュエーションに合わせて4つの異なるアーキテクチャから選択できることが特徴です。順番に解説していきたいと思います。

1. lambda-mono

https://github.com/jill64/sveltekit-adapter-aws/tree/main/docs/lambda-mono#readme

lambda-mono-architecture

単一のLambdaに全てのアセットをアップロードして、全てのリクエストを処理します。
使用するにはadapterのconfigに以下を追加します。

adapter({
    deploy: true,
+    architecture: 'lambda-mono'
})

オプションでCDNを前段に追加することができます。
追加するにはadapterのconfigに以下を追加するだけです。

adapter({
    deploy: true,
    architecture: 'lambda-mono'
+    cdn: true
})

高速なデプロイが可能なのでテストや開発用に適していますが、静的アセットの処理がLambdaを介するため遅くなってしまいます。
CDNを追加すれば多少マシになりますがプロダクションには向きません。

2. lambda-s3

https://github.com/jill64/sveltekit-adapter-aws/tree/main/docs/lambda-s3#readme

lambda-s3-architecture

前述したMikeBild/sveltekit-adapter-awsに近いアーキテクチャです。
使用するにはadapterのconfigに以下を追加します。

adapter({
    deploy: true,
+    architecture: 'lambda-s3'
})

またarchitectureオプションを選択しない場合はこれがデフォルトになります。

MikeBild/sveltekit-adapter-awsとの違いはLambdaの関数URLを使用することです。
これによりAPI Gatewayが不要になっているほか、Lambdaのストリーミングレスポンスが使用可能になっています。

基本的なユースケースに対応できますが、SSGのアセットがLambdaから配信されるため250MBのサイズリミットがあることが唯一のデメリットとなります。
そのため、大規模なSSGを検討している場合は以降に紹介するアーキテクチャの採用が必要です。

3. edge-bundled

https://github.com/jill64/sveltekit-adapter-aws/tree/main/docs/edge-bundled#readme

edge-bundled-architecture

サーバー処理にLambda@Edgeを使用してエッジロケーションでサーバーを実行します。
使用するにはadapterのconfigに以下を追加します。

adapter({
    deploy: true,
+    architecture: 'edge-bundled'
})

この場合、SSGのアセットはS3から配信されるため事実上無制限のSSGが可能です。
また、Lambda@Edgeを使用するため良好なTTFBが期待できます。

ただし、Lambda@Edgeのプラットフォームの制限からストリーミングレスポンスは使用できません。
また、実行環境もLambdaに比べて貧弱なので、このアーキテクチャはSSG主体のアプリケーションに向いている構成と言えるでしょう。

4. edge-unbundled

https://github.com/jill64/sveltekit-adapter-aws/tree/main/docs/edge-unbundled#readme

edge-unbundled-architecture

Lambda@EdgeとLambdaを併用してリクエストを処理します。
使用するにはadapterのconfigに以下を追加します。

adapter({
    deploy: true,
+    architecture: 'edge-unbundled'
})

この場合も、SSGのアセットはS3から配信されるため事実上無制限のSSGが可能です。
またサーバー処理にはLambdaを使用するため、ストリーミングレスポンスの利用やサーバースペックの向上が可能です。

ただし、アーキテクチャが複雑になるためデバックが少し難しくなるほか、デプロイにも時間がかかります。
また、リクエストがLambda@Edgeを通ってからLambdaに転送されるためTTFBもわずかに悪化してしまいます。

大規模なSSGと重めのサーバー処理を両立させたい場合はこのアーキテクチャが適しているでしょう。

総括

いかがだったでしょうか。
この記事がAWSでSvelteKitを運用しようとしている方の助けになれば幸いです。

またjill64/sveltekit-adapter-awsについてバグや不明点がありましたらぜひ以下からIssueを開いてください。

https://github.com/jill64/sveltekit-adapter-aws/issues

Discussion