CSR 快取與 Next.js
瀏覽器快取使用 Core 的 createCsrCache,僅在需要 Next.js 伺服器資料快取時才添加 /next 的 callApiSsrCache。
快取包裝器也是 commonService 的一部分
本頁的 callApiClientCache/callApiServerCache 代碼僅解釋專案共用 HTTP adapter 的快取部分。生成的服務可以配置為導入此函數,因此先查看整個 rxjsHttpService.ts/commonService.ts 結構會更清楚每個包裝器的位置和角色。
CSR 快取(客戶端快取)
createCsrCache<CacheName>()提供 callApiCsrCache(callApiFn, serviceArgs, cacheOptions) 和 removeCsrCache(cacheName)。
ts
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。在瀏覽器中,使用 shareReplay 共享相同快取鍵的 Observable 結果。
Next.js adapter:callApiSsrCache
使用 Next.js 的 next/cache(unstable_cache)的 SSR 幫助器。如果是 GET 且 cacheTime > 0,則使用 force-cache + revalidate,其他請求則以 no-store 執行。
- 可以通過 headersProvider 注入請求的 Cookie/Authorization。
- 在 401 時,如果有 onServer401,則執行。
ts
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$);不對用戶數據進行快取
將瀏覽器/伺服器包裝成一個專案的情況
在共用服務中,瀏覽器可以通過 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。