AWSのSPAアプリケーションにおけるダイナミックレンダリングの実装(アーキテクチャ編)

SPAでサービスを作ったのですが、SEO関連で課題があり、ダイナミックレンダリングの対応をした話です。

インフラは全てAWSで固めたので、AWSを利用していない場合、参考にならないかも知れません。

また、サンプルのソースコードGitHubにあります。 https://github.com/snicmakino/dynamic-rendering-lambda

※ これは2020/07/16時点では有効な話なので、今後の動向次第では有効な対応ではなくなるかも知れません。

ダイナミックレンダリング実装の効果

良い点

イマイチな点

所感としては、SSRを利用するほどコストかけられないが、SEO対策はある程度やりたいといったケースに適しています。

レスポンスタイムがSEOで滅茶苦茶不利になっているような感覚も無いので、十分SSRに対抗する選択肢になり得るかと思います。

ダイナミックレンダリングについて

ダイナミックレンダリングとは

Googleさんのガイドを参考にするとわかりやすいです。 ダイナミックレンダリング

SPAでは通常、ブラウザに真っ白なHTMLが最初に返却され、JSが動いて描写されるという動きをします。

特にSEOを意識しない場合は問題ないのですが、検索エンジンBotなどは、このJSを動かした後の画面を読み込んでくれないことも多く(Googleは結構頑張ってますけど)、コンテンツページなどもデフォルトで設定してあるタイトルを読んでしまったりします。

これではまずいので、ボットに返却するhtmlは、JSを動かして、ちゃんとコンテンツがある状態にしてしまおう(レンダリングする)というのがダイナミックレンダリングです。

サーバサイドレンダリングSSR)との違い

SSRは、全てのアクセスに対して、レンダリングを行います。 対してダイナミックレンダリングでは、bot等の一部のアクセスに対してのみレンダリングをするという違いがあります。

検索エンジン向けのコンテンツと中身を分けるという事なので、あまりSEOに良く無さそうと心配されるかもしれませんが、Googleさんも推奨している方法なので、安心して使って良いかと思います。

インフラ構成

ダイナミックレンダリングシステム構成図
システム構成図
インフラはAWSで固めており、CloudFront、S3、Lambda@Edgeを利用した構成です。 それぞれのサービスを軽く説明します

S3

みんな大好きS3、SPAのhtmlやjs等のリソースの置き場所です。 静的ウェブサイトのホスティング機能を利用します。

CloudFront

みんな大好きCDNAWSサービスとの親和性は素晴らしいです。
ハンドリングの設定をもうちょっと柔軟にしたいですお願いします

Lambda@Edge

CloudFrontでのアクセス時に、なんとAWS Lambdaを動かすことが出来ます。 動かすタイミングは4種類設定でき、今回は以下の2つを使います。

  • Viewer Request CloudFrontがユーザーからリクエストを受信したときに動きます。
    Botかどうかを判断する処理を行います。
  • Origin Request CloudFrontからS3へのリクエスト時に動きます。
    Botだった場合のレンダリング処理を行います。

設計のポイント

Lambda@Edgeの使い方について疑問に思った方も多いかと思うので解説します。

Viewer RequestとOrigin Requestの2つを利用している理由

Viewer Requestだけで全部処理したほうが良いと感じるかも知れませんが、Lambda@Edgeの制限により、この構成を取っています。

ダイナミックレンダリングでは、Lambda上でブラウザを動作させて、レンダリングされたHTMLを返すのですが、ブラウザを動作させるには大きなメモリサイズと、そこそこの時間がかかります。

これがViewer Requestだとメモリ128MB、タイムアウト5秒と制限されてしまうため、動作させることが出来ませんでした。

そのため、重い処理の部分は屈強なLambdaを用意できるOrigin Requestにまかせています。

Lambda@Edgeの実装

次回、Lambda@Edgeの実装周りについて書きます。とりあえずソースさえあれば十分という方はGitHubを参考にしてみてください。
https://github.com/snicmakino/dynamic-rendering-lambda
(未検証だけど多分動作するはず)