Next.jsで「ISR・SSGをしない」という選択肢
Next.jsで小規模なアプリケーションを実装する場合の構成について色々と模索したところ,
- ISRは諦めてSSRに寄せる
- FargateやApp RunnerでNext.jsを動作させ,前にCDNを配置する
という構成が良さそうだ,という結論に至ったので,その根拠について書きます.
ISRを行う場合の構成
Next.jsのIncremental Static Regeneration(ISR)をawsで動かす際に,Serverless Nextjsを用いた以下のような構成をよく見かけます.
CloudFront --> Lambda@Edge --> APIサーバ --> DB
CloudFrontへのアクセスをトリガーにして,Lambda@Edgeでレンダリング処理を行いレスポンスを返す構成ですね.
この構成では,API Routesや getServerSideProps
等の処理はLambda@Edgeで動作し,フロントエンドで必要なデータはAPIサーバを通して取得します.
ただ,小さなアプリケーションを実装するケースで「Lambda@Edgeからデータを読むのにわざわざAPIを通す必要がある」という点に不満がありました.
データ取得にAPIを通す理由
これには「Lambda@EdgeからVPCリソースにアクセスできない」という仕方のない理由があります.
エッジ関数に対する制限 - Amazon CloudFront
VPC 内のリソースにアクセスするように Lambda 関数を設定することはできません。
とはいえ,RDSへのインターネットからのアクセス許可を設定するのにはセキュリティ上の懸念がありますし,RDS Proxyではそもそもそういった設定は不可能だったりします.
RDS プロキシは、データベースと同じVirtual Private Cloud(VPC)内に存在する必要があります。プロキシにはパブリックにアクセスできませんが、データベースにはパブリックにアクセスできます。
Amazon RDS Proxy の使用 - Amazon Relational Database Service
そうなってくると,API越しにアクセスする方がベターということになります.
インターネットからのアクセスを許可しても良いようなAPIを切り出せさえすれば,APIからVPCのリソースへアクセスすることは自由なので,技術選定にもある程度自由が効きます.
CloudFront+Lambda@Edge構成のデメリット
しかし,CloudFront+Lambda@Edgeの構成だと前述したように「Lambda@Edgeからデータを読むのにわざわざAPIを通す必要がある」というデメリットがあります.
私は小規模なアプリケーションであれば,Next.js から Prisma ORM を利用する で説明されているパターンで実装することが多いです.
そのため,インターネットからのアクセスを許可するために技術選定を縛ったり,データの取得にわざわざAPIを通さなければならないのは面倒に感じています.
そういった事情を加味して,ISRを諦めてSSRに寄せる方針に落ち着きました.
SSRに寄せる構成の利点
ISRは,Serverless NextjsやAmplify Consoleのおかげでawsとvercelではかなり簡単に動作させることができます.
しかし,他の環境でISRを動作させることは難しいのが現状です.
それに,DBからデータを読みたい,という目的のためだけにわざわざAPIを用意するのはいささか面倒ですし,とはいえパブリックアクセスを許可する方針にして技術選定を縛るのもあまりやりたくありません.
そういった事情で,ISRを諦めてSSRに寄せる方針が良いように感じています.
この方針には構成がシンプルになる,という利点もあります.
awsだと,ECSの前にCloudFrontを立てておく,というシンプルな構成で済みます.
GCPだとGAE単体でレスポンスキャッシュが効くのでそれで良さそうですね.
「ISR・SSGをしない」という選択肢について
Next.jsは,できるだけSSGに寄せる方針を推していて,ISRもビルド時にすべてを処理することが難しいケースでSSGに近いことができるので,Next.jsの思想が色濃く現れた機能だと感じています.
しかし,SSGやISRの採用の有無というのは技術の良し悪しではなく,フレームワークの思想の違いだと思っています.
実際,SSGの機能を持たないRemixのようなフレームワークも登場していますし,ZennもISRをしない方針を取っているようです.
Next.jsアプリをVercelからGoogle Cloudに移行した話
こういった現状を見ると,アプリケーションの要件を考えてSSG,ISRをしない,という方針もあり得るのではないかと思っています.
Discussion