Nuxt.jsで作った静的サイトをCloudFront + S3で配信するときのTips
いくつかハマりポイントがあったのでメモを残しておく。
前提
Nuxt.jsに限らずReactやVueで作られたSPAでも同じ要領だと思われるが、実ファイルのディレクトリ構成は以下のようになっているはず。
code: ディレクトリ構成例
.
├── 200.html
├── _nuxt
│ ├── LICENSES
│ ├── 1234567890abcdef1234.js
│ ├── abcdef1234567890abcd.js
│ └── img
│ ├── 1234567.svg
│ └── abcdefg.png
├── dashboard
│ └── index.html
├── favicon.ico
└── index.html
Nuxtで作ったSPAを開く際、CloudFrontで何も設定していない状態だと、ブラウザでindex.htmlを直指定してもNuxtのRoutingがうまく動作せずにエラーになる。リソースを指定せずにRoot URLを開いても、Access Deniedになる。
CloudFrontのDefault Root Objectの設定
CloudFront + S3 で配信する場合、Default Root Objectを指定しない状態だと、下記の通りWebアプリが正しく動作しない。
hogehoge.com --> NG
hogehoge.com/index.html --> NG
そのため、CloudFrontのDefault Root Objectにindex.htmlを指定することで、 https://hogehoge.com へのアクセスが index.html に飛ばされ、NuxtのRoutingも正常動作するようになる。 エラーページの設定
Rootへのアクセス ( hogehoge.com ) は上記のDefault Root Objectの設定で対応できるが、SPAで hogehoge.com/dashboard のような場所に遷移した場合に問題になる。
CloudFrontは /dashboard というディレクトリへのアクセスに対しては、デフォルトでは 403 を返す。一方でNuxt.jsのRouterを正しく動作させるためには/dashboard へのアクセスで /dashboard/index.htmlを返せるようにしなければならない。
そこで、CloudFrontの Custom Error Response を利用すれば良い。設定例は以下の通り。
https://gyazo.com/b465b724acbd69a664d676d29677e9c4
これで/dashboardへのアクセスが正しく動作するようになる。
コンテンツにCustom Headerを付与
Webアプリは通常、いくつかのセキュリティ対策が求められる。例えばクリックジャッキング対策のために html のResponse HeaderにX-Frame-Options: DENYを付与する、など。
ここで問題になるのが、どうやら エラーページとして配信したページにLambda@Edgeが効かない ということ。つまり、上記の例だとhogehoge.com/dashboardにアクセスした際にLambda@Edgeの関数が呼び出されず、Custom Headerが付与されない。
これに関しては解決方法が見つかっておらず、対応検討中…。
(追記)
解決した。
Viewer Response、つまりキャッシュがヒットした場合はLambda@Edgeの関数が実行されないため、下記の通りエラーページのキャッシュのTTLを 0 に設定すれば良い。パフォーマンスが犠牲になるが仕方ない。
https://gyazo.com/5649fa3875c94040fbab0e392eb50802
/icons/hr.icon