Preface
As I've promised in the previous Typia Series Articles, I'll introduce you my new library nestia, which can make NestJS
much faster and easier.
With my new library nestia, you can boost up your NestJS
server performance dramatically, just by writing only one line per each
API function. Also, you can build SDK library, so you can help your
fellow client developers to be much convenient.
Let's see nestia, and imagine how much your NestJS
server would be powerful.
- Only one line required, with pure TypeScript type
- Runtime validator is 20,000x faster than class-validator
- JSON serialization is 200x faster than class-transformer
- SDK is similar with tRPC, but much advanced
Left is
NestJS
server code, and right is client code utilizing SDK.You can write client code much easily and safely.
Pure TypeScript Type
In NestJS
, you have to define DTO by utilizing those libraries:
class-validator
class-transformer
@nestjs/swagger
I hate those libraries, because they force developer to define
duplicated types like below. As long as you are using them following
formal guide of NestJS
, you never can avoid to duplicated type definitions in both TypeScript type and decorators.
Let's see how those libraries make DTO ugly:
export class BbsArticle {
@IsString()
@ApiProperty({
format: "uuid",
})
id!: string;
// DUPLICATED SCHEMA DEFINITION
// - duplicated function call + property type
// - have to specify `isArray` and `nullable` props by yourself
@IsArray()
@IsObject()
@ValidateNested()
@Type(() => AttachmentFile)
@ApiProperty({
type: () => AttachmentFile,
nullable: true,
isArray: true,
description: "List of attached files.",
})
files!: AttachmentFile[] | null;
@IsString()
@IsOptional()
@ApiProperty({
type: "string",
nullable: true,
minLength: 5,
maxLength: 100,
description: "Title of the article.",
})
title!: string | null;
@IsString()
@ApiProperty({
description: "Main content body of the article."
})
body!: string;
@IsString()
@ApiProperty({
format: "date-time",
description: "Creation time of article",
})
created_at!: string;
}
export class AttachmentFile {
@IsString()
@IsOptional()
@ApiProperty({
type: "string",
nullable: true,
maxLength: 255,
pattern: "^[a-zA-Z0-9-_]+$",
description: "File name.",
})
name!: string | null;
@IsString()
@IsOptional()
@ApiProperty({
type: "string",
nullable: true,
maxLength: 255,
pattern: "^[a-zA-Z0-9-_]+$",
description: "File extension.",
})
extension!: string | null;
@IsString()
@ApiProperty({
format: "url",
description: "URL of the file.",
})
url!: string;
}
In contrary, with nestia, you can define DTO with pure TypeScript type only. Thus, you don't need to be suffered from duplicated type definitions. Furthermore, even supports nestia interface typed DTO.
Let's see how nestia changes DTO so much easier and beautiful:
export interface IBbsArticle {
/**
* Primary Key.
*
* @format uuid
*/
id: string;
/**
* List of attached files.
*/
files: IAttachmentFile[] | null;
/**
* Title of the article.
*
* @minLength 5
* @maxLength 100
*/
title: string | null;
/**
* Main content body of the article.
*/
body: string;
/**
* Creation time of article.
*
* @format date-time
*/
created_at: string;
}
export interface IAttachmentFile {
/**
* File name.
*
* @pattern ^[a-z0-9]+$
* @maxLength 255
*/
name: string | null;
/**
* File extension.
*
* @pattern ^[a-z0-9]+$
* @maxLength 8
*/
extension: string | null;
/**
* URL of the file.
*
* @format uri
*/
url: string;
}
Superfast Validation
If you have seen my previous Typia Series Articles, reading above #TypeScript section, you may suspect that nestia is using typia.
Yes, nestia is utilizing typia, and it is the secret why nestia can use pure TypeScript type as DTO. Also, as nestia is using typia, it can provide superfast validation.
Do you remember? Validation speed of typia was maximum 20,000x faster than class-validator
what NestJS
is using. Such super-fast validation speed also can be applied to your NestJS
server, just by using nestia.
Now, change your class-validator
based DTO classes to pure TypeScript type, and utilize @TypedBody()
function like below. Then, your NestJS
server's validation speed (about request body data) would be 20,000x times faster.
It seems very easy and wonderful, isn't it?
import { TypedBody, TypedRoute } from "@nestia/core";
import { Controller } from "@nestjs/common";
import { IBbsArticle } from "./IBbsArticle";
@Controller("bbs/articles")
export class BbsArticlesController {
@TypedRoute.Post()
public async store(
// 20,000x faster validation
@TypedBody() input: IBbsArticle.IStore
): Promise<IBbsArticle> {
return {
...input,
id: "2b5e21d8-0e44-4482-bd3e-4540dee7f3d6",
created_at: "2023-04-23T12:04:54.168Z",
}
}
}
Measured on Intel i5-1135g7, Surface Pro 8
Superfast Serialization
nestia is using typia. Therefore, in the same reason with #Validation, JSON serialization speed also can be 200x faster than class-transformer
what NestJS
is using.
Just use @TypedRoute.${method}()
decorator on your API function. Then, your NestJS
server's JSON serialization speed (about response body data) would be 200x times faster.
If you're wondering how JSON serialization speed in the server side,
look at the server benchmark graph of below. Just by adapting nestia and utilizing its @TypedRoute.${method}()
function, your NestJS
server can accept maximum 30x more requests.
Most operations in NodeJS server are asynchronously executed in background thread, what are called "event based non-blocking I/O model". However, JSON serialization is a synchronous operation running on the main thread. Therefore, if the JSON serialization speed is slow, it makes the entire server program slow.
It seems very powerful, isn't it?
import { TypedRoute } from "@nestia/core";
import { Controller } from "@nestjs/common";
import { IBbsArticle } from "./IBbsArticle";
@Controller("bbs/articles")
export class BbsArticlesController {
// 200x faster JSON serialization
@TypedRoute.Get("random")
public async random(): Promise<IBbsArticle> {
return {
id: "2b5e21d8-0e44-4482-bd3e-4540dee7f3d6",
title: "Hello nestia users",
body: "Just use `TypedRoute.Get()` function like this",
created_at: "2023-04-23T12:04:54.168Z",
files: [],
};
}
}
Measured on Intel i5-1135g7, Surface Pro 8
Measured on Intel i5-1135g7, Surface Pro 8
SDK generation
Do you know tRPC? If you develop your NodeJS backend server with it, you don't need to deliver any Swagger Documents to your fellow client developers. You just can send an interaction library for them.
By the way, tRPC is good for building toy projects, but not suitable for developing enterprise level backend server. In such reason, many NestJS
lovers had requested tRPC team to support NestJS
. But considering principle of tRPC, it never can support NestJS
.
Instead, I support SDK generation for NestJS
through my new library nestia. Just run npx nestia sdk
command, then nestia will analyze your NestJS
backend server code, and generates optimal SDK library in the compilation level.
Look at below gif image, and imagine how SDK would be helpful for your fellow client developers. Your fellow client developers will just import the SDK library, and call API functions with auto completion.
If they take any mistake, compiler will detect it, therefore you don't need to be suffered from runtime error by mistakes.
Left is
NestJS
server code, and right is client code utilizing SDK.You can write client code much easily and safely.
No comments:
Post a Comment