掘金 后端 ( ) • 2024-05-14 18:45

MVC

MVC指的是模型-视图-控制器(Model-View-Controller) 在MVC架构下,一般指的是在服务端渲染完页面,然后将页面作为响应体响应到客户端(浏览器),类似于传统的服务端渲染的模式

默认情况下,Nest 在底层使用 Express 库。因此,在 Express 中使用 MVC(模型-视图-控制器) 模式的每种技术也适用于 Nest

首先,使用 CLI 工具构建一个简单的 Nest 应用:

$ npm i -g @nestjs/cli
$ nest new project

为了创建一个 MVC 应用,还需要一个 模板引擎 来渲染 HTML 视图:

$ npm install --save hbs

这里使用了 hbs (Handlebars) 引擎,但可以使用任何符合要求的引擎。安装过程完成后,需要使用以下代码配置 express 实例:

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(
    AppModule,
  );

  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  app.setViewEngine('hbs');

  await app.listen(3000);
}
bootstrap();

这里告诉 Express,public 目录将用于存储静态资源,views 将包含模板,而 hbs 模板引擎应该用于渲染 HTML 输出

模板渲染

现在,创建一个 views 目录和 index.hbs 模板,模板中将打印从控制器传递的 message:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>App</title>
  </head>
  <body>
    {{ message }}
  </body>
</html>

打开 app.controller 文件并将root()方法替换为以下代码:

import { Get, Controller, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  root() {
    return { message: 'Hello world!' };
  }
}

在这段代码中,指定了要在 @Render() 装饰器中使用的模板,并将路由处理程序方法的返回值传递给模板进行渲染。请注意,返回值是一个具有属性 message 的对象,与在模板中创建的 message 占位符匹配

在应用运行时,打开浏览器并导航至 http://localhost:3000 。就可以看到 Hello world! 消息

动态模板渲染

如果应用逻辑必须动态决定渲染哪个模板,那么应该使用 @Res() 装饰器,并在路由处理程序中提供视图名称,而不是在 @Render() 装饰器中:

提示:当 Nest 检测到 @Res() 装饰器时,它会注入特定于库的 response 对象。可以使用这个对象来动态渲染模板

import { Get, Controller, Res, Render } from '@nestjs/common';
import { Response } from 'express';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private appService: AppService) {}

  @Get()
  root(@Res() res: Response) {
    return res.render(
      this.appService.getViewName(),
      { message: 'Hello world!' },
    );
  }
}

独立应用

有几种安装 Nest 应用的方法,可以创建一个 Web 应用、一个微服务或只是一个简单的 Nest 独立应用(没有任何网络监听器)。Nest 独立应用是 Nest IoC 容器的封装器,其中包含所有实例化的类。可以直接使用独立应用对象从任何导入的模块中获取对任何现有实例的引用。因此,可以在任何地方利用 Nest 框架,包括脚本化的 CRON 作业等。甚至可以在其之上构建 CLI

入门

要创建 Nest 独立应用,请使用以下结构:

async function bootstrap() {
  const app = await NestFactory.createApplicationContext(AppModule);
  // application logic...
}
bootstrap();

独立应用对象允许获取对在 Nest 应用中注册的任何实例的引用。假设在 TasksModule 中有一个 TasksService。此类提供了一组希望从 CRON 工作中调用的方法

const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.get(TasksService);

要访问 TasksService 实例,使用 get() 方法。get() 方法的作用类似于在每个注册模块中搜索实例的查询。或者,对于严格的上下文检查,传递一个带有strict: true属性的选项对象。启用此选项后,必须浏览特定模块才能从所选上下文中获取特定实例

const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.select(TasksModule).get(TasksService, { strict: true });

以下是可用于从独立应用对象检索实例引用的方法的摘要

get() 检索应用上下文中可用的控制器或提供程序(包括守卫、过滤器等)的实例 select() 浏览模块的图形以提取所选模块的特定实例(如上所述与严格模式一起使用)

提示:在非严格模式下,默认选择根模块。要选择任何其他模块,需要逐步手动导航模块图

如果希望节点应用在脚本完成后关闭(例如,对于运行 CRON 工作的脚本),将 await app.close() 添加到 bootstrap 函数的末尾:

async function bootstrap() {
  const app = await NestFactory.createApplicationContext(AppModule);
  // application logic...
  await app.close();
}
bootstrap();

脚手架

概述

Nest CLI是一个命令行接口工具,可初始化、开发和维护 Nest 应用。它以多种方式提供帮助,包括搭建项目、在开发模式下提供服务,以及构建和打包用于生产分发的应用。它体现了最佳实践架构模式,以鼓励结构良好的应用

