5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js(SSG)のアプリをAWS Amplifyにデプロイする際の注意点まとめ - 2024

Posted at

はじめに

Next.jsのSSG(Static Site Generation)で作成したWebアプリケーションをAWS Amplifyにデプロイする際、いくつかハマりポイントがありました。ネットで調べてもPage Router時代の古い情報は多く、App Routerの場合の情報が少なかったため、忘れないよう記事にしておこうと思います。

フレームワーク・ライブラリ等のバージョンは執筆時点でのlatestもしくはstableなバージョンを利用しています。参考にされる際はこの点ご留意ください。

SSGとは

Static Site Generationの略です。Next.jsで実装したアプリケーションをnext buildでビルドする際に静的なコンテンツ(HTML, CSS)に落とし込み、それらをCDNでキャッシュして配信することで高速なレスポンスを実現できます。静的コンテンツと聞くと利用シーンが限定されそうに聞こえますが、外部へのデータフェッチを行うアプリケーションであってもSSGを利用することができます。(ソースコード側で少し工夫は必要)
https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation

ハマりポイント

next.config.jsの設定

Next.jsのレンダリング方式は、デフォルトではSSRが適用されています。これをSSGにするためにはnext.config.jsに追記が必要です。

/** @type {import('next').NextConfig} */
const nextConfig = {
+    output: "export",
+    images: { unoptimized: true },
};

export default nextConfig;

まずoutput: "export",ですが、これを設定した状態でnext buildでビルドを行うと、outというディレクトリに成果物が生成されます。outには静的アセットのみが出力されており、これらをWebサーバーに置けばそれだけで配信が可能になります。next.jsのリポジトリを確認したところ、以下の記述がありました。

  /**
   * The type of build output.
   * - `undefined`: The default build output, `.next` directory, that works with production mode `next start` or a hosting provider like Vercel
   * - `'standalone'`: A standalone build output, `.next/standalone` directory, that only includes necessary files/dependencies. Useful for self-hosting in a Docker container.
   * - `'export'`: An exported build output, `out` directory, that only includes static HTML/CSS/JS. Useful for self-hosting without a Node.js server.
   * @see [Output File Tracing](https://nextjs.org/docs/advanced-features/output-file-tracing)
   * @see [Static HTML Export](https://nextjs.org/docs/advanced-features/static-html-export)
   */

https://github.com/vercel/next.js/blob/canary/packages/next/src/server/config-shared.ts#L884

次にimages: { unoptimized: true },ですが、これは「画像の最適化を行わない」という設定になります。
画像の最適化、というのはnext/image<Image>タグを用いた最適化のことを指しています。<Image>タグはHTMLの<img>を拡張したもので、デバイスごとに画像サイズを最適なものに変更したり、画像読み込みのタイミングを調整したりと、裏で色々してくれます。
https://nextjs.org/docs/pages/building-your-application/optimizing/images
https://nextjs.org/docs/pages/api-reference/components/image#unoptimized

しかし、この最適化処理はサーバーで行われます。SSGはnext build実行時に生成された静的アセットを配信するため、ページ表示時にサーバーで行われる処理を実施することはできない?ようです。SSGなページで<Image>を使うと、画像が読み込まれませんでした。loaderを変更することで解消できるとの記事も確認しましたが、今回はそこまでするモチベーションはなかったので、単純に最適化をしない設定にすることで回避しました。
https://zenn.dev/kisukeyas/scraps/6fd8bf7e63e4a3
https://ebisu.com/note/next-image-ssg/

amplify.ymlの修正

$frontend.artifacts.baseDirectory.nextにする必要がありました。

amplify.yml
frontend:
    artifacts:
-        baseDirectory: out
+        baseDirectory: .next

SSGの成果物はoutディレクトリに出力されるのでoutを指定するものだと思っていたのですが、どうやらそうではないみたいです。後述しますが、Next.js v14以降を利用したSSGアプリケーションをホスティングする場合、Amplfy側にはSSRアプリケーションの静的コンテンツとして配信する必要があるみたいです。

Amplify Hostingの設定

Amplifyにアプリをデプロイすると、Amplify側でアプリケーションのフレームワークプラットフォームを自動で検出してくれます。
スクリーンショット 2024-10-09 7.10.04.png

ここが個人的に混乱した箇所なのですが、フレームワークをNext.js - SSRで設定しないといけないようです。
なぜSSGなのにSSRで設定するのか?となりますが、どうやらSSRアプリケーション内の静的コンテンツとしてindex.htmlが配信される形になってるみたいです。実際、ブラウザの開発者ツールで確認したところ、_next/static配下に成果物が保存されていたので、静的コンテンツとして認識されていることが確認できます。
スクリーンショット 2024-10-09 7.14.07.png

プラットフォームWEB_COMPUTEを設定します。通常、Amplifyで静的コンテンツを配信する際はWEBを指定するようですが、Next.js v14以降を利用したSSGアプリケーションはWEB_COMPUTEを使ってくださいとの記述がAWS CLIの公式ドキュメントにありました。

If you are deploying an SSG only app with Next.js version 14 or later, you must set the platform type to WEB_COMPUTE .

ちなみに、フレームワークをNext.js - SSG、プラットフォームをWEBに、amplify.ymlのbaseDirectoryをoutにしてデプロイしたところ、_next/staticにコンテンツが保存されてました。まとめると、以下2パターンのどちらかであればデプロイに成功するっぽい?

  • パターン1
    • framework: Next.js - SSG
    • platform: WEB
    • amplify.yml: $frontend.artifacts.baseDirectory: out
  • パターン2
    • framework: Next.js - SSR
    • platform: WEB_COMPUTE
    • amplify.yml: $frontend.artifacts.baseDirectory: .next

余談ですが、フレームワークプラットフォームはGUIから変更できないため、変更が必要な場合はCLIから実行する必要があります。

# change platform
$ aws amplify update-app --app-id <value> --platform WEB_COMPUTE
# change framework
$ aws amplify update-branch --app-id <value> --branch-name <value> --framework 'Next.js - SSG'

SSGなのにSSRを指定する、というのはユーザーの混乱を招く仕様なので、いずれ仕様変更されるんじゃないかと想像してます。
根本の原因としては、Next.jsがv14からビルドコマンドの仕様を変更したことが起因してるようです。以下の記事がとても参考になりました。
https://zenn.dev/ototrip/articles/tech-nextjs-amplify-4

さいごに

いつもNext.jsを使う際はSSRのことばかり考えているので、SSGを使うのは初めてでした。正直さくっとできるかなと高を括ってましたが、細かいところで色々ハマったのでいい勉強になりました。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?