Nest 有两种组织代码的模式:
- 标准模式:适用于构建具有自己的依赖项和设置的单个以项目为中心的应用程序,并且不需要针对共享模块进行优化,也不需要优化复杂的构建。这是默认模式。
- monorepo 模式:此模式将代码工件视为轻量级 monorepo 的一部分,可能更适合开发人员团队和/或多项目环境。它自动化了构建过程的部分内容,以便于创建和编写模块化组件,促进代码重用,使集成测试更容易,使共享项目范围的工件(如
eslint
规则和其他配置策略)更容易,并且比 github 子模块等替代方案更易于使用。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
.eslintrc.js
我们可以将其转换为 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
.eslintrc.js
generate app
原理图已重新组织代码 - 将每个 application 项目移至 apps
文件夹下,并在每个项目的根文件夹中添加特定于项目的 tsconfig.app.json
文件。我们原来的 my-project
应用程序已成为 monorepo 的 默认项目,现在与刚刚添加的 my-app
同级,位于 apps
文件夹下。我们将在下面介绍默认项目。
将标准模式结构转换为 monorepo 仅适用于遵循规范 Nest 项目结构的项目。具体而言,在转换过程中,原理图会尝试将 src
和 test
文件夹重新定位到根目录中 apps
文件夹下的项目文件夹中。如果项目不使用此结构,则转换将失败或产生不可靠的结果。
工作区项目
monorepo 使用工作区的概念来管理其成员实体。工作区由 项目 组成。项目可以是:
- 应用程序:完整的 Nest 应用程序,包括用于引导应用程序的
main.ts
文件。除了编译和构建注意事项外,工作区内的应用程序类型项目在功能上与 标准模式 结构内的应用程序相同。 - 库:库是一种打包通用功能集(模块、提供程序、控制器等)的方式,可用于其他项目。库不能单独运行,也没有
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
和.eslintrc.js
。相反,使用 monorepo 范围的依赖项和配置文件。
但是,原理图会在项目的根文件夹中生成项目特定的tsconfig.app.json
文件。此配置文件会自动设置适当的构建选项,包括正确设置编译输出文件夹。该文件扩展了顶级(monorepo)tsconfig.json
文件,因此您可以在 monorepo 范围内管理全局设置,但如果需要在项目级别覆盖它们。
库
如前所述,库类型项目或简称库
是 Nest 组件的包,需要将其组合成应用程序才能运行。您可以使用 nest generate library
生成库类型项目。决定库中的内容是一项架构设计决策。我们将在 libraries 一章中深入讨论库。
CLI 属性
Nest 将组织、构建和部署标准和 monorepo 结构化项目所需的元数据保存在 nest-cli.json
文件中。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 资源。(有关要监视的资产的更细粒度控制,请参阅下面的 Assets 部分)。 |
manualRestart | boolean | 如果为 true ,则启用快捷方式 rs 来手动重启服务器。默认值为 false 。 |
builder | string/object | 指示 CLI 使用哪个 builder 来编译项目(tsc 、swc 或 webpack )。要自定义 builder 的行为,您可以传递一个包含两个属性的对象:type (tsc 、swc 或 webpack )和 options 。 |
typeCheck | boolean | 如果为 true ,则启用 SWC 驱动项目的类型检查(当 builder 为 swc 时)。默认值为 false 。 |
全局生成选项
这些属性指定 nest generate
命令要使用的默认生成选项。
属性名称 | 属性值类型 | 说明 |
---|---|---|
spec | boolean or 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
生成服务,仍会生成规范。为了确保正常原理图名称和别名都能按预期工作,请同时指定正常命令名称和别名,如下所示。
{
"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-mode 结构。您通常不应编辑这些属性,因为 Nest 会使用它们来定位 monorepo 中的项目及其配置选项。