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)。

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 适配器: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
ts
const csrCache = createCsrCache<"memberList" | "profile">();

export const callApiClientCache = (
  serviceArguments,
  cacheForService,
) => csrCache.callApiCsrCache(
  callApi,
  serviceArguments,
  cacheForService,
);

export const removeCsrCache = csrCache.removeCsrCache;
commonService.ts
ts
export 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。

© 2026 Byeolnaerim. 保留所有权利.介绍隐私政策