在 Mongoose 项目之间共享模式

在大型组织中,通常会有一个包含多个项目之间共享的模式的项目。例如,假设您的公司有一个@initech/shared-schemas私有 npm 包,而npm list看起来如下所示

@initech/[email protected]
├── @initech/[email protected]
├── [email protected]

在上面的输出中,@initech/web-app1是一个客户端项目,而@initech/shared-schemas共享库

将 Mongoose 作为对等依赖项

首先,也是最重要的一点,我们建议@initech/shared-schemas您共享的模式的peerDependencies中列出 Mongoose,而不是作为顶级依赖项。例如,@initech/shared-schemaspackage.json应该如下所示。

{
  "name": "@initech/shared-schemas",
  "peerDependencies": {
    "mongoose": "8.x"
  }
}

我们推荐这种方法的原因如下

  1. 更容易升级。例如,假设@initech/shared-schemas依赖于 Mongoose 8,而@initech/web-app1可以很好地与 Mongoose 8 协同工作;但是,@initech/web-app2无法从 Mongoose 7 升级。对等依赖关系使依赖于共享模式的项目更容易确定他们想要的 Mongoose 版本,而不会冒出现 Mongoose 模块版本冲突的风险。
  2. 减少 Mongoose 模块重复的风险。不支持将来自一个版本的 Mongoose 的 Mongoose 模式和模型与另一个版本的 Mongoose 一起使用。

导出模式,而不是模型

我们建议@initech/shared-schemas导出 Mongoose 模式,而不是模型。这种方法更加灵活,允许客户端项目使用其首选模式实例化模型。特别是,如果@initech/shared-schemas导出使用mongoose.model()注册的模型,则无法将该模型传输到另一个连接。

// `userSchema.js` in `@initech/shared-schemas`
const userSchema = new mongoose.Schema({ name: String });

// Do this:
module.exports = userSchema;

// Not this:
module.exports = mongoose.model('User', userSchema);

解决方法:导出 POJO

有时,现有的共享库不遵循上述最佳实践。如果您发现自己有一个依赖于旧版本的 Mongoose 的共享库,一个有用的解决方法是导出POJO,而不是模式或模型。这将消除共享库的 Mongoose 版本与客户端项目的 Mongoose 版本之间的任何冲突。

// Replace this:
module.exports = new mongoose.Schema({ name: String });

// With this:
module.exports = { name: String };

并更新您的客户端项目以执行以下操作

// Replace this:
const { userSchema } = require('@initech/shared-schemas');

// With this:
const { userSchemaDefinition } = require('@initech/shared-schemas');
const userSchema = new mongoose.Schema(userSchemaDefinition);