MongoDB正则查询本地正常但Vercel部署失败问题排查
Next.js 14 + Mongoose 正则查询Vercel部署栈溢出问题
问题场景
以下是基于Mongoose的Next.js 14页面代码,逻辑为检测email查询参数,存在则执行MongoDB正则匹配查询:
import { User } from "@/mongo"; import { SearchBar, UserRating } from "./components"; type searchParams = { email?: string; }; export default async function Search({ searchParams }: { searchParams: searchParams}) { const isCustomer = true; const users = await User.find({email: {$regex: searchParams.email ? searchParams.email : ""}}) return ( <> <SearchBar /> <section className="reviews"> {users.map((user, i) => ( <UserRating stars={user.customerRating} isCustomer={isCustomer} author={user._id} key={i}/> ))} </section> </> ); }
该逻辑在本地开发及本地生产构建均正常,但部署到Vercel时构建失败,其他MongoDB调用无异常。
Vercel构建报错日志
RangeError: Maximum call stack size exceeded at RegExp exec (<anonymous>) at create (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:18889) at create (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:18918) at create (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:18918) at parse.fastpaths (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:18997) at picomatch.makeRe (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:21635) at picomatch (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:19637) at /vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:19294 at Array.map (<anonymous>) at picomatch (/vercel/path0/node_modules/next/dist/compiled/micromatch/index.js:15:18918) Error: Command "npm run build" exited with 1
问题原因
- 空正则触发无限递归:当
searchParams.email不存在时,代码传入$regex: ""(空字符串正则),该正则会匹配任意内容。Next.js构建时依赖的micromatch库在处理这类空正则时,会进入递归调用的死循环,导致栈溢出。 - 静态渲染冲突:Next.js 14 App Router默认会尝试静态渲染页面,若页面包含依赖动态参数的数据库查询,构建阶段会执行该查询。空正则的查询逻辑在静态构建时触发了上述递归问题。
解决方案
方案1:优化查询逻辑,避免空正则
修改查询条件,仅当email参数存在时才添加正则匹配,否则使用空查询(或按需调整为无结果查询):
import { User } from "@/mongo"; import { SearchBar, UserRating } from "./components"; type searchParams = { email?: string; }; export default async function Search({ searchParams }: { searchParams: searchParams }) { const isCustomer = true; // 仅当email存在时构建正则查询条件 const query = searchParams.email ? { email: { $regex: searchParams.email, $options: "i" } } // 可选添加i忽略大小写 : {}; // 空查询返回所有用户,若需无结果可改为 { email: { $exists: false } } const users = await User.find(query); return ( <> <SearchBar /> <section className="reviews"> {users.map((user) => ( <UserRating stars={user.customerRating} isCustomer={isCustomer} author={user._id} key={user._id}/> ))} </section> </> ); }
方案2:强制页面动态渲染
添加动态渲染标记,避免Next.js在构建阶段执行查询:
// 在页面顶部添加 export const dynamic = "force-dynamic";
该配置会让页面每次请求都动态生成,不会在构建阶段执行数据库查询,从根源避免静态构建时的递归问题。
额外优化
- 将
map的key从索引i改为user._id,避免列表重渲染时的性能问题和警告。
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

