# @fortedigital/nextjs-cache-handler 中文文档

规范地址：https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/

版本：3\.4\.0
npm 元数据更新时间：2026-10-16T13:05:45.127Z
中文译文更新时间：2026-11-15T09:34:49.856Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40fortedigital/nextjs-cache-handler
原文对照：https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/?lang=original
项目主页：https://github.com/fortedigital/nextjs-cache-handler
源码仓库：https://github.com/fortedigital/nextjs-cache-handler

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：331 kB，70 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：未声明
- Node.js 要求：\>=22\.0\.0
- 运行依赖：3 个
- peer 依赖：next \>=16\.1\.5，ioredis \>= 5\.0\.0，@redis/client \>= 5\.8\.3
- 首次发布：2024-10-02T10:06:30.584Z
- 最新版本发布：2026-10-16T13:05:44.694Z
- 近 30 天下载量：645539（2026-10-16 至 2026-11-14，npm 官方下载统计）
- 已发布版本数：81（近 12 个月 23 个）

## 中文简介

Next.js 缓存处理器

## 安装

```sh
npm install @fortedigital/nextjs-cache-handler
```

也可以使用：`pnpm add @fortedigital/nextjs-cache-handler`、`yarn add @fortedigital/nextjs-cache-handler`、`bun add @fortedigital/nextjs-cache-handler`

## README

