工作空间
工作空间
Nest 有两种代码组织模式:
- 标准模式:适用于构建具有自己依赖项和设置的单个项目导向应用程序,不需要优化模块共享或优化复杂构建。这是默认模式。
- monorepo 模式:此模式将代码工件视为轻量级 monorepo 的一部分,可能更适合开发团队和/或多项目环境。它自动化构建过程的部分内容,使创建和组合模块化组件变得容易,促进代码重用,使集成测试更容易,使共享项目范围的工件(如
eslint规则和其他配置策略)变得容易,并且比 Git 子模块等替代方案更容易使用。Monorepo 模式采用工作空间的概念,在nest-cli.json文件中表示,以协调 monorepo 组件之间的关系。
重要的是要注意,Nest 的几乎所有功能都独立于您的代码组织模式。此选择的唯一影响是如何组合项目以及如何生成构建工件。从 CLI 到核心模块再到附加模块的所有其他功能在任一模式下都以相同方式工作。
此外,您可以随时轻松地从标准模式切换到 monorepo 模式,因此您可以推迟此决定,直到一种或另一种方法的好处变得更加清晰。
标准模式
当您运行 nest new 时,使用内置原理图为您创建一个新项目。Nest 执行以下操作:
- 创建一个新文件夹,对应于您提供给
nest new的name参数 - 使用对应于最小基础级别 Nest 应用程序的默认文件填充该文件夹。您可以在 typescript-starter 存储库中检查这些文件。
- 提供其他文件,如
nest-cli.json、package.json和tsconfig.json,这些文件配置并启用各种工具来编译、测试和服务您的应用程序。
从那里,您可以修改启动文件、添加新组件、添加依赖项(例如,npm install),并以本文档其余部分所涵盖的方式开发您的应用程序。
Monorepo 模式
要启用 monorepo 模式,您从_标准模式_结构开始,并添加项目。项目可以是完整的应用程序(您使用命令 nest generate app 将其添加到工作空间)或库(您使用命令 nest generate library 将其添加到工作空间)。我们将在下面讨论这些特定类型项目组件的详细信息。现在要注意的关键点是,向现有标准模式结构添加项目的行为将其转换为 monorepo 模式。让我们看一个例子。
如果我们运行:
$ nest new my-project
我们构建了一个_标准模式_结构,文件夹结构如下所示:
node_modules/
src/
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts
nest-cli.json
package.json
tsconfig.json
eslint.config.mjs
我们可以按如下方式将其转换为 monorepo 模式结构:
$ cd my-project
$ nest generate app my-app
此时,nest 将现有结构转换为 monorepo 模式结构。这导致一些重要的变化。文件夹结构现在如下所示:
apps/
├── my-app/
│ ├── src/
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.ts
│ │ └── main.ts
│ └── tsconfig.app.json
└── my-project/
├── src/
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
└── tsconfig.app.json
nest-cli.json
package.json
tsconfig.json
eslint.config.mjs
generate app 原理图重新组织了代码 - 将每个应用程序项目移动到 apps 文件夹下,并在每个项目的根文件夹中添加特定于项目的 tsconfig.app.json 文件。我们原始的 my-project 应用程序已成为 monorepo 的默认项目,现在与刚添加的 my-app 是对等的,位于 apps 文件夹下。我们将在下面介绍默认项目。
警告 标准模式结构到 monorepo 的转换仅适用于遵循规范 Nest 项目结构的项目。具体来说,在转换过程中,原理图尝试将项目文件夹中的 src 和 test 文件夹重新定位到根目录下的 apps 文件夹中的项目文件夹下。如果项目不使用此结构,转换将失败或产生不可靠的结果。
工作空间项目
monorepo 使用工作空间的概念来管理其成员实体。工作空间由项目组成。项目可以是:
- 应用程序:包含
main.ts文件以引导应用程序的完整 Nest 应用程序。除了编译和构建考虑之外,工作空间内的应用程序类型项目在功能上与_标准模式_结构内的应用程序相同。 - 库:库是一种打包通用功能集(模块、提供者、控制器等)的方式,可以在其他项目中使用。库不能独立运行,并且没有
main.ts文件。在这里阅读更多关于库的信息。
所有工作空间都有一个默认项目(应该是应用程序类型项目)。这由 nest-cli.json 文件中的顶级 "root" 属性定义,该属性指向默认项目的根目录(有关更多详细信息,请参阅下面的 CLI 属性)。通常,这是您开始使用的标准模式应用程序,后来使用 nest generate app 转换为 monorepo。当您遵循这些步骤时,此属性会自动填充。
当未提供项目名称时,nest build 和 nest start 等 nest 命令使用默认项目。
例如,在上述 monorepo 结构中,运行
$ nest start
将启动 my-project 应用程序。要启动 my-app,我们将使用:
$ nest start my-app
应用程序
应用程序类型项目,或我们可能非正式地称为"应用程序",是您可以运行和部署的完整 Nest 应用程序。您使用 nest generate app 生成应用程序类型项目。
此命令自动生成项目骨架,包括来自 typescript starter 的标准 src 和 test 文件夹。与标准模式不同,monorepo 中的应用程序项目没有任何包依赖项(package.json)或其他项目配置工件,如 .prettierrc 和 eslint.config.mjs。相反,使用 monorepo 范围的依赖项和配置文件。
但是,原理图确实在项目的根文件夹中生成特定于项目的 tsconfig.app.json 文件。此配置文件自动设置适当的构建选项,包括正确设置编译输出文件夹。该文件扩展顶级(monorepo)tsconfig.json 文件,因此您可以在 monorepo 范围内管理全局设置,但如果需要,可以在项目级别覆盖它们。
库
如前所述,库类型项目或简称"库"是需要组合到应用程序中才能运行的 Nest 组件包。您使用 nest generate library 生成库类型项目。决定什么属于库是一个架构设计决策。我们在库章节中深入讨论库。
CLI 属性
Nest 在 nest-cli.json 文件中保留组织、构建和部署标准和 monorepo 结构项目所需的元数据。当您添加项目时,Nest 会自动添加和更新此文件,因此您通常不必考虑它或编辑其内容。但是,有一些设置您可能想要手动更改,因此对文件有一个概览了解是有帮助的。
运行上述步骤创建 monorepo 后,我们的 nest-cli.json 文件如下所示:
{
"collection": "@nestjs/schematics",
"sourceRoot": "apps/my-project/src",
"monorepo": true,
"root": "apps/my-project",
"compilerOptions": {
"webpack": true,
"tsConfigPath": "apps/my-project/tsconfig.app.json"
},
"projects": {
"my-project": {
"type": "application",
"root": "apps/my-project",
"entryFile": "main",
"sourceRoot": "apps/my-project/src",
"compilerOptions": {
"tsConfigPath": "apps/my-project/tsconfig.app.json"
}
},
"my-app": {
"type": "application",
"root": "apps/my-app",
"entryFile": "main",
"sourceRoot": "apps/my-app/src",
"compilerOptions": {
"tsConfigPath": "apps/my-app/tsconfig.app.json"
}
}
}
}
该文件分为几个部分:
- 具有控制标准和 monorepo 范围设置的顶级属性的全局部分
- 具有关于每个项目的元数据的顶级属性(
"projects")。此部分仅存在于 monorepo 模式结构中。
顶级属性如下:
"collection":指向用于生成组件的原理图集合;您通常不应更改此值"sourceRoot":指向标准模式结构中单个项目的源代码根目录,或 monorepo 模式结构中_默认项目_的源代码根目录"compilerOptions":具有指定编译器选项的键和指定选项设置的值的映射;请参阅下面的详细信息"generateOptions":具有指定全局生成选项的键和指定选项设置的值的映射;请参阅下面的详细信息"monorepo":(仅限 monorepo)对于 monorepo 模式结构,此值始终为true"root":(仅限 monorepo)指向_默认项目_的项目根目录
全局编译器选项
这些属性指定要使用的编译器以及影响任何编译步骤的各种选项,无论是作为 nest build 或 nest start 的一部分,还是无论编译器是 tsc 还是 webpack。
| 属性名称 | 属性值类型 | 描述 |
|---|---|---|
webpack | boolean | 如果为 true,使用 webpack 编译器。如果为 false 或不存在,使用 tsc。在 monorepo 模式下,默认值为 true(使用 webpack),在标准模式下,默认值为 false(使用 tsc)。有关详细信息,请参阅下文。(已弃用:请使用 builder) |
tsConfigPath | string | (仅限 monorepo)指向包含 tsconfig.json 设置的文件,当调用 nest build 或 nest start 而不带 project 选项时将使用这些设置(例如,当构建或启动默认项目时)。 |
webpackConfigPath | string | 指向 webpack 选项文件。如果未指定,Nest 查找文件 webpack.config.js。有关更多详细信息,请参阅下文。 |
deleteOutDir | boolean | 如果为 true,每当调用编译器时,它将首先删除编译输出目录(如 tsconfig.json 中配置的,默认为 ./dist)。 |
assets | array | 每当编译步骤开始时,启用自动分发非 TypeScript 资产(资产分发在 --watch 模式下的增量编译中不会发生)。有关详细信息,请参阅下文。 |
watchAssets | boolean | 如果为 true,在监视模式下运行,监视所有非 TypeScript 资产。(有关要监视的资产的更细粒度控制,请参阅下面的资产部分)。 |
manualRestart | boolean | 如果为 true,启用快捷键 rs 手动重启服务器。默认值为 false。 |
builder | string/object | 指示 CLI 使用什么 builder 来编译项目(tsc、swc 或 webpack)。要自定义构建器的行为,您可以传递包含两个属性的对象:type(tsc、swc 或 webpack)和 options。 |
typeCheck | boolean | 如果为 true,为 SWC 驱动的项目启用类型检查(当 builder 为 swc 时)。默认值为 false。 |
全局生成选项
这些属性指定 nest generate 命令要使用的默认生成选项。
| 属性名称 | 属性值类型 | 描述 |
|---|---|---|
spec | boolean 或 object | 如果值为布尔值,true 值默认启用 spec 生成,false 值禁用它。在 CLI 命令行上传递的标志会覆盖此设置,项目特定的 generateOptions 设置也会覆盖(更多信息见下文)。如果值为对象,每个键代表一个原理图名称,布尔值确定是否为该特定原理图启用/禁用默认 spec 生成。 |
flat | boolean | 如果为 true,所有生成命令将生成扁平结构 |
以下示例使用布尔值指定默认情况下应为所有项目禁用 spec 文件生成:
{
"generateOptions": {
"spec": false
},
...
}
以下示例使用布尔值指定扁平文件生成应该是所有项目的默认值:
{
"generateOptions": {
"flat": true
},
...
}
在以下示例中,仅为 service 原理图禁用 spec 文件生成(例如,nest generate service...):
{
"generateOptions": {
"spec": {
"service": false
}
},
...
}
警告 当将 spec 指定为对象时,生成原理图的键当前不支持自动别名处理。这意味着指定键为例如 service: false 并尝试通过别名 s 生成服务,spec 仍将被生成。为了确保正常的原理图名称和别名都按预期工作,请指定正常的命令名称以及别名,如下所示。
{
"generateOptions": {
"spec": {
"service": false,
"s": false
}
},
...
}
项目特定生成选项
除了提供全局生成选项外,您还可以指定项目特定的生成选项。项目特定的生成选项遵循与全局生成选项完全相同的格式,但直接在每个项目上指定。
项目特定的生成选项覆盖全局生成选项。
{
"projects": {
"cats-project": {
"generateOptions": {
"spec": {
"service": false
}
},
...
}
},
...
}
警告 生成选项的优先级顺序如下。在 CLI 命令行上指定的选项优先于项目特定选项。项目特定选项覆盖全局选项。
指定编译器
不同默认编译器的原因是,对于较大的项目(例如,在 monorepo 中更典型),webpack 在构建时间和生成将所有项目组件捆绑在一起的单个文件方面可以具有显著优势。如果您希望生成单独的文件,请将 "webpack" 设置为 false,这将导致构建过程使用 tsc(或 swc)。
Webpack 选项
webpack 选项文件可以包含标准的 webpack 配置选项。例如,要告诉 webpack 捆绑 node_modules(默认情况下被排除),请将以下内容添加到 webpack.config.js:
module.exports = {
externals: [],
};
由于 webpack 配置文件是 JavaScript 文件,您甚至可以公开一个接受默认选项并返回修改对象的函数:
module.exports = function (options) {
return {
...options,
externals: [],
};
};
资产
TypeScript 编译自动将编译器输出(.js 和 .d.ts 文件)分发到指定的输出目录。分发非 TypeScript 文件(如 .graphql 文件、images、.html 文件和其他资产)也很方便。这允许您将 nest build(和任何初始编译步骤)视为轻量级开发构建步骤,您可能正在编辑非 TypeScript 文件并迭代编译和测试。
资产应位于 src 文件夹中,否则它们将不会被复制。
assets 键的值应该是指定要分发的文件的元素数组。元素可以是具有 glob 样式文件规范的简单字符串,例如:
"assets": ["**/*.graphql"],
"watchAssets": true,
为了更精细的控制,元素可以是具有以下键的对象:
"include":要分发的资产的glob样式文件规范"exclude":要从include列表中排除的资产的glob样式文件规范"outDir":指定应分发资产的路径(相对于根文件夹)的字符串。默认为为编译器输出配置的相同输出目录。"watchAssets":布尔值;如果为true,在监视模式下运行,监视指定的资产
例如:
"assets": [
{ "include": "**/*.graphql", "exclude": "**/omitted.graphql", "watchAssets": true },
]
警告 在顶级 compilerOptions 属性中设置 watchAssets 会覆盖 assets 属性中的任何 watchAssets 设置。
项目属性
此元素仅存在于 monorepo 模式结构中。您通常不应编辑这些属性,因为 Nest 使用它们来定位 monorepo 内的项目及其配置选项。