You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Next.js TypeScript项目中集成Redis自定义缓存处理器时遇到配置与运行错误

在Next.js TypeScript项目中集成Redis自定义缓存处理器时遇到配置与运行错误

我明白你在Next.js TS项目里搭建Redis缓存处理器时踩了不少坑,咱们一步步拆解问题,逐个解决:

一、核心运行错误:TypeError: CurCacheHandler is not a constructor

这是最紧急的问题——Next.js要求自定义缓存处理器必须导出一个构造函数(类或函数),而不是提前实例化好的对象。你当前的代码导出的是new CacheHandler()创建的实例,Next.js会尝试调用这个导出值作为构造函数,自然会报错。

修复方案:

把缓存处理器的导出逻辑改成导出类本身,而不是实例:

// lib/cache-handler.js(如果后续改回TS,逻辑一致)
const getRedisInstance = require('./redis');

class CacheHandler {
  // 你的类逻辑保持不变...
}

// ❌ 不要导出实例,改成导出类
// const cacheInstance = new CacheHandler();
// module.exports = cacheInstance;

✅ module.exports = CacheHandler;

如果后续切换回TypeScript,导出方式对应改为:

export default CacheHandler;

二、解决TypeScript不识别cache-handler.ts的问题

之前你被迫把TS文件改成JS,主要是配置没到位,调整以下几点:

  1. 更新tsconfig.json的include字段:
    确保lib/cache-handler.ts被包含在编译范围内,去掉原来的.js版本路径:
{
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "next-env.d.ts",
    ".next/types/**/*.ts",
    "lib/redis.ts", // 同步把redis也改成TS文件
    "lib/cache-handler.ts"
  ]
}
  1. 修正tsconfig.json的配置位置:
    你把noUnusedLocals和noUnusedParameters放在了根节点,这些属于编译选项,要移到compilerOptions里:
{
  "compilerOptions": {
    // 其他选项保持不变...
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  // 其他根节点配置...
}
  1. 给Redis客户端添加TS支持:
    把lib/redis.js改成lib/redis.ts,补上类型断言(避免环境变量的类型报错):
import Redis from 'ioredis';

// 断言REDIS_URL存在,或者你可以加个判断处理不存在的情况
const redis = new Redis(process.env.REDIS_URL as string);

export default redis;

三、修正next.config.js的配置错误

你的next.config.js有两处问题:

  1. logging字段嵌套错误,verbose级别应该直接放在logging下,而不是嵌套的logging.logging;
  2. 配置对象未闭合,缺少结尾的}和导出语句。

修复后的完整配置:

/**
 * @format
 * @type {import('next').NextConfig}
 */
const path = require("path");
const nextConfig = {
  logging: {
    level: 'verbose', // 正确的日志级别配置
    fetches: {
      fullUrl: true,
    },
  },
  eslint: {
    dirs: ['src'],
  },
  cacheHandler: path.resolve(__dirname, "lib/cache-handler.ts"), // 改回TS文件路径
  cacheMaxMemorySize: 0, // 禁用默认内存缓存
};

// 别忘了导出配置
module.exports = nextConfig;

四、TypeScript版本缓存处理器的优化(可选)

如果用TS,可以让类实现Next.js的CacheHandler接口,获得类型提示:

import type { CacheHandler } from 'next/dist/server/lib/incremental-cache';
import redis from './redis';

class RedisCacheHandler implements CacheHandler {
  private static instance: RedisCacheHandler;
  private options: { ttl: number };

  constructor(options: { ttl?: number } = { ttl: 3600 }) {
    if (!RedisCacheHandler.instance) {
      this.options = { ttl: 3600, ...options };
      RedisCacheHandler.instance = this;
    }
    return RedisCacheHandler.instance;
  }

  async get(key: string): Promise<any | null> {
    const cachedData = await redis.get(key);
    return cachedData ? JSON.parse(cachedData) : null;
  }

  async set(key: string, data: any, ctx: { tags?: string[] } = {}): Promise<void> {
    const cacheEntry = {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags || [],
    };

    await redis.set(key, JSON.stringify(cacheEntry), 'EX', this.options.ttl);

    if (ctx.tags) {
      for (const tag of ctx.tags) {
        await redis.sadd(`tag:${tag}`, key);
      }
    }
  }

  async revalidateTag(tags: string | string[]): Promise<void> {
    const tagList = Array.isArray(tags) ? tags : [tags];

    for (const tag of tagList) {
      const keys = await redis.smembers(`tag:${tag}`);
      if (keys.length) {
        await redis.del(...keys);
        await redis.del(`tag:${tag}`);
      }
    }
  }

  resetRequestCache(): void {}
}

export default RedisCacheHandler;

按照上面的步骤调整后,应该能解决你遇到的所有问题。

备注:内容来源于stack exchange,提问作者Pirathikaran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:40:29