概要
筆者が当初ざっくりと考えていたのは「Next.jsをLambdaにデプロイしたい・デプロイを自動化したい」だったのですが、これに結構苦戦したのでそのまとめと言ったところです。
この記事はaws初学者には意味がわからないと思うので、以下に登場ワードを書いておくのでまずはそちらをある程度調べてから挑戦した方がいいかと思います。
- S3
- Lambda
- API Gateway
- Route53
- ACM
- IAM
- Role
- Policy
注意点
まず、ただ単に「Next.jsで作ったものを公開したい」だけであれば、AWSに限定する必要は全くないです。ZEIT Nowを使えばいいと思います。
同じようなことをするためのライブラリでServerless Nextjs Componentと言うのがあります。今回やることはこれに近いので、実際問題これを使ってもいいのかもしれません。そこは読者さんご自身で考えてみてください。
一応僕の意思決定としては、
- わりと新しいツールなのでハマった場合すごく面倒そう・即時解決しない可能性までありそう
- ツールの使い方で時間取られるくらいなら、AWS直接使った方が勉強にもなるしマシ
- デプロイ全自動化したいので、aws-sdkで書いた方が繋ぎ込むときに簡単そう
などの理由から今回aws-sdkを使って直接操作する方針を取りました。
また、今回紹介する方法はカスタムドメインを使いますが、API Gatewayだけでもいけるじゃん?と思っている場合ソースコードのURLを書き換えなければいけない箇所が出てきます。API Gatewayにはstage
と言う概念があることが関係します。簡単に言うと、API Gatewayのルートパスに対してのパスマッピングができず、/static/xxx.png
などが/<stage>/static/xxx.png
と言うパスでしか公開できないので、ソースコード中の静的ファイルへのリンクを変更しなければいけません。
AWSにデプロイするファイルは?
Next.jsは、public
ディレクトリを特別扱いしていて、public
ディレクトリに配置されたファイルはその構造のまま配信されると言うルールがあります。
a. public/**/*
Next.jsは、次のようなファイルを生成します。
b. .next/serverless/pages/**/*.html
c. .next/serverless/pages/**/*.js
d. .next/static/**/*
bは、静的ファイルを返すだけのページの場合に出力されます。それに対して、cはサーバーサイドでのレンダリングが必要なページに対して出力されるファイルです。dは、splitされたソースコードや、各ページのロード後の動的コンテンツ用のスクリプトなどです。
上のうち、a, b, dはS3にアップロードし、cは加工後にlambdaにデプロイします。
加工とは?
Next.jsが出力する、各ページ向けのjsファイルは、例えばlambda
だったりzeit now
などと関係がないインターフェイスで出力されます(#6173 issuecomment)。なので、lambdaのhandler向けに加工しなければlambdaでは使えません。それは、#6070 issuecommentだったり、next-aws-lambdaを使うことで解決します。
Route53
筆者の場合、Google Domainsで購入したドメインをAWSで使っています。Google DomainsでドメインのネームサーバーをAWSのネームサーバーに変更し所有者の確認が取れれば、あとは基本的にAWS側で使えます。
API Gatewayから使えるようにするため、事前にACMで証明書の発行が必要です。
API Gatewayとの結合
S3, Lambdaにデプロイしたリソースは、API Gatewayを使ってAPIのパスをコントロールしていきます。
API Gatewayで特別扱いしなければいけないファイルがあります。それは_error.js
です。
これは、エラー(例えば404など)に対する画面をハンドリングするファイルなので、全てのパスに対して_error.js
のLambda関数と統合する必要があります。{proxy+}
のようにリソースパスを指定します。動的パスの場合もこれを用いてリソースパスを設定しLambda関数と統合します。
それが終わったら、任意のステージにデプロイし、カスタムドメインを設定すれば完了です。
おわりに
まだあまりNext.js + Lambda界隈は盛り上がっていないような気がしますが、個人的には今後にかなり期待しています。
この記事ではコードを添付していないですが、理由としてはまだいくらか手作業の部分が残っていて完全自動化できていないためです。(特にIAM, Role, Policy, Route53まわり)
もし需要がありそうであれば、コードを整えて共有しようかなと言う気持ちはありますがとりあえずは個人で利用するだけなのでいったん手作業も容認かなあと言うところです(...