Next.js中使用MongoDB的$eq动态传slug查询文档报错解决
问题:Next.js中通过动态Slug从MongoDB获取文档时出现模块缺失错误
问题代码
用户在pages/[videoPage].js中编写的getStaticProps代码:
export async function getStaticProps(context) { const postSlug = context.params.postPage; const { db } = await connectToDatabase(); const posts = await db .collection("posts") .find({ slug: { $eq: postSlug } }) .toArray(); return { props: { posts: JSON.parse(JSON.stringify(posts)), }, }; }
报错信息
运行时出现以下错误:
./node_modules/mongodb/lib/cmap/auth/gssapi.js:4:0 Module not found: Can't resolve 'dns' Import trace for requested module: ./node_modules/mongodb/lib/index.js ./pages/[videoPage].js
MongoDB数据结构
数据库中posts集合的文档结构:
[ { "Post": "this is a post", "_id": ObjectId("630f3c32c1a580642a9ff4a0"), "slug": "this-is-a-title", "title": "This is a title" }, { "Post": "this is a post", "_id": ObjectId("630f3c32c1a580642a9ff4a1"), "slug": "this-is-a-titleb", "title": "This is a titleB" } ]
用户反馈:硬编码Slug时代码可正常运行,动态传参时触发上述错误。
解决方案
1. 修正参数名不匹配问题
你的页面文件是[videoPage].js,所以context.params中的动态参数名应该是videoPage,而非postPage,这会导致你获取的Slug值为空或错误,修正后代码如下:
const postSlug = context.params.videoPage;
2. 解决dns模块缺失问题
这个错误是因为MongoDB驱动依赖Node.js核心模块dns,但Next.js在客户端构建时默认不会打包这类模块。可以通过以下两种方式解决:
方式一:配置Next.js的Webpack fallback
在项目根目录的next.config.js中添加如下配置,告知Webpack忽略这些Node.js核心模块(仅在客户端环境生效):
module.exports = { webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { ...config.resolve.fallback, dns: false, net: false, tls: false }; } return config; }, };
方式二:降级MongoDB驱动版本
部分高版本的mongodb包引入了额外的核心模块依赖,你可以降级到兼容的版本,比如4.11.0:
npm install mongodb@4.11.0 # 或使用yarn yarn add mongodb@4.11.0
3. 优化查询逻辑(可选)
因为Slug是唯一标识,使用findOne替代find.toArray()可以直接返回单个文档,更高效:
const post = await db.collection("posts").findOne({ slug: postSlug }); return { props: { post: JSON.parse(JSON.stringify(post)), }, };
内容的提问来源于stack exchange,提问作者Tribe56123
相关产品推荐
相关产品推荐

