一.SSR 概要

SSR(Server-Side Rendering)は新しい概念ではなく、フロントエンドとバックエンドの分離之前の長い期間ではサーバーサイドレンダリングが主流でした(JSP、PHP)。サーバーサイドで完全な HTML ページを生成します
前端渲染模式的探索 より抜粋
サーバーサイドでコンポーネントレンダリング作業を完了する理由は、パフォーマンスとアクセシビリティという 2 つの大きな利点があるからです
二.2 つの大きな利点
パフォーマンス
CSR(Client-side rendering)モードと比較して、SSR のパフォーマンス上の利点は 2 つの側面に現れます:
-
ネットワークリンク
-
クライアントの二次リクエストデータのネットワーク伝送オーバーヘッドを省略
-
サーバーサイドのネットワーク環境はクライアントよりも優れており、内部サーバー間の通信経路もより短い
-
-
コンテンツプレゼンテーション
-
初画面読み込み時間(FCP)がより速い
-
ブラウザのコンテンツ解析最適化メカニズムが機能を発揮できる
-
ネットワークリンクでは、サーバーサイドから API リクエストを発行し、返されたデータを HTML レスポンスコンテンツと一緒に一度にクライアントに伝送するため、CSR の二次リクエストよりも速いです。さらにサーバーサイドのネットワーク伝送速度はより速く(より大きな帯域幅を持てる)、通信経路もより短く(同じデータセンターにデプロイ可能)、通信効率もより高い(RPC を使用可能)です
コンテンツプレゼンテーションの側面では、CSR の HTML はほとんど空殻です:
<!DOCTYPE html>
<html>
<head>
<title>My Awesome Web App</title>
<meta charset="utf-8">
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
クライアントはこのような HTML を受け取るとすぐに空白のページをレンダリングするしかなく、二次リクエストのデータが戻ってきた後に初めて意味のあるコンテンツを呈现できます。一方、SSR が返す HTML にはコンテンツ(データ)があり、クライアントはすぐに意味のある初画面コンテンツ(First Contentful Paint)をレンダリングできます。同時に、静的な HTML 文書により、ストリーミング文書解析(streaming document parsing)などのブラウザ最適化メカニズムもその機能を発揮できます
重要な違いは SSR がクライアント環境に依存しないことです。ネットワーク環境とデバイスパフォーマンスを含みます。つまり、ユーザーのネットワーク状況が非常に悪い場合(弱ネットワーク)、デバイスパフォーマンスが非常に悪い場合(安価、旧式デバイス)でも、サーバーサイドレンダリングは最適なユーザー環境(Wi-Fi ネットワーク、ハイエンドデバイス)とほぼ同等のコンテンツ読み込み体験を保障できます
アクセシビリティ
アクセシビリティ(accessibility)は 2 つの側面から理解できます:
-
人に対して:古く特殊なユーザーデバイス。例えば JavaScript を無効化したデバイス
-
ロボットに対して:クローラープログラムなど。典型的には、検索エンジンクローラー
前者は通常あまり気にする必要はありませんが、後者は 2 つの大きな「顧客」に注目する必要があります:
-
検索エンジン:SEO
-
ソーシャルメディア:ページコンテンツを抓取してサムネイル情報を表示(Twitter カードなど)
PC サイトにとって、検索エンジンが正しくインデックスし、ページ内容を正確に理解できることを保証することは、重要な商業価値があります(検索結果が上位になり、露出量が大きくなる)。モバイルエンドでは検索エンジンのクロールを考慮する必要はありませんが、同様のソーシャルシェアリングの需要もあり、ソーシャルメディアはターゲットページ内の画像などをサムネイル情報として抓取します
P.S.確かに、一部の検索エンジンは重 CSR の SPA を正しくクロールできますが、すべてではなく、さらに一大批のソーシャルメディアはほとんどレスポンス HTML から一部の内容のみをサムネイル情報として抽出します。動的レンダリング HTML(一部)コンテンツの需要は真切に存在します
これらの利点を持っていますが、SSR は CSR ほど広く応用されていません。SSR が 6 つの難題に直面しているからです
三.6 つの難題
難題 1:既存の CSR コードをどのように活用してアイソモーフィックを実現するか
ダウングレード、复用、移行コストの低減などの目的のために、通常は 1 セットの JavaScript コードでクライアント、サーバーサイドを跨いで実行するアイソモーフィック方式を採用して SSR を実現します。しかし、既存の CSR コードをサーバーサイドで実行できるようにするには、まず多くの問題を解決する必要があります。例えば:
-
クライアント依存:API 依存とデータ依存の 2 種類に分かれます。例えば
window/documentなどの JS API、デバイス関連データ情報(画面の幅と高さ、フォントサイズなど) -
ライフサイクルの差異:例えば React では、
componentDidMountはサーバーサイドで実行されません -
非同期操作が実行されない:サーバーサイドのコンポーネントレンダリングプロセスは同期的で、
setTimeout、Promiseなどは待てません -
依存ライブラリの適応:React、Redux、Dva など。さらにサードパーティライブラリなどが universal 環境で実行できるかどうかも不確かで、環境を跨いで状態を共有する必要があるかどうかも問題です。状態管理層を例にすると、SSR はその store がシリアライズ可能であることを要求します
-
両側で状態を共有:共有が必要なすべての状態について、(サーバーサイドで)どのように伝送し、(クライアントで)どのように受信するかを考慮する必要があります
難題 2:サービスの安定性とパフォーマンス要求
クライアントプログラムと比較して、サーバーサイドプログラムは安定性とパフォーマンスに対する要求がはるかに厳格です。例えば:
-
安定性:異常クラッシュ、無限ループ
-
パフォーマンス:メモリ/CPU リソース占有、レスポンス速度(ネットワーク伝送距離なども考慮する必要があります)
したがって、バックエンドの専門的な問題に直面します。デモレベルの SSR はそれほど難しくないかもしれませんが、高可用性の SSR サービスは決して容易ではありません。大トラフィック/高並発にどのように対処するか、どのように障害を識別するか、どのようにダウングレード/快速回復するか、どのリンクにキャッシュを追加する必要があるか、キャッシュをどのように更新するか……
難題 3:付帯施設の建設
SSR の最も核心的な部分はレンダリングサービスですが、それ以外にも考慮する必要があります:
-
ローカル開発キット(検証 + 構築 + プレビュー/HMR+ デバッグ)
-
リリースフロー(バージョン管理)
一整套の工程施設は、SSR モードではすべて再考慮する必要があります
難題 4:お金に関する問題
SSR レンダリングサービスを導入することは、実際にはネットワーク構造に 1 つのノードを追加することで、大トラフィックが通る場所では、すべてのレイヤーがお金です:
Most importantly, SSR React apps cost a lot more in terms of resources since you need to keep a Node server up and running.
コンポーネントレンダリングロジックをクライアントからサーバーに変更して実行するため、計算リソースのコストを考慮する必要があります
難題 5:hydration のパフォーマンス損失
クライアントは SSR レスポンスを受け取った後、(JavaScript ベースの)インタラクション機能をサポートするために、依然としてコンポーネントツリーを作成し、SSR がレンダリングした HTML と関連付け、関連する DOM イベントをバインドして、ページをインタラクティブにする必要があります。このプロセスを hydration と呼びます
hydration に必要な JavaScript コードの読み込みと実行は、CSR モードよりもそれほど少なくないかもしれません。この部分の作業はクライアントで実行され、ユーザーデバイスのパフォーマンスに制限され、较差のデバイスでは知覚可能な非インタラクティブ時間を引き起こす可能性があります:
-
CSR:インタラクティブだがデータがない(非同期でデータをリクエスト中で、非常に長くなる可能性がある)
-
SSR:データがあるがインタラクティブでない(JS を取得した後 hydrate プロセスを開始し、コンテンツは見えるがインタラクティブでない。通常はそれほど長くは続かない)
リッチインタラクションのシナリオでは、後者は必ずしも前者よりもユーザー体験が良いとは限りません
難題 6:データリクエスト
サーバーサイドの同期レンダリングは、まずリクエストを送信し、データを取得してからコンポーネントのレンダリングを開始する必要があるため、3 つの問題に直面します:
-
データ依存をビジネスコンポーネントから分離する必要がある
-
クライアント公参が欠落(cookie などクライアントがデフォルトで付与する header 情報を含む)
-
両側のデータプロトコルが異なる:サーバーサイドにはより効率的な通信方式がある可能性がある。例えば RPC
現在主流の CSR モードでは、データ依存とビジネスコンポーネントは密結合しており、サーバーサイドから発行する必要があるデータリクエストはすべてコンポーネントライフサイクル関数に混在しています。データ依存を分離することは、CSR コード���同時に改造する必要があることを意味します。公参、データプロトコルなどの差異もコード复用、保守性に対していくつかの新しい挑戦を提起します
四。アプリケーションシナリオ
初画面読み込みパフォーマンスもアクセシビリティも、コンテンツ密集型ページに対してのみ意味があり、インタラクション密集型のページでは、SSR が事前にレンダリングできるコンテンツは少なく、ユーザーにとって意味が大きくなく、SEO の必要性も検討の余地があります。したがって、SSR は静的なコンテンツ表示シナリオに適しています。典型的には、商品詳細、ガイド、記事などの図文混排のシナリオです
別の側面では、必ずしも 100% SSR である必要はなく、特定のページをレンダリングするだけでなく、ページフレームのみをレンダリングするのも良いアプリケーションです:
"Application Shell" is an excellent concept. But sometimes, we might need to render a part of the page in the server. It could be the header with user info. In such cases, you need server-side rendering.
コメントはまだありません