ReactJS を使用した CSR VS SSR
おそらく最も重要かつ基本的な決定の 1 つは、新しい Web アプリの設計を開始するときに Web アプリケーションをレンダリングする方法です。そのため、今日はクライアント側レンダリングとサーバー側レンダリングという 2 つのレンダリング方法について説明したいと思います。もちろん、これら 2 つのパターンだけではなく、プログレッシブ レンダリングや他のパターンについても近い将来説明します。
使用する用語
レンダリング
- SSR:サーバーサイド レンダリング — クライアントサイドまたはユニバーサル アプリをサーバー上の HTML にレンダリングします。
- CSR:クライアント側レンダリング — 通常は DOM を使用して、ブラウザーでアプリをレンダリングします。
- リハイドレーション:サーバーでレンダリングされた HTML の DOM ツリーとデータを再利用できるように、クライアント上で JavaScript ビューを「起動」します。
- FP: First Paint — ピクセルが初めてユーザーに表示されるとき。
- FCP: First Contentful Paint — 要求されたコンテンツ (記事本文など) が表示される時間。
- TTI:インタラクティブ化までの時間 — ページがインタラクティブになる時間 (イベントが接続されるなど)。
- TTFB:最初のバイトまでの時間 — リンクを入力してからコンテンツの最初の部分が受信されるまでの時間
CSR — 構造。
サーバー上に空の div タグとバンドルされた js を含む html があると考えてください。CSR レンダリングは次のようになります。
HTML は 1 つの root div タグだけで構成されており、DOM の表示や更新などのその他の処理はすべて JS によって処理されます。
バンドルとパフォーマンス
パフォーマンスについて考えると、ページの複雑さが増すにつれて、JS の複雑さとサイズも増加し、サーバーから JS を取得する時間も増加することがわかります。これにより、ページの FCP と TTI に遅延が発生します。
長所と短所
長所
- CSR は、更新せずにページを移動することをサポートする SPA を使用する方法を提供します。これは長い間大きな問題でしたが、今では Web サイトが動的なアプリケーションのように動作し始めることが可能になりました。
ただし、いくつかの落とし穴があります。
- パフォーマンス。ページの複雑さが増すにつれて、JS がFCP を認識するまでさらに待たなければなりません。
- 瀬尾さん。ユーザーの訪問者と同じように、ボットはページの表示をリクエストします。これはクロールとしてよく知られたプロセスです。最初の段階では、Googlebot がページのソース コードをクロールし、表示されているすべての (JavaScript 以外の) コンテンツのインデックスを作成します。ただし、JS が実行されて dom が構築されるまでは何も表示されません。このレンダリング段階中に、彼は再びやって来て (その時間が数か月かかる場合もあります)、クロール可能なページの実際のコンテンツを取得し、最終的にはインデックスに追加します。
- 遅延読み込み。遅延読み込みを使用すると、重要ではないリソースの読み込みを回避できます。このアプローチにより、最初のページの読み込み時間が短縮されます。
- 積極的なコード分割。これは、実行時に動的にロードできる複数のバンドルを作成するのに役立ちます。また、JS リソースを遅延ロードすることもできます。コード分割は、TurbopackやWebpackなどのバンドラーによってサポートされています。
- Service Worker によるキャッシュ。これを使用すると、アプリケーション シェルをオフラインでキャッシュし、パフォーマンス時間を向上させることができます。
SSRとは何かを見てみましょう。これは、ユーザーがリクエストを行うときに表示されるページ コンテンツの完全な HTML を生成する最も古い方法です。この実装では、ブラウザがFCP を簡単に構築できるように、サーバー側で HTML を構築してブラウザに送信する必要があります。
ブラウザはサーバー上でリクエストを行い、空のルートだけでなく、コンテンツを含む HTML も生成されます。したがって、ブラウザはコンテンツをできるだけ早く表示します。これで、ブラウザがバンドルのダウンロードを開始し、ユーザーには引き続き画面にコンテンツが表示されますが、まだ対話的ではありません。バンドルがダウンロードされた後でのみ、イベント リスナーが HTML にアタッチされ、インタラクティブになります。このプロセスを水和または再水和と呼びます。
SSR — 長所と短所
長所
Javascript を減らすと、ブラウザの FCP と TTI が高速化されます。
クライアント FCP に大量の Javascript を送信することを避けているため、ユーザーは TTI を待つだけです。ページ上に多数の UI 要素がある場合、SSR は CSR よりも JS がはるかに少ないため、たとえFP=FCP=TTI であってもスクリプトを取得する時間が短くなります。
SEO
検索エンジン ボットは最初の段階でコンテンツを簡単に取得できるようになったので、ページのインデックスを作成できるようになりました。これで、このページではかなり優れた SEO が得られるようになりました。
短所
場合によっては、 TTFB が遅くなることがあります。これは、ユーザーのネットワークが遅いか、サーバー コードが最適化されていない場合のシナリオです。
すべてのコードがクライアント側で利用できるわけではないため、サーバーへの頻繁な呼び出しによりページ全体のリロードが発生し、場合によってはインタラクション間の時間が長くなることがあります。したがって、SSRではSPAは不可能です。
Expressを使用して簡単なReact SSRアプリを作成してみましょう。
npx create-react-app ssr-react
増加メソッドと減少メソッドを備えたコンポーネント:カウンターを書いてみましょう。
import React, { useState } from "react";
const App = ({ initialValue }) => {
const [count, setCount] = useState(initialValue);
return (
<>
<div className="App">
<button onClick={() => setCount(count + 1)}>Increase</button>
<div style={{ margin: "20px" }}>{count}</div>
<button onClick={() => setCount(count - 1)}>Decrease</button>
</div>
</>
);
};
export default App;
npm i express --save
import express from "express";
const app = express();
app.listen(3000, function () {
console.log("server running on 3000");
});
import express from "express";
import fs from "fs";
import path from "path";
import App from "../src/App";
import React from "react";
import ReactDOMServer from "react-dom/server";
const app = express();
app.get("/page", async (req, res) => {
fs.readFile(path.resolve("./build/index.html"), "utf-8", (err, data) => {
if (err) {
return res.status(500).send("Error happened");
}
const html = `<div id="root">${ReactDOMServer.renderToString(
<App />
)}</div>`;
return res.send(data.replace('<div id="root"></div>', html));
});
});
app.use(express.static(path.resolve(__dirname, "..", "build")));
app.listen(3000, function () {
console.log("server running on 3000");
});
したがって、サーバー側で JSX を使用しており、それをサポートする必要があるため、それに対応する babel を追加します。
npm i @babel/preset-env @babel/preset-react @babel/register ignore-styles --save-dev
require("ignore-styles");
require("@babel/register")({
ignore: [/(node_module)/],
presets: ["@babel/preset-env", "@babel/preset-react"],
});
require("./server");
import React, { StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import App from "./App";
hydrateRoot(document.getElementById("root"), <App initialValue={10} />);
"ssr": "node server/index.js",
それでおしまい。
Github のソースコードはここにあります。

![とにかく、リンクリストとは何ですか?[パート1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































