发布V9
今天,我很高兴宣布 NestJS v9 的正式发布。
这是整个平台的主要版本,包括框架,改进 @nestjs/swagger
软件包,CLI 以及对文档的更新。
Note
如果您不熟悉Nestjs,它是一个打字稿Node.js框架,可帮助您构建企业级高效且可扩展的Node.js应用程序。
Cat in Kyiv. Photo by Valdemar Kostenko
让我们进去!
版本 9 中有什么新功能?¶
该版本带来了许多出色的功能和期待已久的改进。 这里有太多的地方要列出,但是让我们高度看一些最令人兴奋的东西。
REPL (阅读评估打印循环)¶
REPL 是一个简单的交互式环境,可将单个用户输入,执行它们并将结果返回给用户。 REPL 功能使您可以直接从终端检查提供器(和控制器)上的依赖关系图并调用方法。
Nest 的 Repl 功能于 2022 年 5 月首次宣布,此后收到了大量改进和更新。
要以模式运行您的 Nestjs 应用程序,请创建一个新的repl.ts
文件(与现有的main.ts
文件一起),并在内部添加以下代码:
现在,在您的终端中,使用以下命令启动重复:
Hint
内置的Nestjs替补带有一些本机功能,这些功能在您启动重置时全球可用。您可以调用help()
列出它们。
启动并运行后,您应该在控制台中看到以下消息:
现在,您可以开始与依赖关系图进行交互。 例如,您可以检索 AppService(我们在此处以启动器项目为例)并调用 getHello()方法:
您可以从终端内执行任何 JavaScript 代码,例如,将 AppController 的实例分配给本地变量,并使用等待调用异步方法:
要显示给定提供商或控制器上可用的所有公共方法,请使用 Method()函数,如下:
要将所有注册模块与其控制器和提供商一起打印为列表,请使用debug()
。
Quick demo:
REPL example
Configurable module builder¶
If you have have ever manually created dynamic modules that are highly configurable that expose async methods, registerAsync, forRootAsync, etc., you know it can be quite complicated and require quite a bit of boilerplate code.
We aim to simplify this in Nest v9, which will provide a ConfigurableModuleBuilder class that facilitates this process and lets you construct a module "blueprint" - in just a few lines of code.
For demonstration purposes, let's create a configurable HttpClientModule using the new ConfigurableModuleBuilder. Before we start, let's make sure we declare a dedicated interface that represents what options our HttpClientModule takes in.
You also have the ability to inject a configuration object using the @Inject(MODULE_OPTIONS_TOKEN) construction. Read more on this feature in the documentation.
Durable providers¶
Request-scoped providers may sometimes lead to increased latency since having at least 1 request-scoped provider (injected into the controller instance, or deeper - injected into one of its providers) makes the controller request-scoped as well. That means, it must be recreated (instantiated) per each individual request (and garbage collected afterwards).
HINT For instance, for 30k requests in parallel, there will be 30k ephemeral instances of the controller (and its request-scoped providers).
Having a common provider that most providers depend on (e.g., database connection), automatically converts all those providers to request-scoped providers as well. This can pose a challenge in multi-tenant applications, especially for those that have a central request-scoped "data source" provider that grabs headers/token from the request object and based on their values, retrieves the corresponding database connection/schema (specific to that tenant).
For instance, let's say you have an application alternately used by 10 different customers. Each customer has its own dedicated data source, and you want to make sure customer A will never be able to reach customer's B database. One way to achieve this could be to declare a request-scoped "data source" provider that - based on the request object - determines what's the "current customer" and retrieves its corresponding database. But, a major downside to this approach is that since most likely a large chunk of your application' components rely on the "data source" provider, they will implicitly become "request-scoped", and therefore you will undoubtedly see an impact in your apps performance.
But what if we had a better solution?
Since we only have 10 customers, couldn't we have 10 individual DI sub-trees per customer (instead of recreating each tree per request)?
If your providers don't rely on any property that's truly unique for each consecutive request (e.g., request UUID) but instead there are some specific attributes that let us aggregate them, then we have no reason to recreate the DI sub-tree on every incoming request.
This is exactly where durable providers come in handy!
Before we start flagging providers as durable, we must first register a strategy that:
instructs Nest what those "common request attributes" are provides logic that groups requests, and associates them with their corresponding DI sub-trees.
Hint Similar to the request scope, durability bubbles up the injection chain. That means if A depends on B which is flagged as durable, A implicitly becomes durable too (unless durable is explicitly set to false for A provider).
Warning Note this strategy is not ideal for applications operating with a large number of tenants.
With this strategy in place, you can register it somewhere in your code (as it applies globally anyway), so for example, we could place it in the main.ts file:
As long as the registration occurs before any request hits your application, everything will work as intended.
Lastly, to turn a regular provider into a durable provider, simply set the durable flag to true:
Redis transporter¶
In v9, the Redis transport strategy will no longer use redis package under the hood but instead was migrated to leverage ioredis.
Upgraded dependencies¶
Nest v9 brings support for Fastify v4 and drops support for Node.js v10. Make sure to use at least the latest LTS version!
Migration from Nest v8¶
In order to migrate your existing project, follow the guidelines that are available here. Also, make sure to get rid of all deprecation messages that may appear in your console.
Enjoy v9!¶
We're excited to see how you use the latest version of NestJS.
Make sure to follow Nest on Twitter @nestframework to stay up to date with all the latest announcements!