Help us understand the problem. What is going on with this article?

Next.jsアプリをLambda@Edgeで超簡単にSSRできるserverless-next.jsのご紹介

Next.js をSSR対応でホスティングしたいなら Now を使うのが定石だと思います。
Next.jsとNowはどちらも ZEIT社 が開発しているため一緒に使った際のDXは大変良いものです。
しかし、AWS内で完結できるならそうした方が嬉しい事が多いのでいい方法はないかと調べた所、
serverless-next.jsというServerless Componentのプラグインがよさそうだったのでご紹介したいと思います。

以下のドキュメントの要点をまとめつつ、掘り下げたものです。
https://github.com/danielcondemarin/serverless-next.js/
https://serverless.com/blog/serverless-nextjs/

serveless-next.js

機能と特徴

  • SSRをLambda@Edgeで行う
  • Dynamic Routing (Next.js 9からの機能)と互換性のあるルーティングを行う
  • Automatic pre-rendering (Next.js 9からの機能) のサポート

    • SSR不要なページはNextによって静的HTMLに書き出される
    • serverless-next.jsはこれをS3にホスティングする
    • アクセスがあるとLambda@EdgeがS3にリクエストをフォワードする
  • Nextが生成したファイル(jsのチャンクファイル等)のホスティング

    • Lambda@Edgeを通さず、CloudFrontを通してS3でホスティングする
  • static フォルダ内のアセットのホスティング

    • 上記と同様CloudFrontを通してS3でホスティングする

これらの機能をゼロコンフィグで行える。

デプロイについて

  • pageはLambda@Edgeに、静的ファイルはS3にデプロイされる。
  • デプロイは通常1分以内に終わる。
  • 初回のみディストリビューションの有効化に時間がかかるが、それ以降は高速に終わる。

アーキテクチャ

Cloud Frontに3つのキャッシュビヘイビアが作成される。
a.png

  • static => S3へ (Lambda@Edgeなし)
  • _next => S3へ (Lambda@Edgeなし)
  • Default(*) => Lambda@Edge

Defalut(*) の挙動

① SSRされるページ(getInitialPropsありのページ) を処理する
② Automatic pre-renderingされたHTMLページをS3にフォワード
③ favicon.ico などのルート直下のファイルをS3にフォワード

②,③をする理由

ファイルごとにディストリビューションを作成しないため。
(ちなみにCloudFrontは最大25個しかディストリビューションを作れない)

デプロイする

serverless.yml
myApp:
 component: serverless-next.js
デプロイ
$ npx serverless

削除
$ npx serverless remove

これだけでとりあえず https://<文字列>.cloudfront.net のようなURLでアクセス可能な状態になる。

ドメインを割り当てたいなら

serverless.yml
myApp:
  component: serverless-next.js
  inputs:
    domain: "example.com"
    # domain: ["sub", "example.com"] # サブドメインもこんな感じで指定できる

舞台裏

CloudFormationは使ってません

  • 高速なデプロイのため
  • CloudFormationは記述できるリソースが200個までと制限がある

ほとんどの作業はserverless-component の以下の4つが行っており、
serverless-next.js はこれらのオーケストレーションを単純に行っているだけ。

1つ懸念があるとすると

serverless-next.js自体はbetaではないが、その裏側のserverless-compoentがよく見るとbetaではある。
https://github.com/serverless/components

実際にリソースの作成を行っている箇所のソースを見てみる

serverless-nextjs-component/serverless.js

serverless-componentはymlによるCloud Formationによる管理だけでなく、
プログラマティックにリソースを操作することも可能。
例えば S3の例は以下。

const bucket = await this.load('@serverless/aws-s3')

// deploy
await bucket({
  accelerated: true
})

// upload directory
await bucket.upload({ dir: './my-files' })

// upload file
await bucket.upload({ file: './my-file.txt' })

S3のリソース作成
https://github.com/danielcondemarin/serverless-next.js/blob/master/packages/serverless-nextjs-component/serverless.js#L272

Cloud Frontのリソース作成
https://github.com/danielcondemarin/serverless-next.js/blob/master/packages/serverless-nextjs-component/serverless.js#L407

Lambda@Edgeのリソース作成
https://github.com/danielcondemarin/serverless-next.js/blob/master/packages/serverless-nextjs-component/serverless.js#L391

その他メモ

デプロイの度にCloudFrontディストリビューションをdestroy/createせず、updateしたい場合

.serverless ディレクトリでリソースのstateが管理されており、これを一緒にgitでcommitしておく必要がある。

※ ちなみに現在 serverlessチームはstate管理をリモートストレージでできるように改修を行っているので、将来的にはgit管理しなくてよくなる。


以上です

now.sh以外にNext.jsアプリをサクッとデプロイできる選択肢が増えるのは嬉しい事なので、今後も開発が続く事を願っています。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away