ReactSEO戦略とベストプラクティス
公開: 2022-03-11Reactは、宣言型、モジュラー型、クロスプラットフォーム型のインタラクティブなUIを作成するために開発されました。 今日、これは、パフォーマンスの高いフロントエンドアプリケーションを作成するための最も人気のある(最も人気がないにしても)JavaScriptフレームワークの1つです。 シングルページアプリケーション(SPA)を作成するために最初に開発された、Reactは現在、本格的なWebサイトやモバイルアプリケーションを作成するために使用されています。
従来のWeb開発の豊富な経験があり、Reactに移行した場合、JavaScriptに移行するHTMLおよびCSSコードの量が増えていることに気付くでしょう。 これは、ReactがUI要素を直接作成または更新することを推奨せず、代わりにUIの「状態」を記述するためです。 次に、Reactは最も効率的な方法で状態に一致するようにDOMを更新します。
その結果、UIまたはDOMへのすべての変更は、Reactのエンジンを介して行う必要があります。 開発者にとっては便利ですが、これはユーザーの読み込み時間が長くなり、検索エンジンがコンテンツを見つけてインデックスを作成するための作業が増えることを意味します。
この記事では、SEOパフォーマンスの高いReactアプリとWebサイトを構築する際に直面する課題に取り組み、それらを克服するために使用されるいくつかの戦略の概要を説明します。
Googleがウェブページをクロールしてインデックスを作成する方法
Googleはすべてのオンライン検索の90%以上を受け取ります。 クロールとインデックス作成のプロセスを詳しく見てみましょう。
Googleのドキュメントから取得したこのスナップショットは、私たちを助けることができます。 これは簡略化されたブロック図であることに注意してください。 実際のGooglebotははるかに洗練されています。
注意点:
- Googlebotは、将来クロールしてインデックスを作成するために必要なすべてのURLを含むクロールキューを維持します。
- クローラーがアイドル状態のとき、クローラーはキュー内の次のURLを取得し、要求を行い、HTMLをフェッチします。
- HTMLを解析した後、Googlebotは、コンテンツをレンダリングするためにJavaScriptをフェッチして実行する必要があるかどうかを判断します。 はいの場合、URLはレンダリングキューに追加されます。
- 後の時点で、レンダラーはJavaScriptをフェッチして実行し、ページをレンダリングします。 レンダリングされたHTMLを処理ユニットに送り返します。
- 処理装置は、Webページに記載されているすべてのURL
<a> tagsを抽出し、それらをクロールキューに追加し直します。 - コンテンツはGoogleのインデックスに追加されます。
HTMLを解析するProcessingステージとJavaScriptを実行するRendererステージには明確な違いがあることに注意してください。
この違いは、Googlebotが130兆を超えるウェブページを閲覧する必要があることを考えると、JavaScriptの実行にはコストがかかるために存在します。 そのため、Googlebotがウェブページをクロールすると、すぐにHTMLが解析され、後で実行するためにJavaScriptがキューに入れられます。 Googleのドキュメントには、ページが数秒間レンダリングキューにとどまると記載されていますが、それより長くなる場合があります。
クロールバジェットの概念についても言及する価値があります。 Googleのクロールは、Googlebotインスタンスの帯域幅、時間、可用性によって制限されます。 特定の予算またはリソースを割り当てて、各Webサイトのインデックスを作成します。 数千ページの大規模なコンテンツの多いウェブサイト(eコマースウェブサイトなど)を構築していて、これらのページがコンテンツのレンダリングに多くのJavaScriptを使用している場合、Googleはウェブサイトから読み取るコンテンツが少なくなる可能性があります。
注:クロール予算を管理するためのGoogleのガイドラインはこちらでご覧いただけます。
SEOのためにReactを最適化することが難しい理由
Googlebot、クロール、インデックス作成の概要は、表面的なものにすぎません。 それでも、ソフトウェアエンジニアは、Reactページをクロールしてインデックスを作成しようとする検索エンジンが直面する潜在的な問題を特定する必要があります。 これで、React SEOを困難にするものと、これらの課題のいくつかに対処して克服するために開発者ができることを詳しく見ることができます。
空の初回通過コンテンツ
ReactアプリケーションはJavaScriptに大きく依存しており、検索エンジンで問題が発生することがよくあります。 これは、Reactがデフォルトでアプリシェルモデルを採用しているためです。 最初のHTMLには意味のあるコンテンツが含まれておらず、ユーザーまたはボットはページの実際のコンテンツを表示するためにJavaScriptを実行する必要があります。
このアプローチは、Googlebotが最初のパスで空のページを検出することを意味します。 コンテンツは、ページがレンダリングされたときにのみGoogleに表示されます。 これにより、数千ページを処理するときにコンテンツのインデックス作成が遅れます。
読み込み時間とユーザーエクスペリエンス
JavaScriptの取得、解析、実行には時間がかかります。 さらに、JavaScriptはコンテンツをフェッチするためにネットワーク呼び出しを行う必要がある場合があり、ユーザーは要求された情報を表示できるようになるまでしばらく待つ必要がある場合があります。
Googleは、ランキング基準で使用される、ユーザーエクスペリエンスに関連する一連のWebバイタルをレイアウトしました。 読み込み時間が長くなると、ユーザーエクスペリエンスのスコアに影響し、Googleがサイトのランクを下げるように促される可能性があります。
次のセクションで、Webサイトのパフォーマンスを詳しく確認します。
ページメタデータ
メタ<meta>タグは、Googleやその他のソーシャルメディアWebサイトで、ページの適切なタイトル、サムネイル、説明を表示できるため便利です。 ただし、これらのWebサイトは、フェッチされたWebページの<head>タグに依存してこの情報を取得します。 これらのWebサイトは、ターゲットページに対してJavaScriptを実行しません。
Reactは、メタタグを含むすべてのコンテンツをクライアントにレンダリングします。 アプリシェルはウェブサイト/アプリケーション全体で同じであるため、個々のページにメタデータを適合させるのは難しい場合があります。
サイトマップ
サイトマップは、サイト上のページ、ビデオ、およびその他のファイルとそれらの間の関係に関する情報を提供するファイルです。 Googleのような検索エンジンはこのファイルを読み取って、サイトをよりインテリジェントにクロールします。
Reactには、サイトマップを生成するための組み込みの方法がありません。 React Routerのようなものを使用してルーティングを処理している場合は、多少の労力が必要になる場合がありますが、サイトマップを生成できるツールを見つけることができます。
その他のSEOに関する考慮事項
これらの考慮事項は、一般的に優れたSEOプラクティスの設定に関連しています。
- 人間と検索エンジンにページで何を期待するかについての良いアイデアを与えるために最適なURL構造を持ってください。
- robots.txtファイルを最適化すると、検索ボットがWebサイトのページをクロールする方法を理解するのに役立ちます。
- CDNを使用して、CSS、JS、フォントなどのすべての静的アセットを提供し、レスポンシブ画像を使用して読み込み時間を短縮します。
サーバーサイドレンダリング(SSR)または事前レンダリングを使用することで、上記で概説した問題の多くに対処できます。 これらのアプローチを以下で確認します。
同形反応を入力してください
同型の辞書の定義は、「対応する形式または類似した形式」です。
Reactの用語では、これはサーバーがクライアントと同様の形式を持っていることを意味します。 つまり、サーバーとクライアントで同じReactコンポーネントを再利用できます。
この同形アプローチにより、サーバーはReactアプリをレンダリングし、レンダリングされたバージョンをユーザーと検索エンジンに送信できるため、JavaScriptがバックグラウンドで読み込まれて実行されている間、ユーザーはコンテンツを即座に表示できます。
Next.jsやGatsbyのようなフレームワークは、このアプローチを普及させてきました。 同形コンポーネントは、従来のReactコンポーネントとは大幅に異なって見える可能性があることに注意してください。 たとえば、クライアントではなくサーバーで実行されるコードを含めることができます。 APIシークレットを含めることもできます(ただし、サーバーコードはクライアントに送信される前に削除されます)。
注意すべき点の1つは、これらのフレームワークは多くの複雑さを抽象化するだけでなく、コードを書くための独創的な方法を導入することです。 この記事では、パフォーマンスのトレードオフについてさらに詳しく説明します。
また、レンダリングパスとWebサイトのパフォーマンスの関係を理解するために、マトリックス分析を行います。 ただし、その前に、Webサイトのパフォーマンスを測定するための基本事項について説明します。
ウェブサイトのパフォーマンスの指標
検索エンジンがウェブサイトをランク付けするために使用するいくつかの要因を調べてみましょう。
ユーザーの質問にすばやく正確に答える以外に、Googleは優れたウェブサイトには次の属性が必要であると考えています。
- すぐに読み込まれるはずです。
- ユーザーは、待ち時間をあまりかけずにコンテンツにアクセスできる必要があります。
- 早い段階でユーザーのアクションに対してインタラクティブになる必要があります。
- ユーザーのデータやバッテリーの消耗を防ぐために、不要なデータをフェッチしたり、高価なコードを実行したりしないでください。
これらの機能は、おおまかに次のメトリックにマップされます。
- TTFB :最初のバイトまでの時間–リンクをクリックしてからコンテンツの最初のビットが入ってくるまでの時間。
- LCP :最大のコンテンツフルペイント–要求された記事が表示されるようになる時間。 この値を2.5秒未満に保つことをお勧めします。
- TTI :インタラクティブになるまでの時間–ページがインタラクティブになる時間(ユーザーはスクロール、クリックなどができます)。
- バンドルサイズ–ページが完全に表示されインタラクティブになる前にダウンロードされたコードと実行されたコードの合計数。
さまざまなレンダリングパスがそれぞれにどのように影響するかをよりよく理解するために、これらのメトリックを再検討します。
次に、React開発者が利用できるさまざまなレンダリングパスを理解しましょう。
レンダリングパス
ブラウザまたはサーバーでReactアプリケーションをレンダリングし、さまざまな出力を生成できます。
クライアント側とサーバー側のレンダリングされたアプリ間で、ルーティングとコード分割という2つの機能が大幅に異なります。 これらを以下で詳しく見ていきます。

