V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zuohuadong
V2EX  ›  Node.js

NestJS:我们一直在等待的精美的 Node.js 框架

  •  
  •   zuohuadong · 2018-03-21 18:38:21 +08:00 · 19965 次点击
    这是一个创建于 2446 天前的主题,其中的信息可能已经有所发展或是发生改变。

    NestJS 是一个精心制作的服务器端(后端)应用程序框架,以支持开发人员的生产力并让他们的生活更加快乐。

    那么,它不仅是一个框架,它还是进入领域驱动设计,事件采购,微服务架构等先进工程概念领域的推动者。 所有软件包都以简单轻量级的形式打包,以便您可以选择 - 无论您决定使用整个框架还是仅重新使用其组件。

    我是一个 PHP 编写的 Symfony 框架的粉丝。 在我的职业生涯中,我花了好几年的时间开发大型应用程序,它并没有让我失望。 它写得很好,作为一个客观的,具有良好文档的模块化 Web 框架,提供了良好的开发者体验。 与我描述 NestJS 完全一样。

    Node.js 和包管理器 NPM 提供了功能全面的服务器端环境,灵活性强,运行速度极快,对开发人员来说具有巨大的灵活性,从而将开发到生产的时间缩短到几小时,而不是几天。

    image.png

    然而,尽管 Node.js 的优点很多,但它并不能解决最常见的问题,在我看来,这是最大的问题,所有的 NodeJS 现代框架似乎都没有受到熏陶 - 架构的灵活性。

    有人可能会说 - 这不是决定项目架构的框架问题。 那么,我完全同意这一点,但是我们几乎在每个项目中都会看到一些众所周知的概念和模式。 在我看来,如果一个框架将开发人员推向了良好的架构决策,这是一件好事。

    NestJS 到底是什么?

    根据该项目的网站:

    NEST 是构建高效,可扩展的 NodeJS 服务器端应用程序的框架。

    这与 Node.js 语言相同,所以区别在哪里? 那么,重点是在细节:

    它使用现代 JavaScript,使用 Typescript (保留与纯 JavaScript 的兼容性)构建,并结合了 OOP,FP 和 FRP 的元素。

    就是这样。Nest 框架以一种非常活跃的方式鼓励开发人员尝试,学习和使用一些著名的软件工程范例。这不仅是介绍性的口号 - 在项目文档中我们找到了很多示例,指导和代码源,以便我们可以在几分钟内在项目中使用它们。 此外,所有这些新词汇的 NestJS 给我们参考它背后的知识。 所以如果你不知道一些模式 - 不用担心,你将会顺利地完成整个过程。

    一些特性

    NestJS 是一个完全用 TypeScript 编写的框架(它也支持 JS ),它很容易测试,并且带来了所有必要的东西,你总是但您不知道该选什么。

    • 依赖注入容器 - NestJS 带有自己的 DiC,这是一个在 JavaScript 世界中似乎被遗忘的实用工具,但我真的不能没有它。 有一些解决方案像 Inversify 或 Bottle,但 NestJS 有自己的解决方案。 它也支持工厂注入。
    • 模块化 - 在 NestJS 中,处于相同域边界内的应用程序的每个逻辑部分都是一个模块,它鼓励封装。
    • 可测试性 - 由于引入了 DiC 和 Modularisation,您可以根据服务构建应用程序, 使控制器的工作更容易进行测试。
    • 使用 TypeScript 中 - 类型很好。 你可以给一个变量分配类型,减少可能出现的错误。

    入门:构建一个简单的天气应用程序

    在这篇文章中,我们将使用 Nest 框架和 OpenWeatherMap API 编写一个简单的天气应用程序。 准备项目 首先,让我们确保你已经安装了支持的 Node.js 版本:

    node -v
    

    需要高于 6.11.0。 如果您没有安装 Node.js 或版本不正确,请安装或更新。 第二步是从 OpenWeatherMap 网站检索 API 密钥。 为了实现我们需要注册的功能,成功注册后,我们将能够从 API 密钥标签中检索我们的 API 密钥 。 image.png 准备就绪了。 让我们来设置这个项目。 为此,我将使用 Nest 的 TypeScript 初学者存储库(还有一种方法可以从头开始构建项目,但我很懒)。 它提供了良好的初学者体验,并拥有开始编写代码所需的一切。

      $ git clone https://github.com/nestjs/typescript-starter.git project
       $ cd weather-app /
    

    安装依赖关系并启动:

    $ npm i
    $ npm run start
    

    当安装了项目依赖关系并且应用程序成功启动后,您应该在控制台中看到以下输出,并在浏览器中指向 http://localhost:3000/ 的 url,应该会给您热情而欢迎的 Hello World ! 文本。

     > [email protected] start /Users/mat/Development/weather-app> node index.js
    
    [Nest] 31827 - 2018-1-13 11:39:32 [NestFactory] Starting Nest application...
    [Nest] 31827 - 2018-1-13 11:39:32 [InstanceLoader] ApplicationModule dependencies initialized +7ms
    [Nest] 31827 - 2018-1-13 11:39:32 [RoutesResolver] AppController {/}: +34ms
    [Nest] 31827 - 2018-1-13 11:39:32 [RouterExplorer] Mapped {/, GET} route +2ms
    [Nest] 31827 - 2018-1-13 11:39:32 [NestApplication] Nest application successfully started +1ms
    

    image.png

    安装 HTTP 客户端

    我们已经建立了项目,获取天气数据的 API 密钥和开发服务器,随时准备交付。 我们现在安装一个 HTTP 客户端,在这个区域我的个人偏好是 axios。 为什么选择 axios ? 这是一个基于 Promise 的客户端,它支持服务器端和客户端,并提供许多有用的功能,如:对 JSON 转换的自动响应和专用的工具 - moxios--使测试变得顺畅和轻松。

    $ npm i --save axios
    

    建立第一个服务

    现在我们可以开始构建我们的第一个服务 为了做到这一点,让我们在我们的 src/ 文件夹中创建一个名为 weather.service.t s 的文件:

    import { Component } from '@nestjs/common';
    import axios, { AxiosInstance } from 'axios';
    
    @Component()
    export class WeatherService {
        private client: AxiosInstance;
    
        constructor() {
            this.client = axios.create({
                baseURL: 'https://api.openweathermap.org/data/2.5/',
                params: {
                    APPID: 'CHANGE_ME'
                }
              });
        }
    
        async ofCity(city: string): object {
            const response = await this.client.get('weather', {
                params: { q: city }
            });
            return response.data;
        }
    }
    

    我们正在创建一个封装 HTTP 客户端的类,以实现实际的 API 调用。 有一点需要注意的是类装饰器 @Component(),多亏了它,框架才会知道这是我们想要在 DiC 中注册的组件。 它有一种方法,这是异步的 - 它会返回一个 Promise - 返回到控制器将由 Nest 处理。 HTTP 通信层 接下来我们需要建立的是控制器。 在 src /文件夹中创建一个名为 weather.controller.ts 的文件:

    import { Get, Controller } from '@nestjs/common';
    import { WeatherService } from './weather.service';
    
    @Controller('weather')
    export class WeatherController {
        constructor(private readonly weatherService: WeatherService) {}
    
            @Get()
            async root(): Promise< object > {
            const response = await this.weatherService.forCity('New York');
            return response;
      }
    

    装饰器 @Controller ('weather')告诉框架我们期望这个控制器在 / weather 路由上作出响应。 然后,我们在类构造函数中注入了我们的 WeatherService,并将其设置为名为 weatherService 的私有属性。 最后是一个称为 root 的异步操作,它返回一个 Promise,最终解析为一个对象。 它内部调用我们的 weatherService 并获得纽约的实际天气预报。 连接点 为了使我们的应用程序正常工作,我们需要做的最后一件事是将应用程序模块中的所有部分连接在一起:

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { WeatherController } from './weather.controller';
    import { WeatherService } from './weather.service';
    
    @Module({
      imports: [],
      controllers: [AppController, WeatherController],
      components: [WeatherService],
    })export class ApplicationModule {} 
    

    保存文件,重启你的开发服务器,当你在浏览器中导航到 url http://127.0.0.1:3000/weather 时,你会看到天气服务的响应。 上面的代码是为了显示我们如何快速地在 NestJS 中构建一个好的东西。然而, 我看到一些改进, 这还没有做, 因为我想保持简单:

    • 返回类型的接口。 我们可以充分利用 TypeScript 和强类型所有的东西
    • 错误处理。 当 promise 不是 resolve 时,我们的控制器很可能会中断
    • 测试套件。 我们还没有写任何测试
    • 我们要返回整个数据 blob。我们只能去掉我们关心的值

    概要

    我们从理论上讨论了 NestJS 并做了一个实际的例子。 欲了解更多信息,请参阅框架的官方文档,其中包含大量随时可用的指导和代码片段。 Node.js 是为了扩展和实现实时网络应用程序的高效开发而创建的,它非常好。 现在我们已经有了 NestJS 框架来解决架构问题。

    中文文档: https://docs.nestjs.cn 英文官方文档: https://docs.nestjs.com

    14 条回复    2019-09-10 05:46:52 +08:00
    gongbaodd
        1
    gongbaodd  
       2018-03-21 18:50:25 +08:00
    这么好的框架竟然没火起来太可惜了,本来想在公司内部推都推不起来。
    zhlssg
        2
    zhlssg  
       2018-03-21 18:55:21 +08:00 via iPhone
    支持一下
    lihongjie0209
        3
    lihongjie0209  
       2018-03-21 19:32:25 +08:00
    这些东西看起来越来越像 Java 了, 那为什么不直接用 Java 呢
    coderfox
        4
    coderfox  
       2018-03-21 20:17:13 +08:00 via Android
    刚看到 nest 的时候觉得很棒,后来想了想,既然用了这种框架,为什么不直接用 Java/.NET 呢?
    qiuyk
        5
    qiuyk  
       2018-03-26 11:48:53 +08:00
    今天试着玩了一下 感觉很爽 不过那为什么不直接用 Java 呢
    strugglexiang
        6
    strugglexiang  
       2018-03-26 14:30:28 +08:00
    不懂,帮顶
    breezeFP
        7
    breezeFP  
       2018-03-27 11:58:39 +08:00
    楼上说得对啊,为啥不用 java 呢,真的像 springMVC 的框架,可能对像我这样刚转过来的 javaer 比较友好吧
    chenbimo
        8
    chenbimo  
       2018-03-27 13:11:29 +08:00
    为什么不用 java 呢?
    zuohuadong
        9
    zuohuadong  
    OP
       2018-04-02 14:26:36 +08:00
    @gongbaodd 我们目前已经在用了
    zuohuadong
        10
    zuohuadong  
    OP
       2018-04-02 14:28:20 +08:00
    @lihongjie0209
    @coderfox
    @breezeFP
    @chenbimo

    我们目前感觉:
    1. 能用 node.js ,为什么要用 java 增加开发成本?
    2. java 在 ARM 单片机的表现差强人意。
    3. npm 真的很方便。
    4. 也是最重要一点:可以跟 angular 通用,做全栈。
    lihongjie0209
        11
    lihongjie0209  
       2018-04-02 14:55:58 +08:00
    1. 开发成本是相对的, 对于我来说编译安全比动态类型更省成本
    2. ARM 不懂
    3. npm 的依赖管理不如 java, 这个不细说
    4. 如果按照 web 分层开发, 前端用什么都和后端选型没关系.进一步说,前端已经绑死在 js 上了, 还能选出个花来.

    个人理解.
    wujohns
        12
    wujohns  
       2019-05-02 19:26:29 +08:00
    虽然设计理念很好,但是实际开发体验比 eggjs 差了很多,特别是 nestjs 中间件的设计,可以说是相当的反人类
    erickim
        13
    erickim  
       2019-08-06 15:57:57 +08:00
    typescript 强类型太像 java 了,在我实际项目使用过程中发现 typescript 的维护成本远高于 java。
    所谓的什么 DI 和 IOC 真的是 spring-mvc 的那一套,是蛮好用的,但 nestjs 从简介来看好像就是 jser 可以开心地开发 springboot + springcloud 了。
    mascotqoo
        14
    mascotqoo  
       2019-09-10 05:46:52 +08:00
    我也一直不懂,如果我用 nest.js ,为何我不用 java ?
    意思是出外行走,要有两把刷子:
    1、简单快速的一套方案 ;
    2、复杂麻烦的一套方案
    而且一定是越来越简单的越流行,之後若商业模式发展起来後,要加强大後端,到时候在导入 java 也不迟。

    而且到那个时候,多数人未必会选择 java,麻烦死了!我规划使用 python,既不失精准稳定,又不失「新」的主流语言。


    然而选择 java 或是.net ,又或是 php,根本无感,java 慢慢失去主流市场的态势,越来越明显,而何况同领域的竞争者是非常多,而且生态圈也很完整,在高速发展与变化万千的 web 领域中压宝 java,我觉得优势越来越低、风险也越来越大
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2611 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:32 · PVG 13:32 · LAX 21:32 · JFK 00:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.