将 Mongoose 与 Next.js 一起使用
¥Using Mongoose With Next.js
Next.js 是一个流行的框架,用于使用 React 构建全栈应用。Mongoose 与 Next.js 一起开箱即用。如果你想开始使用,请使用 Next.js 的官方 Mongoose 示例应用。此外,如果你将 Next.js 与 Vercel 无服务器函数 一起使用,请查看 Mongoose 的 AWS Lambda 文档。
¥Next.js is a popular framework for building full stack applications with React. Mongoose works out of the box with Next.js. If you're looking to get started, please use Next.js' official Mongoose sample app. Furthermore, if you are using Next.js with Vercel Serverless Functions, please review Mongoose's AWS Lambda docs.
快速开始
¥Quick Start
以下是使用 Mongoose 和 Next.js 应用路由的基本示例:
¥Here's a basic example of using Mongoose with Next.js App Router:
// lib/mongodb.js
import mongoose from 'mongoose';
const MONGODB_URI = process.env.MONGODB_URI;
export default dbConnect;
async function dbConnect() {
if (!MONGODB_URI) {
throw new Error('Please define the MONGODB_URI environment variable');
}
await mongoose.connect(MONGODB_URI);
return mongoose;
}然后在 API 路由或服务器组件中使用它:
¥Then use it in your API routes or Server Components:
// app/api/users/route.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export async function GET() {
await dbConnect();
const users = await User.find({});
return Response.json({ users });
}
最佳实践
¥Best Practices
连接管理
¥Connection Management
Mongoose 会自动处理连接管理。如果 Mongoose 已经连接,调用 mongoose.connect() 不会执行任何操作,因此你可以安全地在每个 API 路由和服务器组件中调用 dbConnect(),而无需担心创建多个连接。
¥Mongoose handles connection management automatically. Calling mongoose.connect() when Mongoose is already connected is a no-op, so you can safely call dbConnect() in every API route and Server Component without worrying about creating multiple connections.
环境变量
¥Environment Variables
将你的 MongoDB 连接字符串存储在 .env.local 中:
¥Store your MongoDB connection string in .env.local:
MONGODB_URI=mongodb://localhost:27017/mydb对于生产环境,请在你的托管平台(Vercel、Netlify 等)中使用环境变量。
¥For production, use environment variables in your hosting platform (Vercel, Netlify, etc.).
模型注册
¥Model Registration
请在单独的目录中定义你的模型,并确保它们只注册一次:
¥Define your models in a separate directory and ensure they're only registered once:
// models/User.js
import mongoose from 'mongoose';
const UserSchema = new mongoose.Schema({
name: String,
email: { type: String, required: true }
}, { timestamps: true });
export default mongoose.models.User || mongoose.model('User', UserSchema);mongoose.models.User || mongoose.model('User', UserSchema) 模式可防止在开发过程中热重载时出现模型重新编译错误。
¥The mongoose.models.User || mongoose.model('User', UserSchema) pattern prevents model recompilation errors during hot reloading in development.
常见问题
¥Common Issues
使用 Next.js 时有一些你应该注意的常见问题。
¥There are a few common issues when working with Next.js that you should be aware of.
类型错误:无法读取未定义的属性(读取 'prototype')
¥TypeError: Cannot read properties of undefined (reading 'prototype')
你可以通过将以下内容添加到 next.config.js 来解决此问题:
¥You can fix this issue by adding the following to your next.config.js:
const nextConfig = {
experimental: {
esmExternals: "loose", // <-- add this
serverComponentsExternalPackages: ["mongoose"] // <-- and this
},
// and the following to enable top-level await support for Webpack
webpack: (config) => {
config.experiments = {
topLevelAwait: true
};
return config;
},
}此问题是由 MongoDB 的 bson 解析器的这一变化 引起的。MongoDB 的 bson 解析器在 ESM 结构下使用顶层等待和动态导入来避免一些 Webpack 打包问题。Next.js 强制使用 ESM 结构。
¥This issue is caused by this change in MongoDB's bson parser. MongoDB's bson parser uses top-level await and dynamic import in ESM mode to avoid some Webpack bundling issues. And Next.js forces ESM mode.
与 Pages Router 结合使用
¥Using with Pages Router
如果你使用的是 Next.js Pages Router,则可以在 API 路由和 getServerSideProps 中使用 Mongoose:
¥If you're using Next.js Pages Router, you can use Mongoose in API routes and getServerSideProps:
// pages/api/users.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export default async function handler(req, res) {
await dbConnect();
if (req.method === 'GET') {
const users = await User.find({});
return res.status(200).json({ users });
}
if (req.method === 'POST') {
const user = await User.create(req.body);
return res.status(201).json({ user });
}
res.status(405).json({ error: 'Method not allowed' });
}在 getServerSideProps 中使用:
¥Using in getServerSideProps:
// pages/users.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export async function getServerSideProps() {
await dbConnect();
const users = await User.find({});
return {
props: {
users: JSON.parse(JSON.stringify(users))
}
};
}
export default function UsersPage({ users }) {
return (
<div>
<h1>Users</h1>
{users.map(user => (
<div key={user._id.toString()}>{user.name}</div>
))}
</div>
);
}重要提示:使用 JSON.parse(JSON.stringify()) 将 Mongoose 文档转换为普通对象,因为 Next.js 需要可序列化的数据。
¥Important: Use JSON.parse(JSON.stringify()) to convert Mongoose documents to plain objects, as Next.js requires serializable data.
与 App Router 服务器组件结合使用
¥Using with App Router Server Components
在 Next.js 13+ 的 App Router 中,你可以直接在服务器组件中使用 Mongoose:
¥With Next.js 13+ App Router, you can use Mongoose directly in Server Components:
// app/users/page.js
import dbConnect from '@/lib/mongodb';
import User from '@/models/User';
export const runtime = 'nodejs';
export default async function UsersPage() {
await dbConnect();
const users = await User.find({}).lean();
return (
<div>
<h1>Users</h1>
{users.map(user => (
<div key={user._id.toString()}>{user.name}</div>
))}
</div>
);
}
Next.js 边缘运行时
¥Next.js Edge Runtime
Mongoose 目前不支持 Next.js 边缘运行时。Mongoose 无法在 Edge Runtime 中连接到 MongoDB,因为 Edge Runtime 目前不支持 Node.js net API,这是 MongoDB Node 驱动程序用来连接到 MongoDB 的。
¥Mongoose does not currently support Next.js Edge Runtime.
There is no way for Mongoose to connect to MongoDB in Edge Runtime, because Edge Runtime currently doesn't support Node.js net API, which is what the MongoDB Node Driver uses to connect to MongoDB.
其他资源
¥Additional Resources
Mongoose AWS Lambda 指南(适用于无服务器架构)部署)
¥Mongoose AWS Lambda Guide (for serverless deployments)
