在 Mongoose 项目之间共享结构

¥Sharing Schemas Between Mongoose Projects

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

¥In larger organizations, it is common to have a project that contains schemas which are shared between multiple projects. For example, suppose your company has an @initech/shared-schemas private npm package, and npm list looks like the following:

@initech/web-app1@1.0.0
├── @initech/shared-schemas@1.0.0
├── mongoose@8.0.1

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

¥In the above output, @initech/web-app1 is a client project and @initech/shared-schemas is the shared library.

将 Mongoose 作为对等依赖

¥Put Mongoose as a Peer Dependency

首先,也是最重要的,我们建议 @initech/shared-schemas你的共享架构的 peerDependencies 中列出 Mongoose,而不是作为顶层依赖。例如,@initech/shared-schemaspackage.json 应如下所示。

¥First, and most importantly, we recommend that @initech/shared-schemas list Mongoose in your shared-schema's peerDependencies, not as a top-level dependency. For example, @initech/shared-schemas's package.json should look like the following.

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

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

¥We recommend this approach for the following reasons:

  1. 升级更容易。例如,假设 @initech/shared-schemas 依赖于 Mongoose 8,而 @initech/web-app1 与 Mongoose 8 配合良好;但 @initech/web-app2 无法从 Mongoose 7 升级。对等依赖使依赖共享模式的项目可以更轻松地确定他们想要的 Mongoose 版本,而不会冒 Mongoose 模块版本冲突的风险。

    ¥Easier to upgrade. For example, suppose @initech/shared-schemas has a dependency on Mongoose 8, and @initech/web-app1 works fine with Mongoose 8; but @initech/web-app2 cannot upgrade from Mongoose 7. Peer dependencies makes it easier for the projects that rely on your shared schemas to determine which version of Mongoose they want, without risking having conflicting versions of the Mongoose module.

  2. 降低 Mongoose 模块重复的风险。不支持将一个版本的 Mongoose 中的 Mongoose 架构和模型与另一版本一起使用。

    ¥Reduce risk of Mongoose module duplicates. Using Mongoose schemas and models from one version of Mongoose with another version is not supported.

导出结构,而不是模型

¥Export Schemas, Not Models

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

¥We recommend that @initech/shared-schemas export Mongoose schemas, not models. This approach is more flexible and allows client projects to instantiate models using their preferred patterns. In particular, if @initech/shared-schemas exports a model that is registered using mongoose.model(), there is no way to transfer that model to a different connection.

// `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

¥Workaround: Export a POJO

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

¥Sometimes, existing shared libraries don't follow the above best practices. If you find yourself with a shared library that depends on an old version of Mongoose, a helpful workaround is to export a POJO rather than a schema or model. This will remove any conflicts between the shared library's version of Mongoose and the client project's version of Mongoose.

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

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

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

¥And update your client project to do the following:

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

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