← 解説「@angular/ssr — ng add で始めるサーバサイドレンダリング」に戻る
サンプルコードで身につける: @angular/ssr — ng add で始めるサーバサイドレンダリング
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1ng add が変えるもの一覧
ng add @angular/ssrを実行すると、追加・変更されるファイルが一式表示されます。それぞれの役割を知っておくと、後でエラーが出たときにどこを見ればよいか分かります。
ng add @angular/ssr
# CREATE src/main.server.ts … サーバ側アプリの起動口
# CREATE src/server.ts … Node.js(Express)サーバ本体
# CREATE src/app/app.routes.server.ts
# … ルートごとの描画方法の宣言
# UPDATE angular.json … サーバ用ビルドの設定を追加
# UPDATE src/app/app.config.ts
# … provideClientHydration などを追加
# 開発中はこれまで通りでOK(SSRで動く)
ng serve
2RenderMode 3種の宣言
app.routes.server.tsで、ルートのパスごとにServer・Prerender・Clientを割り当てます。ワイルドカード(**)でまとめて既定を決め、例外だけ個別に書くのが読みやすい形です。
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
// ビルド時に作り置き(内容が固定のページ)
{ path: '', renderMode: RenderMode.Prerender },
{ path: 'about', renderMode: RenderMode.Prerender },
// ログイン後の画面はブラウザ描画のまま
{ path: 'mypage/**', renderMode: RenderMode.Client },
// 残り(商品詳細など)はリクエストごとにSSR
{ path: '**', renderMode: RenderMode.Server },
];
3afterNextRender でブラウザ限定の処理を書く
localStorageやwindowに触る処理は、afterNextRender()に移します。このコールバックはブラウザでの描画後にしか呼ばれないので、サーバ実行時に落ちる心配がなくなります。
import { Component, signal, afterNextRender } from '@angular/core';
@Component({
selector: 'app-theme-loader',
template: '<p>テーマ: {{ theme() }}</p>',
})
export class ThemeLoaderComponent {
theme = signal('light'); // サーバでは既定値で描画される
constructor() {
// ブラウザで最初の描画が終わった後にだけ実行される。
// サーバでは呼ばれないので localStorage に触っても安全
afterNextRender(() => {
const saved = localStorage.getItem('theme');
if (saved) this.theme.set(saved);
});
}
}
4prerender するパスをパラメータ付きルートに教える
products/:idのようなパラメータ付きルートをPrerenderにする場合、「どのidのページを作り置きするか」をビルド時に教える必要があります。getPrerenderParamsでidの一覧を返します。
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: 'products/:id',
renderMode: RenderMode.Prerender,
// ビルド時に呼ばれ、作り置きするidの一覧を返す
async getPrerenderParams() {
const res = await fetch('https://api.example.com/products');
const products = await res.json();
return products.map((p: { id: number }) => ({
id: String(p.id),
}));
},
},
];
// → ビルドすると products/1, products/2, ... のHTMLが生成される
5ビルドして本番と同じ形で動かす
SSRアプリのビルドはブラウザ用とサーバ用の2つの成果物を作ります。本番ではdistの中のサーバをNode.jsで起動します。ng serveだけでなく、この形でも一度動作確認しておくと安心です。
# ビルド(ブラウザ用とサーバ用の両方が作られる)
ng build
# dist/my-app/
# browser/ … ブラウザに配るJS・CSS・画像
# server/ … Node.jsで動かすサーバ本体
# 本番と同じ形で起動してみる
node dist/my-app/server/server.mjs
# → http://localhost:4000 で、HTMLに中身が入って
# 返ってくることを「ページのソースを表示」で確認する