CloudFront + S3 で対峙する初歩的なエラー:_next 配下呼ばれないぞ、、
内容
今回の投稿はFLINTERSブログ祭りの記事です。テーマは #CloudFront #S3 #SPA です。
CloudFront + S3 構成でフロントページにアクセスした際、_next配下が読み込まれなかった際の初歩的なエラーとそれに伴う今後の展望への備忘録を記載します。
今回の事象の背景
- Next.js 13 を用いてCSRでフロントページを作成
- システム構成
- フロントページのビルドファイルは、S3バケットAに配置する
- CloudFrontの設定にて
- /hoge の場合、S3バケットAに遷移させる
- /huga の場合、S3バケットAに遷移させる
- それ以外のパスはALBへ遷移させる
エラーが起きるまでの手順
- Next.js 13 でCSRを用いてフロントページ作成
- next.config.js にて、
output: 'export'
を指定したのち、next buildを実行し、ビルドファイル(out配下のファイル群)を生成 - S3バケットAへout配下のファイル群を配置
- CloudFrontの設定にて /hoge, /huga に対して、S3バケットAへ遷移するように設定(S3バケットのポリシー設定もする)
- 今のままでは、/hoge/index.htmlでは画面描画できるはずだが、/hogeや/hoge/、/hugaや/huga/では描画できないので、CloudFront Functionsで下記のように設定
async function handler(event) {
const request = event.request;
const uri = request.uri;
// Check whether the URI is missing a file name.
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check whether the URI is missing a file extension.
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
- デフォルトのパス(*)にて、ALBへ遷移するように設定
-
https://example.com/hoge のようなURLへアクセスした際、画面が描画されない
- _next/配下がALBの方に向かっていた
エラー内容
_next/配下がALBに向かっていたのは、ビルドファイルのhoge/index.htmlを見ると明らかで、例えば<script src="/_next/static/chunks/xxxxxx.js"></script>
のように、src先が絶対パスになっている。
そのため、/_next/static/chunks/xxxxxx.js は https://example.com/_next/static/chunks/xxxxxx.js に遷移してしまう。
エラー対処法
CloudFrontの設定で、/_next/* に対して、S3バケットAを指定してあげれば良い。
今後の懸念点
想定展開
今後、フロントページを増やす際、今回とは別で切り出してフロントページを構築し、別S3バケットBへビルドファイルを格納したいとなった場合のCloudFront設定を少し懸念している。
例えば、現状は下記のようになっているが、今後[懸念]にもあるように、/piyoに対して新たなS3バケットを指定したいとなった時に、/_next/* に指定するS3バケットをどうするか、という問題がある。
現状
- /hoge
- S3バケットA
- CloudFront Functions A
- /huga
- S3バケットA
- CloudFront Functions A
- /_next/*
- S3バケットA
- *
- ALB
今後[懸念]
- /hoge
- S3バケットA
- CloudFront Functions A
- /huga
- S3バケットA
- CloudFront Functions A
- /piyo
- S3バケットB
- CloudFront Functions A(Aと内容は同じなので、Aを指定)
- /_next/*
- S3バケットA? S3バケットB? // ここが懸念点
- *
- ALB
解決策?
next.config.js にて、assetPrefix を指定すると、ビルドしたindex.htmlのリンク先が変更になる。
参考:https://nextjs.org/docs/app/api-reference/next-config-js/assetPrefix
例えば、assetPrefix="/a" とすると、index.htmlの内容が<script src="/a/_next/static/chunks/xxxxxx.js"></script>
のようになる。
そのため、
フロントページA(/hoge, /huga)のものは、assetPrefix="a"
フロントページB(/piyo)のものは、assetPrefix="b"
とし、新たな_next配下用のS3バケットCを作成し、
/a パスに フロントページAの _nextディレクトリを、
/b パスに フロントページBの _nextディレクトリを配置すれば良いのではと考えている
今後[解決策?]
- /hoge
- S3バケットA
- CloudFront Functions A
- /huga
- S3バケットA
- CloudFront Functions A
- /piyo
- S3バケットB
- CloudFront Functions A(Aと内容は同じなので、Aを指定)
- /a/_next/*
- S3バケットC
- /b/_next/*
- S3バケットC
- *
- ALB
どなたか良い解決策があったら教えてくださいm
Discussion