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核心模块:
- 安装依赖:
npm install @upstash/redis - 创建客户端:
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
相关产品推荐
相关产品推荐

