Serverless Frameworkを使わず、Nuxt3でSSR構成（CloudFront + Lambda + S3）をする方法

# 対象者
- 自分と同じAWS初心者
- 「俺たちは感覚でAWSを触っている」状態の人
- バックエンドなんもわからんけどAWSへのデプロイを控えている人
- ~~Next全盛の今NuxtのSSRで頑張っている人~~

# なぜやろうと思ったか？

「Nuxt3 SSR AWS」で検索するとAmplifyを使うパターンか、Serverless Frameworkを使うパターンしか検索結果に引っかからないからです。

Amplifyは融通が効かない部分があるため今回は使いたくないし、
かといってServerless Frameworkはv4から有料になるしv3は２０２４年でサポート終了するらしいし...

ということで、自前で一からCloudFront + Lambda + S3構成を作ってみたのですが、
できるまで丸二日間スタックしたので皆さんが同様の状況にならないようにまとめました。

# 前提

1. Nuxt SSR構成でビルドできる状態であること
1. 調べればすぐ出てくるようなデプロイ用の設定は終わっていること
    1. `nuxt.config.ts`の`nitro`の設定に`preset:aws-lambda`が設定されているとか
1. AWSの権限が適切であること
1. （任意）AWS CLIがインストールされていること

## 今回作成する構成
![名称未設定ファイル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/b2b2e6ab-4675-52c7-7acc-f7b0f3d5cac6.png)


# Nuxt側対応

## Nuxtのプロジェクトをビルドする

プロジェクト直下で
```
npm run build
```
してください。

エラーが出ず、`.output`フォルダ内に`public`と`server`の二つのフォルダができていれば多分OKです。

## serverをzipファイル化

serverディレクトリ内まで移動してserverフォルダ全体をzipファイル化しましょう。
（macじゃない人はコマンド違うと思うので各々で調べたり手動でやるなりしてください。）
```
cd ./server
zip -r server.zip ./
```

# AWS側対応

## S3（静的コンテンツ）
`.output/public`フォルダ内の静的コンテンツを格納するためのS3を作成します。
S3の`バケットを作成`からデフォルト設定でぽちぽちしていけばOKです。

終わったら手動で`.output/public`フォルダをアップロードするか、
下記コマンドでアップロードしてください。
```
aws s3 sync .output/public s3://{バケット名}
```

## Lambda
Lambdaの`関数の作成`からLambdaを作成します。
基本的にデフォルト設定で、
- Node.js
    - v20.x
- アーキテクチャ
    - x86_64

であればOKです。（アーキテクチャはどちらでも良いかもしれませんが念の為）

### Lambda：コードソース設定
コードタブ内の`コードソース`の右側にあるアップロード元指定をzipファイルにし、先ほど作成した`server.zip`をアップロードします。
![スクリーンショット 2024-07-23 17.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/7147e321-193a-141a-69b4-ba904faef5ae.png)

### Lambda：ランタイム設定
コードタブの下の方にランタイム設定があるので、ハンドラを指定しましょう。
`index.handler`と入力すればOKです。
（各々のパスによって変わるのでindex.mjsがある場所を確認してください。）
![スクリーンショット 2024-07-29 9.51.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/4447432b-5bc1-3d53-63cd-342662c84de3.png)


### Lambda：一般設定
設定タブ内にある一般設定項目を編集します。
メモリがデフォルトだと少なすぎるので増やしておきましょう。
そのほかの設定はお好みで変更してください。
![スクリーンショット 2024-07-23 17.34.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/ad9201f3-25a3-f493-e8de-41b3dab0bd8d.png)

### Lambda：関数URL
同じく設定タブ内の関数URLを設定します。

今回はシンプルにアクセスできれば良いため認証設定はNoneで作成しました。
![スクリーンショット 2024-07-23 17.37.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/b4172955-234a-925e-0e62-7b80d87810d2.png)

### Lambda:環境変数
設定タブ内の環境変数から編集します。
.envファイル内の設定を持ってきましょう。
詳細は割愛します。


## CloudFront
`ディストリビューションを作成`から作成を進めます。

オリジンドメインにLambdaで作成した関数URLを指定する以外はデフォルト設定でOKです。
![スクリーンショット 2024-07-23 17.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/0df42255-0743-ed22-f95a-fd037b3cd9ce.png)

### CloudFront：オリジン設定（S3）
静的コンテンツを格納したS3にアクセスできるようにオリジン設定を行います。
オリジンタブの`オリジンを作成`からオリジンドメインに作成したS3を指定します。
![スクリーンショット 2024-07-23 17.43.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/f5b0ba11-07a0-7ff4-27a3-48726b718770.png)

S3を指定すると自動でオリジンアクセス項目が表示されるのでOACに変更して今回のS3のための新たなOACを作成して設定してください。
![スクリーンショット 2024-07-23 17.44.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303906/30edd819-b750-0f78-ff7b-a9b190af667b.png)

作成後にS3用のポリシーが生成されるので、`S3バケットアクセス許可に移動`リンクから、S3側に戻ってポリシーを更新しておきましょう。

### CloudFront：ビヘイビアの作成
特定のパスの際にS3内のコンテンツへのアクセスができるようにするため、ビヘイビアで振り分けを作成します。

`ビヘイビアを作成`から、
`/_nuxt/*`と`/*.*`の2パターンのパスのビヘイビアをそれぞれ作成してください。
`オリジンとオリジングループ`の指定はともに静的コンテンツのS3です。


## 確認
ここまで対応できたら、CloudFrontのドメインにアクセスしてみましょう。
作成したサイトが確認できればOKです！


# 参考文献
今回の内容をServerless Frameworkベースで対応したパターンです。
大変参考になりました。

https://www.fourier.jp/blog/nuxt3-ssr-cloudfront-lambda