🎣
Serverless Next.js Component のISR実装を読み解く
AWS Amplify ConsoleでNext.jsのプロジェクトをデプロイすると Serverless Next.js Component のインテグレーションによってAWS Lambda リソースが最大4つ作成される(ソースコードはエクスポートできる)
- Default Lambda@Edge for Next CloudFront distribution
- API Lambda@Edge for Next CloudFront distribution
- Image Lambda@Edge for Next CloudFront distribution
- Next.js Regeneration Lambda
それぞれのAWS Lambdaが行っていることを読み解くとVercelが自社で構成しているシステムの外観が分かるのではないかと思って眺めてみた
(CloudFrontのコンソールでどのパスで呼び出されているのかわかる)
Default Lambda@Edge
serverless-next.js/default-handler.ts at serverless-nextjs/serverless-next.js
- 静的なレスポンスを返せる場合はS3 bucketからアセットファイルを読み取りレスポンスを返す
- SSRが発生する場合はHTMLのレンダリングまでをこのLambdaのコンテキストで行う
- ISRの処理が発生する場合このLambdaが "Next.js Regeneration Lambda" を着火させるためのSQSにメッセージを送信する
API Lambda@Edge
serverless-next.js/api-handler.ts at serverless-nextjs/serverless-next.js
- API Routes用のLambda
- シンプルに該当するパスのNode.jsスクリプトが実行されるだけ
Image Lambda@Edge
serverless-next.js/image-handler.ts at serverless-nextjs/serverless-next.js
- next/image 専用のLambda
- 内部的には sharp を使って画像をオプティマイズしている
- 対象のURLがビルド済みのS3 bucketにあるファイルではなくインターネット上の画像ならこのタイミングで fetch() してダウンロードする
Next.js Regeneration Lambda
serverless-next.js/regeneration-handler.ts at serverless-nextjs/serverless-next.js
- ISRを実現するバックエンド
- こいつだけ仲間外れでCloudFrontからではなく他のLambdaがSQSに送信したメッセージを受信することで実行される
- やっていることは次のレスポンス用にSSGした結果をS3 bucketに書き出しておくのが主
- ここで作成されたレスポンス結果のHTMLファイルに revalidate から計算されたExpire する時刻がメタ情報にセットされて、Default Lambda@Edgeはリクエストを返す時についでにそれを参照して再生成の命令をSQSへ出すのか決める
まとめ
- 思ったよりシンプル。アプリケーション開発者としては
packages/libs/lambda-at-edge/
を理解するだけでよさそう - Serverless ComponentはServerless Frameworkのプラグインみたいなものかと思っていたけど違った。単体で使えるようにしたツールという位置付けだった
- デプロイ処理を見る時は
packages/serverless-components/nextjs-component
を参照する。Nextプロジェクトの構造を解析して適切なAWSリソースを作成してくれている。ここを読んでいたら自分のアプリケーションでうまく動作しない問題を発見できた - GitHubスターが2.5kもあるのにコントリビューター全然いなくて困ってるらしい
Discussion