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

Next.js 13.4连接Redis(rediss)遇TypeError: url_1.URL is not a constructor

Redis连接在Next.js 13.4 Edge Runtime中报错:url_1.URL is not a constructor

问题背景

在纯Node.js环境中,使用官方redis客户端连接Redis(包括SSL连接)完全正常:

Node.js环境正常代码

// src/redis-client.js
const { createClient } = require('redis');

const redisClient = createClient({
  url: REDIS_URL, // 来自Vercel KV的连接地址
});

redisClient.on('error', (error) => {
  console.error('Redis Error:', error);
});

redisClient.connect();

module.exports = redisClient;
// test-redis.js
const redisClient = require('./src/redis-client')

const testRedis = async () => {
    const key = 'foo';
    const value = 'bar';
    const result = await redisClient.set(key, value, { EX: 60 });
    console.log(result);
    const result2 = await redisClient.get(key);
    console.log(result2);
    await redisClient.quit()
};

testRedis();

执行node test-redis.js后功能正常。

但在Next.js 13.4环境中,使用以下代码创建客户端时:

import { createClient } from 'redis';

console.log(process.env.REDIS_URL) // 能正确输出连接地址

const redisClient = createClient({ url: process.env.REDIS_URL }); // 此处报错

redisClient.on('error', (error) => {
  console.error('Redis Error:', error);
});

redisClient.connect();

export default redisClient; 

出现报错:

- event compiled client and server successfully in 2.7s (3788 modules)
- error Error [TypeError]: url_1.URL is not a constructor
    at <unknown> (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/client/index.js:86)
    at Function.parseURL (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/client/index.js:86:76)
    at Commander._RedisClient_initiateOptions (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/client/index.js:394:27)
    at new RedisClient (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/client/index.js:202:148)
    at new Commander (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/commander.js:46:13)
    at create (webpack-internal:///(middleware)/./node_modules/@redis/client/dist/lib/client/index.js:82:16)
    at createClient (webpack-internal:///(middleware)/./node_modules/redis/dist/index.js:78:38)
    at eval (webpack-internal:///(middleware)/./src/redis-client.ts:8:72)
    at Module.(middleware)/./src/redis-client.ts (file:///Users/shreyas/Desktop/planet-webapp/.next/server/middleware.js:6408:1)
    at __webpack_require__ (file:///Users/shreyas/Desktop/planet-webapp/.next/server/edge-runtime-webpack.js:37:33)
    at fn (file:///Users/shreyas/Desktop/planet-webapp/.next/server/edge-runtime-webpack.js:268:21) {
  digest: undefined
}

此前使用dotenv时也出现类似环境差异问题:Node.js中正常,Next.js里提示process.cwd不是函数。

原因分析

你的怀疑完全正确——问题根源在于Next.js的Edge Runtime:

  • Edge Runtime基于V8引擎,仅支持Web标准API和部分Node.js API,不包含完整的Node.js核心模块;
  • 官方redis客户端内部依赖了Node.js专属的URL构造函数实现,而Edge Runtime中的URL是Web标准版本,二者存在差异,导致解析URL时抛出错误;
  • 之前的process.cwd报错也是同理:Edge Runtime不支持Node.js的process模块的部分方法。

解决方案

方案1:切换到Node.js Runtime

如果你的代码不需要Edge Runtime的特性(如全球边缘部署、低延迟),可以直接指定使用Node.js Runtime:

  • 在Middleware文件中添加:
    export const runtime = 'nodejs';
    
  • 在App Router的路由组件/API路由中添加:
    export const runtime = 'nodejs';
    

切换后,代码会在Node.js环境中运行,和你本地测试的环境一致,即可正常使用官方redis客户端。

方案2:使用Edge兼容的Redis客户端

改用专门为Serverless/Edge环境设计的Redis客户端,比如@upstash/redis,它完全基于Web标准API,无需依赖Node.js核心模块:

  1. 安装依赖:
    npm install @upstash/redis
    
  2. 创建客户端:
    import { Redis } from '@upstash/redis';
    
    const redisClient = new Redis({
      url: process.env.REDIS_URL,
      token: process.env.REDIS_TOKEN, // 若使用Upstash Redis需提供token;Vercel KV可直接用URL
    });
    
    export default redisClient;
    

该客户端支持所有Redis基础操作,且完美适配Next.js Edge Runtime。

方案3:手动拆分Redis连接参数(继续使用官方客户端)

绕过客户端的URL解析逻辑,手动拆分连接参数传入,避免触发Node.js专属的URL构造函数:

import { createClient } from 'redis';

// 用Web标准URL构造函数解析参数(Edge Runtime支持该版本)
const urlParts = new URL(process.env.REDIS_URL);

const redisClient = createClient({
  host: urlParts.hostname,
  port: parseInt(urlParts.port),
  password: urlParts.password,
  tls: {
    servername: urlParts.hostname
  }
});

redisClient.on('error', (error) => {
  console.error('Redis Error:', error);
});

redisClient.connect();

export default redisClient;

内容的提问来源于stack exchange,提问作者Shreyas Chorge

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:03:18