Next.js をAWSにデプロイする Amplify vs Serverless

SHARE
はじめに
Next.js アプリケーションのデプロイ先の候補として Vercel が真っ先に挙げられますが、料金などの色々な都合でほかの場所にホスティングしたいこともあると思います。
SSG (Static Site Generation) で利用する場合は、幅広い選択肢がありますが、SSR (Server Side Rendering) と ISR (Incremental Static Regeneration) を使いたい場合の選択肢は、それほど多くありません。
AWSに SSR可能な Next.js アプリケーションをデプロイするメジャーな2つの方法 AWS Amplify と Serverless Next.js Plugin (Component) を紹介します。
サーバーレスなSSRとISR
Next.jsのさまざまなレンダリング形態と特徴については、本記事では深掘りしませんが、SSRとISRについてざっくりと触れます。
SSRは、文字通り、サーバーサイドでHTMLを書き出します。これによって、ブラウザの負荷を下げたり、データベースアクセスなどをサーバー側に隠蔽する効果も期待できます。
Webの長い歴史の中では、CGIという言葉が今よりも一般的に使われていた時代から、サーバーサイドレンダリングが当たり前でした。それから、ブラウザの進歩にともないクライアントサイドでレンダリングするSPAが盛り上がった時期もあります。「サーバーを立てる」とかいう表現をすることもありますが、サーバーというものは、コンピュータをたちあげて、プロセスを立ち上げて、リクエストが来るまでずっとスタンバイしていなければいけません。なので、自分のサーバーにNext.jsのプロセスを立ち上げておけば、SSRの完成です。
サーバーレスな世界では、AWS Lambda などの、リクエストが発生したときだけ起動するコンピューティングリソースを使います。これによって、サーバーをずっと立ち上げておく必要も無いし、そのサーバーを見守る必要も無くなります。
ISRはもう少し複雑になります。生成したHTMLをストレージ上に保存しておかなければいけません。そこで、AWS S3 への読み書きも発生することになります。
Amplify も Serverless Next.js Plugin も、どちらも、裏側で使われるリソースは似た構成になります。
CloudFront、 Lambda@Edge、S3 といったリソースが緊密に連携することで、SSRやISRを実現します。
とくに Lambda@Edge のメカニズムは重要なので、事前に学習しておいたほうが良いでしょう。
Amplify か Serverless framework か
Amplify
Amplifyは、AWSが提供する、フルスタックなアプリケーションを構築するためのフレームワークです。ですので、Next.jsのためだけのものではありません。Amplifyを使うと、認証、データベース、API、プッシュ通知など、アプリケーション開発に必要な機能がフルスタックで提供されます。裏側では、認証= AWS Cognito といった具合に、よく知られているAWSリソースが使われますが、Amplifyによって抽象化されます。また、CloudFormation によってコード化されるので、 Infrastructure as Code の利点を享受できます。
Amplifyそのものが一癖も二癖もあるので、もし深く使う場合は、予習が必要なのですが、ホスティングだけなら、マウスぽちぽちだけで気軽に試せないこともないです。
Next.jsアプリケーションのデプロイは、具体的には、Amplifyのなかの Amplify Hosting を使います。
やりかた
以下のページが参考になります。
公式ドキュメント Amplify Hostingを利用したサーバーサイドレンダリングアプリをデプロイ
クラスメソッドさんのブログ AWS AmplifyでNext.jsのISRを試してみる
通常は Amplify CLI を使うのですが、Next.jsのデプロイに関しては、CLIがなくても、AWSコンソール上でポチポチクリックするだけでデプロイできるようになります。
Amplifyのデプロイには、以下のような注意点があります。
- (良くも悪くも)手動デプロイには対応していない
- つまり、手元のコードをアップロードすることはできない
- 必ずGitHubなどのコードリポジトリと連携させなければいけない
- GitHub / Bitbucket / GitLab / AWS CodeCommit が対応しているようです
- SSGかSSRかを自動判別します
- package.json の scripts.build の内容を読み取って、そのアプリケーションのビルド方法を自動的に判別します。
next build && next export
になっているとSSGと判定します。
Serverless framework
Serverlessは、AWS Lambdaを使ったアプリケーション開発を支援するためのフレームワークです。(AWS以外のクラウドプロバイダにも対応する。)
事前に Serverless framework の予習が必要です。Serverless CLI のセットアップと、AWS認証情報のセットアップをしておく必要があります。
Next.js をAWSにデプロイするスキームは、Serverless のひとつのプラグイン(コンポーネント)として提供されます。
以前はServerlessの機能拡張は「プラグイン」と呼ばれていましたが、現在では、「コンポーネント」という別の形式がメインになっているようです。ドキュメント上でも、コンポーネントとプラグインという用語が混在しているのですが、Next.jsのデプロイは「コンポーネント」になっているようです。また、現時点で公式ドキュメント上には、「ベータバージョンの”コンポーネント”をベースにして作られている」旨が書かれています。
やりかた
公式ドキュメントを参照してください。
Serverless Next.js Plugin
serverless.yml を記述して、コマンド一発ですぐにデプロイできます。
CLIがうまく動かないときは・・・以下のコマンドでインストールして
npm install -g @serverless/cli
以下のコマンドで起動します。
components-v1
---
比べてみて
両者を見てみて、共通する特徴があります。
- 対応する機能が限られる
- 詳細は各ページを参照されたし
- 現時点で、どちらも、Next.js 11 まで対応
- 最新版は 12 です
- middleware など12特有の機能が使えない
- Next.js 12 ではビルド高速化がなされています。したがって、11は遅い
- ただし、全く非対応というわけではなく、実験的で部分的な対応がされているように見受けられます。
- CloudFront、Lambda@Edge、S3、SQSなどを利用する点は同じ
- ISRのための regenerationファンクションが独立しており、SQS経由でページ生成リクエストを受け取ります。
- Infrastructure as Code の原則にしたがって、生成されたAWSリソースを直接編集しないようにしましょう
- AWSリソースを作ったり消したりするので、適切な権限が必要
- デプロイの遅さ
- Vercel では1分未満でデプロイが完了するが・・・
- 私の体験では、Amplifyでは10分程度、serverlessでは5分程度かかる。この差は、CloudFormationを使っているかどうかに起因するのかもしれません。
ちがい
両者ともCloudFrontやLambdaなど、同じようなパーツを使っているものの、中身が違うことに注意が必要です。
「Next.jsをデプロイするんだから、同じものでしょ?」と思われるかもしれませんが、そうではないのです。そのNext.jsを呼び出したりするためのコードやアーキテクチャが必要で、それらに違いが出てくる余地があります。実際、Next.jsをLambda@Edgeにポン置きすることは不可能です。
- カスタムドメインとDNS
- Amplify: 外部のDNSサーバーも利用できる
- serverless: Route53を使う必要がある
- ドメイン
- Amplify:
amplifyapp.com
のサブドメインが与えられる - Serverless:
cloudfront.net
のサブドメインが与えられる
- Amplify:
- ベーシック認証
- Amplify: ある。AWS Consoleから設定できる
- Serverless: ある。
serverless.yml
で設定できる
- カスタマイズ性
- Amplify: 深掘りできていないが、おそらく、CloudFrontやLambda@Edgeの設定は変更できない
- Serverless:
serverless.yml
で、あらかじめ用意されたパラメータを設定できる。
- CI/CD
- Amplify: リポジトリと連携した自動デプロイのみ
- Serverless: CI/CDは自分でやらなければいけない。自由度が高いとも言える。
トラブルシューティング
Amplifyのネガティブな感想として、そのブラックボックス感はよく挙げられます。エラーの原因がつかみにくく、手出しできない場所に起因するエラーだったり、遠回りしたけどけっきょく権限の問題だったりすることも。いったん動いたあとの運用フェーズでも、この問題はつきまとうと想像できます。AWSは予告無くツールチェーンのアップデートをするでしょうし、とくに裏側であれば、ユーザーには何もできません。さいあく、Amplifyをやめることを想定しておかなければいけません。
その点、Serverless のほうが、そういったブラックボックスは少ないし、設定可能なパラメータも多いです。Amplifyよりもコントロールを握れるので、問題が起きても自分でロールバックしやすいのではないでしょうか。
開発体制やサポート体制
私的な印象ですが、Amplifyは、まだ若く、開発が続けられている最中のフレームワークです。未解決のIssueも多く溜まっています。一方、Serverlessそのものは、もっと前からあり、ある程度枯れています。それゆえに、開発の勢いは弱まっていると思います。
どちらの方法を取るにしても、Next.jsとの連携はVercelに遅れをとるということを念頭に置きましょう。
Vercelとしては、どんどん新機能や破壊的変更を試してNext.jsを成長させたい思惑があるでしょう。セキュリティのための更新もあると思います。一方、それ以外のホスティングプロバイダは、もっと安定したホスティングを望むはずです。しかし、Vercelとの間で契約をしているわけではなく、後追いでVercelホスティングのエミュレーションをしているだけにすぎないのです。ここにジレンマがあります。この点は重要だと思います。
おわり
このへんで終わりにします。
これからNext.jsでアプリケーションを構築したり、デプロイをするさいの参考になれば幸いです。

itoudium
Webエンジニア