NestJS 是用于构建服务器端应用程序的最佳 Node 框架之一。在本教程中,我们将探索如何构建一个简单的 NestJS 电子商务应用程序,并在此过程中展示 Nest 的许多主要功能。我们将介绍:
开始使用我们的 NestJS 电子商务应用程序
创建 NestJS 电子商务商店产品功能
创建用户管理功能
创建用户认证和授权
为我们的 NestJS 电子商务应用程序创建商店购物车功能
默认情况下,NestJS在后台使用Express,尽管您可以选择使用Fastify。Nest 提供了坚实的应用程序架构,而 Express 和 Fastify 是强大的 HTTP 服务器框架,具有无数的应用程序开发功能。
拥有健壮的架构使您能够构建高度可扩展、可测试、松散耦合且易于维护的应用程序。使用 Nest 可以让您的 Node.js 后端更上一层楼。
Nest 深受Angular的启发,并借鉴了它的许多概念。如果你已经在使用 Angular,Nest 可能是完美的搭配。
要学习本教程,您至少需要 Node、MongoDB、TypeScript 和 Nest 的基本知识和经验。确保您的机器上安装了Node和MongoDB。
让我们花点时间回顾一下 Nest 的主要功能:模块、控制器和服务。
模块是组织和构建 Nest 应用程序的主要策略。必须至少有一个根模块才能创建应用程序。每个模块都可以包含控制器和服务,甚至是其他模块。
Nest 使用依赖注入模式来连接模块及其依赖项。为了使类可注入,Nest 使用了@Injectable装饰器。然后,为了在模块或控制器中提供类,它使用基于构造函数的依赖注入。
控制器处理传入的 HTTP 请求、验证参数并将响应返回给客户端。控制器应该保持干净和简单,这是下一个 Nest 功能发挥作用的地方。
服务包含 Nest 项目的大部分业务逻辑和应用程序功能。任何复杂的逻辑都应该通过服务提供。事实上,服务属于一种称为提供者的主要类别。
超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →
提供者只是一个作为依赖注入的类。可能使用的其他类型的提供程序包括存储库、工厂、助手等类。
准备好后,让我们初始化一个新的 Nest 项目。首先,我们将安装 Nest CLI。然后,我们将创建一个新项目:
npm install -g @nestjs/cli 嵌套新的nestjs-电子商务
安装完成后,导航到项目并启动它:
cd nestjs-电子商务 npm 运行开始:开发
然后,您可以通过访问http://localhost:3000/在浏览器中启动该应用程序。您应该会看到一个不错的“Hello World!” 信息。
在您进行任何更改后,该应用程序将自动重新加载。如果要手动重新启动应用程序,请改用npm run start命令。
现在我们准备开始创建商店功能。
在本节中,我们将专注于产品管理。商店产品功能将允许我们检索商店产品、添加新产品以及编辑或删除它们。
让我们从创建所需的资源开始。要创建它们,请运行以下命令:
巢g模块产品 巢g服务产品--no-spec 巢g控制器产品--no-spec
第一个命令生成一个产品模块并将其放在自己的同名目录中。
接下来的两个命令生成服务和控制器文件,并在product模块中自动导入它们。该--no-spec参数告诉 Nest 我们不想生成额外的测试文件。
运行上述命令后,我们将获得一个product包含以下文件的新目录:product.module.ts、product.service.ts和product.controller.ts.
不要错过来自 LogRocket 的精选时事通讯The Replay
使用 React 的 useEffect优化应用程序的性能
在多个 Node 版本之间切换
了解如何使用 AnimXYZ 为您的 React 应用程序制作动画
探索 Tauri,一个用于构建二进制文件的新框架
比较NestJS 与 Express.js
发现TypeScript 领域中使用的流行 ORM
现在我们有了 NestJS 电子商务商店产品功能的基本结构。在我们继续之前,我们需要设置我们的数据库。
由于我们使用 MongoDB 作为数据库,我们需要安装mongoose和@nestjs/mongoose打包。
npm install --save @nestjs/mongoose mongoose
安装完成后,打开app.module.ts并将其内容替换为以下内容:
从'@nestjs/common'导入{模块}; 从'@nestjs/mongoose'导入 { MongooseModule };// 1.1 导入猫鼬模块 从'./app.controller'导入{AppController}; 从'./app.service'导入{AppService}; 从'./product/product.module'导入{ ProductModule };// 2.1 导入产品模块 @模块({ 进口:[ MongooseModule.forRoot('mongodb://localhost/store'), // 1.2 设置数据库 ProductModule, // 2.2 添加产品模块 ], 控制器:[AppController], 提供者:[AppService], }) 导出类 AppModule {}
这是我们在上面的代码中所做的。跟随我的编号笔记:
首先,我们导入MongooseModule(1.1)并用它来建立一个新的store数据库(1.2)
其次,我们导入ProductModule(2.1) 并将其添加到imports数组 (2.2)
我们的下一步是为我们的产品模型创建一个数据库模式。
在product目录中,创建一个新schemas目录。product.schema.ts在新目录中放置一个文件,内容如下:
从“@nestjs/mongoose”导入 { Prop、Schema、SchemaFactory }; 从“猫鼬”导入{文档}; 导出类型 ProductDocument = 产品和文档; @Schema() 出口类产品{ @支柱() 名称:字符串; @支柱() 描述:字符串; @支柱() 价格:数量; @支柱() 类别:字符串; } 出口 const ProductSchema = SchemaFactory.createForClass(Product);
上面的代码为我们的产品创建了一个带有name、description、price和category属性的模式。
现在product.module.ts按以下方式编辑:
从'@nestjs/common'导入{模块}; 从'./product.controller'导入{ProductController}; 从'./product.service'导入{ ProductService }; 从'@nestjs/mongoose'导入 { MongooseModule };// 1. 导入猫鼬模块 从'./schemas/product.schema'导入{ ProductSchema };// 2. 导入产品架构 @模块({ 进口:[ MongooseModule.forFeature([{ name: 'Product', schema: ProductSchema }]) // 3. 设置 mongoose 模块以使用产品模式 ], 控制器:[ProductController], 提供者:[产品服务] }) 导出类 ProductModule {}
从我的编号注释中可以看出,在上面的代码中,我们导入了MongooseModule(1) 和ProductModule(2),然后将其设置ProductSchema为用于我们的产品模型 (3)。
除了产品架构之外,我们还需要两个用于 NestJS 电子商务应用程序的数据传输对象 (DTO) 文件。DTO 文件定义将从表单提交、搜索查询等接收的数据。
我们需要一个 DTO 用于产品创建,另一个用于产品过滤。现在让我们创建它们。
在product目录中,创建一个新dtos目录。create-product.dto.ts在这个新目录中放置一个文件,内容如下:
导出类 CreateProductDTO { 名称:字符串; 描述:字符串; 价格:数量; 类别:字符串; }
上面的 DTO 定义了一个产品对象,它具有创建新产品所需的属性。
然后,在同一目录中,创建一个filter-product.dto.ts包含以下内容的文件:
导出类 FilterProductDTO { 搜索:字符串; 类别:字符串; }
第二个 DTO 定义了一个过滤器对象,我们将使用它来按搜索查询、类别或两者过滤商店产品。
本节的所有准备工作都已完成。现在让我们为产品管理创建实际代码。
打开product.service.ts文件并将其内容替换为以下内容:
从'@nestjs/common'导入{可注射}; 从“猫鼬”导入{模型}; 从“@nestjs/mongoose”导入 { InjectModel }; 从'./schemas/product.schema'导入{产品,产品文档}; 从'./dtos/create-product.dto'导入{ CreateProductDTO }; 从'./dtos/filter-product.dto'导入{FilterProductDTO}; @Injectable() 出口类产品服务 { 构造函数(@InjectModel('Product') 私有只读 productModel: Model) { } 异步 getFilteredProducts(filterProductDTO: FilterProductDTO): Promise { 常量 { 类别,搜索 } = filterProductDTO; 让产品 = 等待 this.getAllProducts(); 如果(搜索){ 产品 = products.filter(产品 => product.name.includes(搜索) || product.description.includes(搜索) ); } 如果(类别){ products = products.filter(product => product.category === category) } 退货; } 异步 getAllProducts(): Promise { 常量产品 = 等待 this.productModel.find().exec(); 退货; } 异步 getProduct(id: string): Promise { 常量产品 = 等待 this.productModel.findById(id).exec(); 退货; } 异步 addProduct(createProductDTO: CreateProductDTO): Promise { const newProduct = await this.productModel.create(createProductDTO); 返回 newProduct.save(); } async updateProduct(id: string, createProductDTO: CreateProductDTO): Promise { const updatedProduct = 等待 this.productModel .findByIdAndUpdate(id, createProductDTO,