![NPM Version](https://img.shields.io/npm/v/%40fortedigital%2Fnextjs-cache-handler)

# @ fortedigital/ nextjs-cache- handler (中文(简体) )

最初建在顶部的缓存工具 [`@neshca/cache-handler`](https://www.npmjs.com/package/@neshca/cache-handler),为专门使用的案件提供额外的缓存处理器,重点是基于Redis的缓存.

从版本开始 `2.0.0`此软件包不再依赖于 `@neshca/cache-handler` 并与Next.js 15和部分16保持并兼容。 见 [兼容矩阵](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-feature-compatibility-matrix) 详细特性支持.

**版本要求 :**

-   **下一个.js 15**: 2.0.0+版本(3.0.0+版本建议最新改进和维护开发)
-   **下一个.js 16**: 3.0.0+ 需要的版本

## 目录

-   [文档](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-documentation)
-   [移徙](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-migration)
-   [先决条件](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-prerequisites)
-   [安装](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-installation)
-   [快速启动](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-quick-start)
-   [下一个.js 兼容性](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-nextjs-compatibility)
    -   [特性相容性矩阵](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-feature-compatibility-matrix)
-   [移徙](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-migration)
    -   [从@neshca/ cache- handler 拆卸](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-swapping-from-neshcacache-handler)
-   [处理器](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-handlers)
    -   [复刻字符串](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-redis-strings)
    -   [本地语言](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-local-lru)
    -   [复合](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-composite)
-   [实例](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-examples)
-   [参考原始软件包](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-reference-to-original-package)
-   [API 参考链接](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-api-reference-links)
-   [解决问题](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-troubleshooting)
-   [遗产/贬值](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-legacy--deprecated)
-   [捐款](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-contributing)
-   [许可证](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-license)

## 文档

文件编号: [@neshca/cache-handler - caching-tools.github.io/next-shared-cache 页面存档备份,存于互联网档案馆 (简体中文)](https://caching-tools.github.io/next-shared-cache) 虽然一些细节可能已经过时,但大部分内容仍然相关。 下文介绍新的特征或相关变化.

## 移徙

-   [1.x.x → ^ 2.x.x](https://github.com/fortedigital/nextjs-cache-handler/blob/master/docs/migration/1_x_x__2_x_x.md)
-   [1.2.x - > ^1.3.x](https://github.com/fortedigital/nextjs-cache-handler/blob/master/docs/migration/1_2_x__1_3_x.md)

### 从 `@neshca/cache-handler`

如果您已经使用 `@neshca/cache-handler` 设置非常精简,你只需要替换软件包的引用。 如果你开始新鲜,请检查 [实例项目](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/examples/redis-minimal)。 。 。 .

#### 缓存处理器

**在此之前:**

```js
// cache-handler.mjs

import { CacheHandler } from "@neshca/cache-handler";

CacheHandler.onCreation(() => {
  // setup
});

export default CacheHandler;
```

**之后:**

```js
// cache-handler.mjs

import { CacheHandler } from "@fortedigital/nextjs-cache-handler";

CacheHandler.onCreation(() => {
  // setup
});

export default CacheHandler;
```

* * *

#### 仪器

**在此之前:**

```js
// instrumentation.ts

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { registerInitialCache } =
      await import("@neshca/cache-handler/instrumentation");
    const CacheHandler = (await import("../cache-handler.mjs")).default;
    await registerInitialCache(CacheHandler);
  }
}
```

**之后:**

```js
// instrumentation.ts

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { registerInitialCache } =
      await import("@fortedigital/nextjs-cache-handler/instrumentation");
    const CacheHandler = (await import("../cache-handler.mjs")).default;
    await registerInitialCache(CacheHandler);
  }
}
```

## 先决条件

在安装前,请确保您有:

-   **节点.js** >= 22.0.0
-   **下一个.js** qq 15.2.4 (为 2.0.0+版)或 qq 16.0.0 (为 3.0.0+版)
-   **重写** >= 5.5.6 (或相容再相容服务)
-   **小时** 9.0.0(促进发展)

见 [版本要求](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-version-requirements) 用于软件包版本相容性.

## 安装

`npm i @fortedigital/nextjs-cache-handler`

如果升级 从下14或更早, **冲出您的 Redis 缓存** 在本地运行新版本应用程序之前,并在您主机环境中运行. **下 14 和 15 之间的缓存格式不兼容**。 。 。 .

## 快速启动

这里有一个最小的设置开始:

```js
// cache-handler.mjs
import { CacheHandler } from "@fortedigital/nextjs-cache-handler";
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import { createClient } from "redis";

const client = createClient({ url: process.env.REDIS_URL });
await client.connect();

CacheHandler.onCreation(() => ({
  handlers: [createRedisHandler({ client })],
}));

export default CacheHandler;
```

然后在您体内配置 `next.config.js`数字 :

```js
// next.config.js
module.exports = {
  cacheHandler: require.resolve("./cache-handler.mjs"),
};
```

关于错误处理、倒置和生产设置的完整实例,见 [实例](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-examples) 下节。 快速启动代码并非用于生产.

## 下一个.js 兼容性

原画 `@neshca/cache-handler` 软件包不支持 Next.js 15.

在 2.0.0 之前,这个包包提供了包装和增强,允许使用 `@neshca/cache-handler` 与下册.js 15.  
从2.0版开始, `@fortedigital/nextjs-cache-handler` 是一个独立的解决办法,不依赖 `@neshca/cache-handler` 并完全兼容 Next.js 15和 [复数 5](https://www.npmjs.com/package/redis)。 。 。 .

**版本要求 :**

-   **下一个.js 15**: 2.0.0+版本(3.0.0+版本建议最新改进和维护开发)
-   **下一个.js 16**: 3.0.0+ 需要的版本

我们的目标是跟上新的Next.js版本,并将采用带有适当版本起伏的重大改动.

> \[尖叫声\] **下一条,js 16.3.0 断裂变化:** 从Next.js 16.3.0开始,预先请求应用路由器的路由树(`/_tree`需要每个区块的RSC有效载荷(`segmentData`在缓存条目中存在。 此软件包的版本在 **3.3.0 (单位:千美元)** 没有填充 `segmentData` 当从磁盘恢复初始缓存时(通过) `registerInitialCache`)),这导致"Next.js 16.3.0+"客户端收到了无法解析的响应,用于 `/_tree` 预选请求和无限重试.
> 
> **固定于3.3.0.** 如果你在Next.js 16.3.0上或稍后,升级到 `@fortedigital/nextjs-cache-handler` 3.3.0+ (中文(简体) ).

> \[尖叫声\] **Next.js 16.3.8+路由扫描缓存密钥:** 从Next.js 16.3.8(和 16.4.x)开始,响应缓存条目(`APP_PAGE`, (中文(简体) ), `APP_ROUTE`, (中文(简体) ), `PAGES`)储存在路由范围键下(`/route-cache/<kind>/<hash>/$<path>`)而不是赤出道名. 此软件包的版本在 **3.4.0 (中文(简体) )** 种子初始缓存项(通过 `registerInitialCache`)在赤色路径名下,所以Next.js从不读取,并打破了Pages路由器 `revalidatePath` 无效.
> 
> **固定于 3. 4. 0.** 如果你在Next.js 16.3.8或以后,升级到 `@fortedigital/nextjs-cache-handler` 3.4.0+. 旧路径名密钥下存储的条目在升级后不再被读取 Next.js 并自行过期.

### 特性相容性矩阵

| 特性 | 下一个.js 15 | 下一个.js 16 | 页:1 |
| --- | --- | --- | --- |
| **获取 API 缓存** |  |  |  |
| `fetch` 默认缓存( e)`force-cache`(中文(简体) ) | ✅ | ✅ | 默认行为, 无限缓存 |
| `fetch` 与 `no-store` | ✅ | ✅ | 从不缓存, 总是新鲜的 |
| `fetch` 与 `no-cache` | ✅ | ✅ | 在每个请求上验证缓存 |
| `fetch` 与 `next.revalidate` | ✅ | ✅ | 基于时间的重新验证 |
| `fetch` 与 `next.tags` | ✅ | ✅ | 基于标记的缓存无效 |
| **快取无效** |  |  |  |
| `revalidateTag(tag)` | ✅ | 不详 | Next.js 16的突破变化 |
| `revalidateTag(tag, cacheLife)` | 不详 | ✅ | Next.js 中新需要的 API 16 |
| `updateTag(tag)` | 不详 | ✅ | 服务器动作中立即无效的新 API |
| `revalidatePath(path)` | ✅ | ✅ | 基于路径的再验证 |
| `revalidatePath(path, type)` | ✅ | ✅ | 类型特定路径重新验证 |
| **函数缓存** |  |  |  |
| `unstable_cache()` | ✅ | ✅ | 缓存任何带有标签并重新验证的函数 |
| **静态生成** |  |  |  |
| `generateStaticParams()` | ✅ | ✅ | 静态参数生成 |
| ISR(递增静态再生) | ✅ | ✅ | 按需再生 |
| 路由段配置( N)`revalidate`, (中文(简体) ), `dynamic`页:1 | ✅ | ✅ | 所有段配置选项 |
| **Redis 客户端支持** |  |  |  |
| `redis` 软件包(节点- redis) | ✅ | ✅ | 官方 Redis 客户端 - 完全支持 |
| `ioredis` 软件包 | ✅ | ✅ | IORedis 客户端 - 完全支持 |
| **下一个.js 16 新地物** |  |  |  |
| `cacheHandlers` 配置(用于) `'use cache'`(中文(简体) ) | ❌ | ❌ | 尚未支持 - 需要帮助 |
| `'use cache'` 指令 | ❌ | ❌ | 尚未支持 - 需要帮助 |
| `'use cache: remote'` 指令 | ❌ | ❌ | 尚未支持 - 需要帮助 |
| `'use cache: private'` 指令 | ❌ | ❌ | 尚未支持 - 需要帮助 |
| `cacheComponents` | ❌ | ❌ | 尚未支持 - 需要帮助 |

**注释:**

-   `revalidateTag()` 下一个.js 16 需要一个 `cacheLife` 参数(`'max'`, (中文(简体) ), `'hours'`,或 `'days'`) (中文(简体) ). 这是一个突破性的变化 从Next.js 15.
-   `cacheLife` 剖面图主要是为Vercel的基础设施而设计的. 自定义缓存处理器可能无法完全区分不同的 `cacheLife` 简介.
-   `updateTag()` 仅在服务器动作中可用,而不是路由处理器.
-   新的 `cacheHandlers` API 和 `'use cache'` 指令尚未为本套件所支持.

## 处理器

### `redis-strings`

一个基于 Redis 的处理器,用于基于密钥和标记的缓存. 与原始执行相比,它通过执行TTL-捆绑的hashmaps来防止由正在增长的共享标记图所引发的内存泄露.

**特征 :**

-   使用密钥过期 `EXAT` 或者说 `EXPIREAT`
-   基于标记的再验证
-   自动 TTL 管理
-   Next.js 15+相容性的自动缓冲/字符串转换(以前需要) `buffer-string-decorator` 在1.x.x版本中
-   默认 `revalidateTagQuerySize`数字 : `10_000` (大缓存的安全性)

```js
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";

const redisHandler = await createRedisHandler({
  client: createClient({
    url: process.env.REDIS_URL,
  }),
  keyPrefix: "myApp:",
  sharedTagsKey: "myTags",
  sharedTagsTtlKey: "myTagTtls",
});
```

#### 自定义值序列器

默认情况下,处理器将每个条目存储为 JSON 字符串(`JSON.stringify` 编号 : `JSON.parse`),匹配早先的发布。 你可以用自己的线条格式来收缩有效载荷(压缩),添加加密,或者使用另一个编码——这个软件包不会运送额外的可解码器,所以你的依赖性保持在最小.

**合同**

-   `serialize(value)` 接收完整缓存对象 Next.js 输入(元数据如 `tags`, (中文(简体) ), `lastModified`, (中文(简体) ), `lifespan`,加上被窝 `value` 有效载荷)。 它必须返回适合Redis的字符串 `SET`。 。 。 .
-   `deserialize(stored)` 从 Redis 接收此字符串 `GET`返回与处理器兼容的解析对象,或 `null` 将密钥当作错漏(删除已删除的条目).

处理器正常 `Buffer` 有效载荷内到字符串 `serialize`,然后在 `deserialize`,所以一个平地 `JSON.stringify` 编号 : `JSON.parse` 往返旅行仍然有效.

**默认导出重用**

如果您想要包装或比较行为, 您可以导入内置序列器 :

```js
import createRedisHandler, {
  jsonCacheValueSerializer,
} from "@fortedigital/nextjs-cache-handler/redis-strings";
```

**示例: gzip**

当缓存项是大文本(RSC有效载荷,HTML)时有用. 使用节点的内置 `zlib`· ; `gzipSync` 编号 : `gunzipSync` 缓存时运行在服务器上, 如果您的流量非常热, 则读取并写入配置 .

```js
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import { gzipSync, gunzipSync } from "zlib";

const redisCacheHandler = createRedisHandler({
  client: redisClient,
  keyPrefix: "nextjs:",
  valueSerializer: {
    serialize: (value) => gzipSync(JSON.stringify(value)).toString("base64"),
    deserialize: (stored) => {
      const parsed = JSON.parse(
        gunzipSync(Buffer.from(stored, "base64")).toString("utf-8"),
      );
      return parsed;
    },
  },
});
```

**示例: 溴化物**

当缓存项是大文本(RSC有效载荷,HTML)时有用. 使用节点的内置 `zlib`· ; `brotliCompress` 编号 : `brotliDecompress` 缓存时运行在服务器上, 如果您的流量非常热, 则读取并写入配置 .

```js
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import { brotliCompress, brotliDecompress } from "zlib";
import { promisify } from "util";

const brotliCompressAsync = promisify(brotliCompress);
const brotliDecompressAsync = promisify(brotliDecompress);

const redisCacheHandler = createRedisHandler({
  client: redisClient,
  keyPrefix: "nextjs:",
  valueSerializer: {
    async serialize(value) {
      const compressed = await brotliCompressAsync(
        Buffer.from(JSON.stringify(value), "utf8"),
      );
      return compressed.toString("base64");
    },
    async deserialize(stored) {
      const decompressed = await brotliDecompressAsync(
        Buffer.from(stored, "base64"),
      );
      return JSON.parse(decompressed.toString("utf8"));
    },
  },
});
```

**业务说明**

-   变化 `valueSerializer` (或拖动压缩)使已存在的 Redis 密钥无法被读取,直到您冲出这些密钥或运行迁移;在部署时计划一个密钥前缀凸出或缓存.
-   Tag 映射和 TTL 侧车散列仍然被处理器作为 JSON 存储;只有主条目值使用您的序列器.

#### Redis 集群

```js
import { createCluster } from "@redis/client";
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import { withAdapter } from "@fortedigital/nextjs-cache-handler/cluster/adapter";

const { hostname: redisHostName } = new URL(process.env.REDIS_URL);
redis = withAdapter(
  createCluster({
    rootNodes: [{ url: process.env.REDIS_URL }],

    // optional if you use TLS and need to resolve shards' ip to proper hostname
    nodeAddressMap(address) {
      const [_, port] = address.split(":");

      return {
        host: redisHostName,
        port: Number(port),
      };
    },
  }),
);

// after using withAdapter you can use redis cluster instance as parameter for createRedisHandler
const redisCacheHandler = createRedisHandler({
  client: redis,
  keyPrefix: CACHE_PREFIX,
});
```

### 使用电离层

如果你喜欢使用 `ioredis` 改为 `@redis/client`,可以使用 `ioredisAdapter` 帮手.

`npm i ioredis`

```js
import Redis from "ioredis";
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import { ioredisAdapter } from "@fortedigital/nextjs-cache-handler/helpers/ioredisAdapter";

const client = new Redis(process.env.REDIS_URL);
const redisClient = ioredisAdapter(client);

const redisHandler = createRedisHandler({
  client: redisClient,
  keyPrefix: "my-app:",
});
```

* * *

### `local-lru`

本地lru Handler使用lru-cache QQ实例作为缓存商店. 它将缓存存储在内存中,并在缓存达到极限时驱逐最近使用最少的条目. 当共享缓存无法使用时, 您可以使用这个 Handler 作为倒置缓存 .

> QQ 本地- lru Handler 不适合生产环境. 它只用于发展和测试目的.

**特征 :**

-   使用密钥过期 `EXAT` 或者说 `EXPIREAT`
-   基于标记的再验证
-   自动 TTL 管理
-   默认 `revalidateTagQuerySize`数字 : `10_000` (大缓存的安全性)

```js
import createLruHandler from "@fortedigital/nextjs-cache-handler/local-lru";

const localHandler = createLruHandler({
  maxItemsNumber: 10000,
  maxItemSizeBytes: 1024 * 1024 * 500,
});
```

* * *

### `composite`

路由缓存操作跨越多个基础处理器.

**特征 :**

-   多个后端支持
-   自定义路由策略
-   第一版阅读策略

```js
import createCompositeHandler from "@fortedigital/nextjs-cache-handler/composite";

const compositeHandler = createCompositeHandler({
  handlers: [handler1, handler2],
  setStrategy: (data) => (data?.tags.includes("handler1") ? 0 : 1),
});
```

## 仪器

### 初始缓存登记

默认, `registerInitialCache` 通过覆盖任何已存在的缓存来填充 包含由构建时的文物生成的值的条目(比对调,页面,路由).

#### 初始缓存写入策略

如果您想要保存缓存中可能已经存在的值( 例如, ), 在另一个实例的运行时写入条目,您可以启用 `setOnlyIfNotExists` 选项 :

```ts
await registerInitialCache(CacheHandler, {
  setOnlyIfNotExists: true,
});
```

当启用时, 在初始缓存注册期间执行的缓存写入将仅是 如果相应的缓存密钥不存在,则发生。 这让你可以 明确选择缓存数量策略,而不是执行单一的默认.

## 实例

### 示例项目

这个 [实例项目](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/examples/redis-minimal) next.js 缓存功能的综合演示有交互式实例:

-   **默认缓存** - 证明 `force-cache` 行为
-   **无存储** - 显示 `no-store` 对于永远新鲜的数据
-   **时间调整** - 自动缓存重新验证
-   **用标签获取** - 基于标签的缓存无效
-   **不稳定缓存( c)** - 有标记的函数缓存
-   **以色列** - 递增静态再生
-   **静态参数** - 动态路线静态生成

举例来说:

```bash
pnpm install
cd examples/redis-minimal
npm run build
npm run start
```

> **说明:** 缓存只在生产模式下起作用. 见 [实例](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/examples/redis-minimal/README.md) 更多细节.

### 生产设置示例

这是完整的生产准备 `cache-handler.js` 示例:

```js
import { createClient } from "redis";
import { PHASE_PRODUCTION_BUILD } from "next/constants.js";
import { CacheHandler } from "@fortedigital/nextjs-cache-handler";
import createLruHandler from "@fortedigital/nextjs-cache-handler/local-lru";
import createRedisHandler from "@fortedigital/nextjs-cache-handler/redis-strings";
import createCompositeHandler from "@fortedigital/nextjs-cache-handler/composite";

CacheHandler.onCreation(() => {
  // Important - It's recommended to use global scope to ensure only one Redis connection is made
  // This ensures only one instance get created
  if (global.cacheHandlerConfig) {
    return global.cacheHandlerConfig;
  }

  // Important - It's recommended to use global scope to ensure only one Redis connection is made
  // This ensures new instances are not created in a race condition
  if (global.cacheHandlerConfigPromise) {
    return global.cacheHandlerConfigPromise;
  }

  // You may need to ignore Redis locally, remove this block otherwise
  if (process.env.NODE_ENV === "development") {
    const lruCache = createLruHandler();
    return { handlers: [lruCache] };
  }

  // Main promise initializing the handler
  global.cacheHandlerConfigPromise = (async () => {
    let redisClient = null;

    if (PHASE_PRODUCTION_BUILD !== process.env.NEXT_PHASE) {
      const settings = {
        url: process.env.REDIS_URL,
        pingInterval: 10000,
      };

      // This is optional and needed only if you use access keys
      if (process.env.REDIS_ACCESS_KEY) {
        settings.password = process.env.REDIS_ACCESS_KEY;
      }

      try {
        redisClient = createClient(settings);
        redisClient.on("error", (e) => {
          if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== "undefined") {
            console.warn("Redis error", e);
          }
          global.cacheHandlerConfig = null;
          global.cacheHandlerConfigPromise = null;
        });
      } catch (error) {
        console.warn("Failed to create Redis client:", error);
      }
    }

    if (redisClient) {
      try {
        console.info("Connecting Redis client...");
        await redisClient.connect();
        console.info("Redis client connected.");
      } catch (error) {
        console.warn("Failed to connect Redis client:", error);
        await redisClient
          .disconnect()
          .catch(() =>
            console.warn(
              "Failed to quit the Redis client after failing to connect.",
            ),
          );
      }
    }

    const lruCache = createLruHandler();

    if (!redisClient?.isReady) {
      console.error("Failed to initialize caching layer.");
      global.cacheHandlerConfigPromise = null;
      global.cacheHandlerConfig = { handlers: [lruCache] };
      return global.cacheHandlerConfig;
    }

    const redisCacheHandler = createRedisHandler({
      client: redisClient,
      keyPrefix: "nextjs:",
    });

    global.cacheHandlerConfigPromise = null;

    // This example uses composite handler to switch from Redis to LRU cache if tags contains `memory-cache` tag.
    // You can skip composite and use Redis or LRU only.
    global.cacheHandlerConfig = {
      handlers: [
        createCompositeHandler({
          handlers: [lruCache, redisCacheHandler],
          setStrategy: (ctx) => (ctx?.tags.includes("memory-cache") ? 0 : 1), // You can adjust strategy for deciding which cache should the composite use
        }),
      ],
    };

    return global.cacheHandlerConfig;
  })();

  return global.cacheHandlerConfigPromise;
});

export default CacheHandler;
```

* * *

## 参考原始软件包

这个项目最初的基础是: [`@neshca/cache-handler`](https://www.npmjs.com/package/@neshca/cache-handler)之前的版本 `2.0.0` 包裹或延长原作。 截止 `2.0.0`,该项目完全独立,不再使用或要求 `@neshca/cache-handler`。 。 。 .

对于上下文或历史文献,您仍可参考 [原项目](https://caching-tools.github.io/next-shared-cache)。 。 。 .

## API 参考链接

### Next.js 文档

-   [下一个. js 缓存](https://nextjs.org/docs/app/building-your-application/caching) - 下个.js缓存综合指南
-   [数据获取、缓存和修改](https://nextjs.org/docs/app/building-your-application/data-fetching) - 获取 API 缓存选项
-   [`fetch` API 密码](https://nextjs.org/docs/app/api-reference/functions/fetch) - 下一个.js 获取选项(`next.revalidate`, (中文(简体) ), `next.tags`(中文(简体) )
-   [`revalidateTag`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) - 基于标签的缓存无效
-   [`revalidatePath`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath) - 基于路径的缓存无效
-   [`updateTag`](https://nextjs.org/docs/app/api-reference/functions/updateTag) - 立即缓存无效(下段js 16)
-   [`unstable_cache`](https://nextjs.org/docs/app/api-reference/functions/unstable_cache) - 函数缓存
-   [路由段配置](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config) - 说吧 `revalidate`, (中文(简体) ), `dynamic`等 (中文(简体) ).
-   [递增静态再生](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - 内部审计记录

### Redis 文档

-   [Redis 节点客户端](https://github.com/redis/node-redis) - 官方Redis客户端库
-   [Redis 文档](https://redis.io/docs/) - Redis 服务器文档
-   [Redis 命令](https://redis.io/commands/) - Redis 命令参考

## 解决问题

### 缓存不在开发模式中工作

**问题:** 跑步时卡车好像不起作用 `npm run dev`。 。 。 .

**解决方案 :** 这是预期的行为。 Next.js 故意禁用开发模式中的缓存以更快地热重装. 要测试缓存功能, 您必须使用生产模式 :

```bash
npm run build
npm run start
```

### 重做连接出错

**问题:** 获取连接错误或“ Redis客户端尚未准备好” 错误 .

**解决方案 :**

-   校验 Redis 正在运行 : `redis-cli ping` 应返回 `PONG`
-   检查 `REDIS_URL` 环境变量设置正确
-   确保Redis可以从您的应用程序中访问( 请检查防火墙/ 网络设置)
-   用于生产, 验证 Redis 证书和连接字符串格式
-   检查 Redis 日志的连接问题

### 重新验证 Tag 后缓存不无效

**问题:** 通话 `revalidateTag()` 似乎没有清除缓存.

**解决方案 :**

-   在接下来的.j 16,确保你使用 `revalidateTag(tag, cacheLife)` 与所需 `cacheLife` 参数
-   精确验证标签匹配( 标牌是区分大小写)
-   检查缓存项是用同一标签创建的
-   在开发模式中,缓存被禁用 - 在生产模式中测试

### 从Next.js移徙 14

**问题:** 从Next.js 14到15/16的升级后出错.

**解决方案 :** Next.js 14和15之间的缓存格式不兼容 . **您必须冲出您的 Redis 缓存** 在运行新版本之前 :

```bash
redis-cli FLUSHALL
```

如果使用特定数据库:

```bash
redis-cli -n <database-number> FLUSHDB
```

### 版本相容性问题

**问题:** 软件包版本与您的 Next.js 版本不兼容.

**解决方案 :**

-   Next.js 15:使用 2.0.0+ (3.0.0+建议)版本
-   Next.js 16: 使用版本 3.0.0+(需要)
-   检查 [版本要求](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/#readme-version-requirements) 节
-   校验您的节点. js 版本是 \\ 22. 0.0

### 调试缓存行为

**问题:** 需要调试缓存发生的情况.

**解决方案 :** 通过设置环境变量启用调试记录 :

```bash
NEXT_PRIVATE_DEBUG_CACHE=1 npm run start
```

这将输出详细的缓存操作日志来帮助诊断问题.

## 捐款

这个项目使用 [涡轮](https://turbo.build/repo) 以主软件包和实例管理单列结构.

### 先决条件

-   节点.js 22.0.0
-   时间:

### 发展 工作流量

-   **启动 Dev 服务器**数字 : `pnpm dev` (平行运行所有 dev 服务器)
-   **运行所有测试**数字 : `pnpm test`
-   **运行 e2e 测试**数字 : `pnpm test:e2e`

### 运行e2e测试

Playwright 集成测试启用 [`examples/redis-minimal`](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/examples/redis-minimal)。他们在生产模式中运行实例应用程序,以对抗真正的 Redis 实例,并断言缓存行为(tag/path revalidation,包括Pages路由器).

**先决条件:** Redis 本地运行( 默认) `redis://localhost:6379`) (中文(简体) ).

* * *

## 遗产/贬值

### nish Classic 缓存

⚠️ **折旧:** 此功能从@neshca 迁移出来只是为了兼容的目的 。 谨慎使用 -- -- 没有计划进一步发展或提供支持.

**移徙:** 使用 [`unstable_cache`](https://nextjs.org/docs/app/api-reference/functions/unstable_cache) 相反,它提供了类似的功能和更好的Next.js集成.

`neshClassicCache` 允许您缓存昂贵操作的结果,比如数据库查询,然后在多个请求中重复使用。 与 [`neshCache`](https://npmcn.com/functions/nesh-cache) 或者说 [`unstable_cache` ↗](https://nextjs.org/docs/app/api-reference/functions/unstable_cache) 函数, `neshClassicCache` 必须在 Next.js Pages 路由器中使用,允许用户在 `getServerSideProps` 和API路线.

> \[注\]
> 
> 创建缓存条目 `neshClassicCache` 只能通过 [`revalidateTag` ↗](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) 方法.

#### 参数

-   `fetchData` - 一个同步函数,可以获取要缓存的数据。 它必须是函数返回一个 `Promise`。 。 。 .
-   `commonOptions` - 控制缓存行为的一个对象:
    -   `tags` - 与缓存结果关联的标记系列
    -   `revalidate` - 重新验证间隔数秒
    -   `argumentsSerializer` - 将参数序列化的函数(默认为 `JSON.stringify`(中文(简体) )
    -   `resultSerializer` - 将结果序列化的职能
    -   `resultDeserializer` - 消除结果的功能
    -   `responseContext` - 反应上下文对象

#### 示例

```jsx
import { neshClassicCache } from "@fortedigital/nextjs-cache-handler/functions";
import axios from "axios";

const cachedAxios = neshClassicCache(async (url) => {
  return (await axios.get(url.href)).data;
});

export default async function handler(request, response) {
  const data = await cachedAxios(
    { revalidate: 5, tags: ["api-data"], responseContext: response },
    new URL("https://api.example.com/data.json"),
  );
  response.json(data);
}
```

## 许可证

凭 [MIT 许可证](https://npmcn.com/package/%40fortedigital/nextjs-cache-handler/LICENSE),与原件一致 `@neshca/cache-handler`。 。 。 .

## 常见问题

### @fortedigital/nextjs-cache-handler 是什么？

Next\.js 缓存处理器

### 如何安装 @fortedigital/nextjs-cache-handler？

在项目目录运行 npm install @fortedigital/nextjs-cache-handler，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：next（\>=16\.1\.5）、@redis/client（\>= 5\.8\.3）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @fortedigital/nextjs-cache-handler 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/fortedigital\_\_nextjs-cache-handler 是否存在。

### @fortedigital/nextjs-cache-handler 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @fortedigital/nextjs-cache-handler 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @fortedigital/nextjs-cache-handler 可以商用吗？

@fortedigital/nextjs-cache-handler 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @fortedigital/nextjs-cache-handler 的下载量有多少？

根据 npm 官方下载统计，@fortedigital/nextjs-cache-handler 在 2026/10/16 – 2026/11/14 这 30 天内被下载 645,539 次，日均约 21,518 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @fortedigital/nextjs-cache-handler 还在维护吗？

最新版本 3\.4\.0 发布于 2026/10/16（30 天前）；至今共发布 81 个版本，其中过去 12 个月发布了 23 个；首次发布于 2024/10/02。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

