Dev Study
← 解説「SSRとは — 最初のHTMLをサーバで作る」に戻る

サンプルコードで身につける: SSRとは — 最初のHTMLをサーバで作る

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1CSRとSSRのタイムライン比較

ユーザーがURLを開いてから中身が見えるまでの流れを並べると、SSRの狙いが分かります。CSRは「JSが全部揃ってから表示」、SSRは「まずHTMLで表示、動きは後から」です。

// ── CSR: 中身が見えるのはJS実行後 ──
// 1. HTMLが届く(ほぼ空)      → 白い画面
// 2. JSをダウンロード          → まだ白い画面
// 3. JSを実行、APIから取得     → まだ白い画面
// 4. 画面を描画                → やっと中身が見える
//
// ── SSR: 中身は最初のHTMLに入っている ──
// 1. サーバがアプリを実行してHTMLを作る
// 2. HTMLが届く                → もう中身が見える!
// 3. JSをダウンロード・実行     → (見えたまま)
// 4. ハイドレーション           → 操作もできるようになる

2クローラーから見た2つのHTML

SNSでURLを共有したときのカード表示や検索結果は、多くの場合サーバが返したHTMLだけを見て作られます。CSRでは商品名がHTMLに存在しないため、正しく拾ってもらえないことがあります。

<!-- CSR: クローラーが見るのはこれだけ -->
<head><title>MyShop</title></head>
<body><app-root></app-root></body>
<!-- どの商品ページも同じに見える -->

<!-- SSR: ページごとの中身がHTMLに存在する -->
<head>
  <title>りんご 100円 | MyShop</title>
  <meta property="og:title" content="りんご 100円" />
</head>
<body>
  <app-root><h1>りんご</h1><p>産地直送...</p></app-root>
</body>

3サーバでは動かないコードの例

SSRではコンポーネントのコードがNode.js上でも実行されます。windowやlocalStorageはブラウザにしか無いため、サーバ実行時にエラーで落ちます。これがSSR導入時の典型的なつまずきです。

@Component({ selector: 'app-theme', template: '...' })
export class ThemeComponent {
  constructor() {
    // ブラウザでは動くが、サーバで実行されると
    // ReferenceError: localStorage is not defined で落ちる
    const saved = localStorage.getItem('theme');

    // window も同様にサーバには存在しない
    const width = window.innerWidth;
  }
}
// 対処は次のレッスンで学ぶ afterNextRender() など、
// 「ブラウザでだけ実行する」場所へ移すこと

4CSR・SSR・プリレンダリングの使い分け

描画方式は3択です。判断軸は「中身はユーザーごとに違うか」と「共有・検索されるページか」の2つ。1つのアプリの中でページごとに混ぜられるのがAngularの強みです。

// ── 3つの描画方式の使い分け ──
//
// CSR(ブラウザで描画)
//   向き: ログイン後の管理画面・ダッシュボード
//   理由: 検索されないし、中身がユーザーごとに違う
//
// SSR(リクエストごとにサーバで描画)
//   向き: 商品詳細・記事ページなど動的で共有されるページ
//   理由: 内容が変わるが、クローラーにも見せたい
//
// プリレンダリング/SSG(ビルド時に作り置き)
//   向き: トップページ・会社概要・利用規約
//   理由: 誰が見ても同じなら、毎回描画する必要がない

5SSRの代償も知っておく

SSRは無料ではありません。導入判断の場では利点だけでなくコストも並べて比べます。「全ページSSRにする」ではなく「必要なページだけSSRにする」のが現実的な落とし所です。

// ── SSRで得るもの ──
//   ・初期表示が体感で速い(白い画面の時間が短い)
//   ・クローラー/SNSカードに中身が見える
//
// ── SSRで払うもの ──
//   ・Node.jsサーバの運用が必要(静的配信では済まない)
//   ・リクエストごとにサーバでアプリを実行するCPUコスト
//   ・window等に触れない制約とコードの書き分け
//   ・ビルド/デプロイ構成が少し複雑になる
//
// → 迷ったら: 公開ページだけSSR/Prerender、
//    ログイン後はCSR、が定番の構成