CSRキャッシュ & Next.js
ブラウザキャッシュは Core の createCsrCache を使用し、Next.js サーバーのデータキャッシュが必要なときだけ /next の callApiSsrCache を追加します。
キャッシュラッパーも commonService の一部です。
このページの callApiClientCache/callApiServerCache コードは、プロジェクト共通 HTTP アダプターのキャッシュ部分だけを説明します。生成されたサービスがこの関数をインポートするように構成できるため、全体の rxjsHttpService.ts/commonService.ts 構造を最初に見ると、各ラッパーの位置と役割がより明確になります。
CSR キャッシュ (クライアントキャッシュ)
createCsrCache<CacheName>()は callApiCsrCache(callApiFn, serviceArgs, cacheOptions) と removeCsrCache(cacheName) を提供します。
import {
createCsrCache,
type ServiceArguments,
} from "@byeolnaerim/typed-rx-http";
import type { paths as Paths } from "./@types/ApiTypes";
type CacheNames = "adminList" | "profile";
const csrCache = createCsrCache<CacheNames>();
export const callApiClientCache = <R>(
args: ServiceArguments<Paths, any, any, R>,
cache: {
cacheName: CacheNames;
cacheTime: number;
cacheSize?: number;
},
) => csrCache.callApiCsrCache(
client.callApi,
args as any,
cache as any,
);
csrCache.removeCsrCache("adminList");
csrCache.removeCsrCache("any-prefix");サーバー環境では CSR キャッシュマップを作成せず、元の callApi をそのまま呼び出します。ブラウザでは同じキャッシュキーの Observable 結果を shareReplay で共有します。
Next.js アダプター: callApiSsrCache
Next.js の next/cache(unstable_cache) を使用する SSR ヘルパーです。GET で cacheTime > 0 の場合は force-cache + revalidate を使用し、それ以外のリクエストは no-store で実行します。
- headersProvider でリクエストごとに Cookie/Authorization を注入できます。
- 401 で onServer401 があれば実行します。
import type { paths as Paths } from "./@types/ApiTypes";
import { firstValueFrom } from "rxjs";
import {
callApiSsrCache,
redirectToUnauthorizedOnServer401,
} from "@byeolnaerim/typed-rx-http/next";
const apiUrl = process.env.NEXT_PUBLIC_API_URL!;
const headersProvider = async () => {
const { cookies } = await import("next/headers");
const cookieStore = await cookies();
const cookieHeader = cookieStore
.getAll()
.map((c) => `${c.name}=${c.value}`)
.join("; ");
const accessToken = cookieStore.get("accessToken")?.value;
return {
...(cookieHeader ? { Cookie: cookieHeader } : {}),
...(accessToken
? { Authorization: `Bearer ${accessToken}` }
: {}),
};
};
const obs$ = callApiSsrCache<Paths, { ok: true }, "adminList">({
baseUrl: apiUrl,
serviceArguments: { url: "/api/secure", method: "get" },
cacheForService: { cacheName: "adminList", cacheTime: 10_000 },
headersProvider,
onServer401: redirectToUnauthorizedOnServer401,
});
const res = await firstValueFrom(obs$);ユーザーごとのデータはキャッシュしない
ブラウザ/サーバーを 1 つのプロジェクトラッパーでまとめる場合
共通サービスでブラウザは createCsrCache、サーバーは callApiSsrCache に分岐するようにまとめることもできます。これはプロジェクト構成パターンであり、Core 自体の必須構造ではありません。
commonService.ts
tsconst csrCache = createCsrCache<"memberList" | "profile">();
export const callApiClientCache = (
serviceArguments,
cacheForService,
) => csrCache.callApiCsrCache(
callApi,
serviceArguments,
cacheForService,
);
export const removeCsrCache = csrCache.removeCsrCache;commonService.ts
tsexport const callApiServerCache = (serviceArguments, cacheForService) => {
if (typeof window !== "undefined") {
return callApiClientCache(serviceArguments, cacheForService);
}
return from(
import("@byeolnaerim/typed-rx-http/next"),
).pipe(
mergeMap(({ callApiSsrCache }) =>
callApiSsrCache({
baseUrl: process.env.NEXT_PUBLIC_API_URL || "",
serviceArguments,
cacheForService,
headersProvider,
}),
),
);
};自動生成サービスでキャッシュラッパーを使用する場合も、キャッシュ機能が必要なエンドポイントにのみこのラッパーを接続し、残りは通常の callApi をそのまま使用します。