クライアント側レンダリング(CSR)
クライアント側のレンダリングは、ReactSPAのデフォルトのレンダリングパスです。 サーバーは、コンテンツを含まないシェルアプリを提供します。 ブラウザが含まれているJavaScriptソースをダウンロード、解析、および実行すると、HTMLコンテンツが入力またはレンダリングされます。
ルーティング機能は、ブラウザの履歴を管理することにより、クライアントアプリによって処理されます。 これは、要求されたルートに関係なく同じHTMLファイルが提供され、クライアントはレンダリング後にビューステートを更新することを意味します。
コード分割は比較的簡単です。 動的インポートまたはReact.lazyを使用してコードを分割し、ルートまたはユーザーアクションに基づいて必要な依存関係のみが読み込まれるようにすることができます。
ページがコンテンツ(ブログのタイトルや製品の説明など)をレンダリングするためにサーバーからデータをフェッチする必要がある場合は、関連するコンポーネントがマウントおよびレンダリングされている場合にのみ取得できます。
ウェブサイトが追加のデータを取得している間、ユーザーには「データの読み込み中」のサインまたはインジケーターが表示される可能性があります。
ブートストラップデータを使用したクライアント側のレンダリング(CSRB)
CSRと同じシナリオを考えますが、DOMがレンダリングされた後にデータをフェッチする代わりに、サーバーが提供されたHTML内にブートストラップされた関連データを送信したとします。
次のようなノードを含めることができます。
<script type="application/json"> {"title": "My blog title", "comments":["comment 1","comment 2"]} </script>そして、コンポーネントがマウントされたときにそれを解析します。
var data = JSON.parse(document.getElementById('data').innerHTML);サーバーへの往復を節約しました。 トレードオフについては後ほど説明します。
静的コンテンツへのサーバー側レンダリング(SSRS)
その場でHTMLを生成する必要があるシナリオを想像してみてください。
たとえば、オンライン計算機を構築していて、ユーザーが/calculate/34+15のようなクエリを発行した場合(URLエスケープは省略)。 クエリを処理し、結果を評価し、生成されたHTMLで応答する必要があります。
生成されたHTMLは構造が非常に単純であり、生成されたHTMLが提供された後、DOMを管理および操作するためにReactは必要ありません。
つまり、HTMLとCSSのコンテンツを提供しているだけです。 これを実現するには、 renderToStaticMarkupメソッドを使用できます。
CDNキャッシングを使用すると応答をより高速に処理できますが、結果ごとにHTMLを再計算する必要があるため、ルーティングはサーバーによって完全に処理されます。 CSSファイルをブラウザでキャッシュして、後続のページの読み込みを高速化することもできます。
再水和を伴うサーバー側レンダリング(SSRH)
上記と同じシナリオを想像してみてください。ただし、今回はクライアント上に完全に機能するReactアプリケーションが必要です。
サーバーで最初のレンダリングを実行し、JavaScriptファイルと一緒にHTMLコンテンツを送り返します。 Reactはサーバーでレンダリングされたマークアップを再水和し、アプリケーションはこの時点からCSRアプリケーションのように動作します。
Reactは、これらのアクションを実行するための組み込みメソッドを提供します。
最初のリクエストはサーバーによって処理され、後続のレンダリングはクライアントによって処理されます。 したがって、このようなアプリはユニバーサルReactアプリと呼ばれます(サーバーとクライアントの両方でレンダリングされます)。 ルーティングを処理するコードは、クライアントとサーバーで分割(または複製)される場合があります。
ReactDOMServerはReactをサポートしていないため、コードの分割も少し注意が必要です。 怠惰なので、ロード可能なコンポーネントのようなものを使用する必要があるかもしれません。
ReactDOMServerは浅いレンダリングのみを実行することにも注意してください。 つまり、コンポーネントのrenderメソッドは呼び出されますが、 componentDidMountなどのライフサイクルメソッドは呼び出されません。 したがって、別の方法を使用してコンポーネントにデータを提供するには、コードをリファクタリングする必要があります。
これは、NextJSのようなフレームワークが登場する場所です。 これらは、SSRHでのルーティングとコード分割に関連する複雑さを隠し、よりスムーズな開発者エクスペリエンスを提供します。
このアプローチでは、後で気付くように、ページのパフォーマンスに関してはさまざまな結果が得られます。
静的コンテンツ(PRS)への事前レンダリング
ユーザーが要求する前にWebページをレンダリングできるとしたらどうでしょうか。 これは、ビルド時に実行することも、データが変更されたときに動的に実行することもできます。
次に、結果のHTMLコンテンツをCDNにキャッシュし、ユーザーが要求したときにはるかに高速に提供できます。
これは、コンテンツをレンダリングする前の事前レンダリング、ユーザー前のリクエストと呼ばれます。 このアプローチは、ブログやeコマースアプリケーションに使用できます。これらのコンテンツは通常、ユーザーから提供されたデータに依存しないためです。
再水和(PRH)による事前レンダリング
クライアントがレンダリングするときに、事前にレンダリングされたHTMLを完全に機能するReactアプリにしたい場合があります。
最初のリクエストが処理された後、アプリケーションは標準のReactアプリのように動作します。 このモードは、ルーティングおよびコード分割機能の点で、上記のSSRHに似ています。
パフォーマンスマトリックス
待ちに待った瞬間がやっと到着しました。 対決の時間です。 これらのレンダリングパスのそれぞれがWebパフォーマンスメトリックにどのように影響するかを見て、勝者を決定しましょう。
このマトリックスでは、パフォーマンスメトリックでのパフォーマンスに基づいて、各レンダリングパスにスコアを割り当てます。
スコアの範囲は1〜5です。
- 1=不十分
- 2=悪い
- 3=中程度
- 4=良い
- 5=すばらしい
| TTFB 最初のバイトまでの時間 | LCP 最大の満足のいくペイント | TTI インタラクティブな時間 | バンドルサイズ | 合計 | |
|---|---|---|---|---|---|
| CSR | 5 HTMLはCDNにキャッシュできます | 1 HTMLとデータをフェッチするためのサーバーへの複数回の移動 | 2 データフェッチ+JS実行遅延 | 2 レンダリングする前に、すべてのJS依存関係をロードする必要があります | 10 |
| CSRB | 4 HTMLは、リクエストデータに依存しないため、キャッシュできます | 3 データはアプリケーションでロードされます | 3 JSは、インタラクティブにする前に、フェッチ、解析、および実行する必要があります | 2 レンダリングする前に、すべてのJS依存関係をロードする必要があります | 12 |
| SSRS | 3 HTMLはリクエストごとに生成され、キャッシュされません | 5 JSペイロードまたは非同期操作はありません | 5 ページは最初のペイントの直後にインタラクティブです | 5 重要な静的コンテンツのみが含まれています | 18 |
| SSRH | 3 HTMLはリクエストごとに生成され、キャッシュされません | 4 サーバーが最初のパスをレンダリングしたため、最初のレンダリングが高速になります | 2 最初のHTML解析+ペイント後にJSがDOMをハイドレイトする必要があるため、速度が低下します | 1 レンダリングされたHTML+JSの依存関係をダウンロードする必要があります | 10 |
| PRS | 5 HTMLはCDNにキャッシュされます | 5 JSペイロードまたは非同期操作はありません | 5 ページは最初のペイントの直後にインタラクティブです | 5 重要な静的コンテンツのみが含まれています | 20 |
| PRH | 5 HTMLはCDNにキャッシュされます | 4 サーバーが最初のパスをレンダリングしたため、最初のレンダリングが高速になります | 2 最初のHTML解析+ペイント後にJSがDOMをハイドレイトする必要があるため、速度が低下します | 1 レンダリングされたHTML+JSの依存関係をダウンロードする必要があります | 12 |
重要なポイント
静的コンテンツ(PRS)への事前レンダリングは、最高のパフォーマンスのWebサイトにつながりますが、ハイドレーションを使用したサーバー側レンダリング(SSRH)またはクライアント側レンダリング(CSR)は、圧倒的な結果につながる可能性があります。
ウェブサイトのさまざまな部分に複数のアプローチを採用することも可能です。 たとえば、これらのパフォーマンスメトリックは、公開されているWebページにとって重要であるため、より効率的にインデックスを作成できますが、ユーザーがログインしてプライベートアカウントデータを表示すると、重要性は低くなります。
各レンダリングパスは、データを処理する場所と方法のトレードオフを表します。 重要なことは、エンジニアリングチームがこれらのトレードオフを明確に確認して議論し、ユーザーの幸せを最大化するアーキテクチャを選択できることです。
さらに読むことと考慮事項
私は現在人気のあるテクニックをカバーしようとしましたが、これは網羅的な分析ではありません。 Googleの開発者が、ストリーミングサーバーレンダリング、トリソモーフィックレンダリング、動的レンダリング(クローラーとユーザーに異なる応答を提供する)などの他の高度な手法について説明しているこの記事を読むことを強くお勧めします。
コンテンツを多用するWebサイトを構築する際に考慮する必要のあるその他の要素には、作成者向けの優れたコンテンツ管理システム(CMS)の必要性、ソーシャルメディアプレビューを簡単に生成/変更し、さまざまな画面サイズに合わせて画像を最適化する機能などがあります。