安装

注意:在这里使用了 npm 安装包,包括 Nest CLI。可以自行决定使用其他包管理器。使用 npm,可以使用多个选项来管理操作系统命令行如何解析 nest CLI 二进制文件的位置。在这里描述了使用-g选项全局安装 nest 二进制文件。请注意,全局安装任何 npm 软件包都会将确保其运行正确版本的责任留给用户。这意味着,如果有不同的项目,每个项目都将运行相同版本的 CLI。一个合理的替代方案是使用内置于 npm cli 中的 npx 程序(或其他包管理器的类似功能),以确保运行 Nest CLI 的托管版本

使用 npm install -g 命令全局安装 CLI

$ npm install -g @nestjs/cli

提示:或者可以使用此命令 npx @nestjs/cli@latest,而无需全局安装 cli

基本工作流程

安装后,可以通过 nest 可执行文件直接从操作系统命令行调用 CLI 命令。通过输入以下内容查看可用的 nest 命令:

$ nest --help

使用以下构造获取有关单个命令的帮助。替换任何命令,如 new、add 等,在下面的示例中看到 generate,以获得有关该命令的详细帮助:

$ nest generate --help

要在开发模式下创建、构建和运行新的基本 Nest 项目,请转到应作为新项目父级的文件夹,然后运行以下命令:

$ nest new my-nest-project
$ cd my-nest-project
$ npm run start:dev

在浏览器中,打开 http://localhost:3000 以查看正在运行的新应用。当更改任何源文件时,该应用将自动重新编译和重新加载

提示:建议使用 SWC 构建器 来实现更快的构建(性能比默认 TypeScript 编译器高 10 倍)

项目结构

当运行 nest new 时,Nest 通过创建一个新文件夹并填充一组初始文件来生成样板应用结构。可以继续使用此默认结构,添加新组件。将 nest new 生成的项目结构称为标准模式。Nest 还支持一种用于管理多个项目和库的替代结构,称为 monorepo 模式

除了关于构建过程如何工作的一些具体考虑因素(本质上,monorepo 模式简化了有时可能因 monorepo 样式项目结构而产生的构建复杂性)和内置 library 支持、其余 Nest 功能以及本文档, 同样适用于标准和单一存储库模式项目结构。事实上,可以在任何时候轻松地从标准模式切换到 monorepo 模式

可以使用任一模式来管理多个项目。以下是差异的总结:

特性 标准模式 单体模式 多个项目 独立的文件系统结构 单文件系统结构 node_modules & package.json 单独的实例 跨 monorepo 共享 默认编译器 tsc webpack 编译器设置 单独指定 每个项目可以覆盖的 Monorepo 默认值 配置文件,如 .eslintrc.js、.prettierrc 等。 单独指定 跨 monorepo 共享 nest build 和 nest start 命令 Target 自动默认为上下文中的(唯一)项目 目标默认为 monorepo 中的默认项目 库 手动管理,通常通过 npm 打包 内置支持,包括路径管理和打包

CLI 命令语法

所有 nest 命令都遵循相同的格式:

nest commandOrAlias requiredArg [optionalArg] [options]

例如:

$ nest new my-nest-project --dry-run

这里,newcommandOrAlias。new 命令的别名是 nmy-nest-project 是必需的参数。如果命令行上未提供 requiredArg,nest 将提示输入它。此外,--dry-run 具有等效的简写形式 -d。考虑到这一点,以下命令等同于上面的命令:

$ nest n my-nest-project -d

大多数命令和一些选项都有别名。尝试运行 nest new --help 以查看这些选项和别名,并确认你对上述构造的理解

命令概述

对以下任何命令运行 nest <command> --help 以查看特定于命令的选项

命令 别名 描述 new n 搭建一个新的标准模式应用,其中包含运行所需的所有样板文件 generate g 根据原理图生成和/或修改文件 build 将应用或工作区编译到输出文件夹中 start 编译并运行应用(或工作区中的默认项目) add 导入已打包为嵌套库的库,运行其安装原理图 info i 显示有关已安装的嵌套包的信息和其他有用的系统信息

要求

Nest CLI 需要使用 国际化支持(ICU) 构建的 Node.js 二进制文件,例如来自 Node.js 项目页面 的官方二进制文件。如果遇到与 ICU 相关的错误,请检查二进制文件是否满足此要求

node -p process.versions.icu

如果该命令打印 undefined,则 Node.js 二进制文件不支持国际化