Amplify Hosting × Next.js Dynamic Routesのリダイレクト設定を自動化する
こんにちは、じゃがです 👋
本記事は AWS AmplifyとAWS×フロントエンド Advent Calendar 2022、18日目の記事です
概要
Next.js の Dynamic Routes を使ったアプリケーションを Amplify Hosting でホストする際には、適切なリダイレクト設定が必要です
毎度ページを足すたびにリダイレクト設定を手動で書き換えるのは大変なので、ビルド時に自動でリダイレクト設定を更新しちゃいましょう!
ソースコードは以下で見ることができます
Dynamic Routes に必要なリダイレクト設定
なぜリダイレクト設定が必要か
以下では jaga810/amplify-hosting-redirect-setting-automation のルートディレクトリで作業しているものとします
$ tree pages
pages
├── _app.tsx
├── _document.tsx
├── index.tsx
├── posts
│ ├── [id]
│ │ └── index.tsx
│ └── index.tsx
└── settings
├── private
│ └── index.tsx
└── public
└── index.tsx
pages/[id]/index.tsx
の部分が Dynamic Routes を利用している部分になります
ビルドを実行します
npm run build # next build && next export
out ディレクトリに以下のようなファイル群が生成されます
$ tree out -P *.html -I _next
out
├── 404.html
├── index.html
├── posts
│ └── [id].html
├── posts.html
└── settings
├── private.html
└── public.html
これを Amplify Hosting でホストし、/posts/123
のようなパスにアクセスすると、以下のように /404.html
にリダイレクトされてしまいます
/posts/123
にアクセスを試みても、実際にホストされているファイルは posts/[id].html
であって posts/123.html
ではありません
そのため、リクエストパスに該当するファイルが見つからず、404 ページにリダイレクトされてしまうのです
この問題を回避するためにはどうしたら良いのでしょうか?
Dynamic Routes のためのリダイレクト設定
上述の問題を回避するためには、下記のようなリダイレクト設定が必要です
赤い枠線で囲まれた箇所は、 /posts/<id>
(<id>
は任意の文字列) にマッチするリクエストを、/posts/[id]
にリダイレクトする、という設定です
たとえば /posts/123
へのリクエストが /posts/<id>
にマッチしてリダイレクトされ、 /posts/[id].html
がユーザーに返されることになります
ちなみに、Amplify Hosting のリダイレクト設定において、<id>
はプレイスホルダーと呼ばれています
リダイレクトを使用する - AWS Amplifyホストする
今回の用途のように、特定のパス構造でファイルが見つからない場合にリダイレクトをかけたい場合にプレイスホルダーが重宝します
また、プレイスホルダーは変数のように扱うことができ、リダイレクト先を動的に指定することもできます
毎回手作業は辛いよ...
このように、pages
配下に Dynamic Routes を利用するページを足す度、Amplify Hosting のリダイレクト設定を追加していく必要があります
手動で更新するとどうしてもヒューマンエラーが起こってしまいますし、何より面倒です
定型作業は自動化しちゃいましょう!
自動化
リダイレクト設定を更新するシェルスクリプト update_amplify_redirect_setting.sh
を、Amplify Hosting のビルド時に postBuild
フェーズで実行するようにします
update_amplify_redirect_setting.sh
Amplify Hosting は JSON ファイルを用いてリダイレクト設定を更新することができます
これを利用して、以下の2ステップでリダイレクト設定を更新します
- リダイレクト設定が記された
redirect_settings.json
の生成 - AWS CLI を用いた
redirect_settings.json
の内容の反映
ちなみに、1. を詳しく見ると、以下のような設定を行っています
-
/pages
配下のファイル群に対応した 200 リダイレクトの設定 - アプリで必要な 301 リダイレクトの設定
- 想定外のパスへのアクセスに対する 404 リダイレクトの設定
- Trailing Slash の対応
このように、Dynamic Routes 用の設定以外にも、ホスティングに必要なさまざまなリダイレクト設定を足しています
そのため、Dynamic Routes を利用しているパスも、そうでないパスも、リダイレクト設定の対象としています
手元で出力されるリダイレクト設定を確認したい場合は、以下のコマンドを実行してください
chmod +x update_amplify_redirect_setting.sh
./update_amplify_redirect_setting.sh
AWS CLI がインストールされていない環境の場合は以下のようなエラーが出ますが、リダイレクト設定の JSON ファイル自体は出力されるので無視いただいて大丈夫です
./update_amplify_redirect_setting.sh: line 97: /usr/local/bin/aws: No such file or directory
Amplify Hosting のビルド時にスクリプトを自動実行
amplify.yml
Amplify Hosting では、アプリケーションのルートディレクトリ直下に amplify.yml
を置くことでビルド設定をカスタマイズできます
ビルド設定の構成 - AWS Amplifyホストする
IAM の設定
デフォルトの設定ではビルドパイプライン中で aws amplify update-app
を実行する権限がありませんので、足してあげましょう
- General 開き、Edit を押す
- Create new role を押す
- IAM の画面に移動するので、初期設定のまま遷移してロールを作成する(ただし、Amplify のビルドパイプラインが利用する IAM の権限を絞りたい場合は、適切な権限を付与するようカスタマイズしてください)
- 作成したロールを使うよう設定する
まとめ
Amplify Hosting における Dynamic Routes のリダイレクト設定と、その自動化についてご紹介しました 🚀
amplify.yml
と update_amplify_redirect_setting.sh
をコピペし、IAM の設定をすればすぐ使うことができると思いますので、是非ご活用ください〜!
おまけ
コスト
Amplify Hosting は API をコールしただけでは課金されないため、本記事で紹介したリダイレクト設定の自動化を足すことによる追加料金はありません
AWS Amplify の料金 | ウェブとモバイルのフロントエンド | Amazon Web Services
特定のブランチでのみリダイレクト設定の更新を行う
本記事で紹介した設定をすると、Pull Request プレビューや main ブランチ以外の環境へのデプロイ時にもリダイレクト設定の更新が走ります
pages
配下にページを追加していく場合は問題ありませんが、既存のページ構成を大きく変更したい場合などはご注意ください
dev ブランチでページ構成を変えたものがリダイレクト設定に反映されてしまい、main ブランチが紐づく本番環境で意図しないリダイレクトが起こってしまう可能性があります
(Amplify Hosting のリダイレクト設定はブランチごとに設定できるわけではないため)
main ブランチでのみリダイレクト設定を更新したい場合は、AWS_BRANCH
環境変数を利用すると良さそうです
ビルド設定の構成 - AWS Amplifyホストする
postBuild:
commands:
- if [ "${AWS_BRANCH}" = "main" ]; then ./update_amplify_redirect_setting.sh; fi
参考
この記事は偉大な先人の肩に乗って執筆しました
- 【Next.js x Amplify】リダイレクト設定が面倒なので一括で出力するシェルスクリプトを書きました【書き換えて、リダイレクト】 - Qiita
- Amplify HostingでのNext.jsのDynamic Routesの設定
最後に
私が所属する Nstock では、ソフトウェアエンジニアを募集中です🔥
どんな会社なのか気になる、という方はお気軽にご応募 or Twitter DM ください〜!
Discussion