Originally posted on https://samueleresca.com
Every platform has its own philosophy: a set of principles and guidelines. Node.js is strongly influenced by the Unix philosophy . Particularly in two of its working principles, which are as follows:
“Small is beautiful.”
“Make each program do one thing well.”
The simplicity of Node.js core and its modularity gives a lot of advantages: first of all, reusability. Secondly, modules become easier to understand and use simpler to test and maintain. The modularity may become a problem when you want to follow an specific architecture or patterns . That kind of problem raise when you are involved on large-scale projects with distributed teams . Well, I have found the solution in Nest , which provide out-of-box a server side architecture with Node and Typescript.
This is the definition you can find on nestjs.com :
A progressive Node.js framework for building efficient and scalable server-side applications. Let's show the whole world Node.js potential together!
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses TypeScript and combines elements of OOP , Functional programming and Reactive Programming . Nest stands on top of express, and it implements the MVC pattern. Speaking IMHO, the point of strength of Nest is its similarity to a lot of frameworks from other languages. ASP.NET, Django and Spring developers will find the strongly typed approach of Typescript and the architecture of Nest very familiar. Like others MVC frameworks, characteristic such as highly testability, scalability, loosely coupling are the core part of Nest.
Nest uses decorators to define recognise components inside our code. This kind of approach is also called meta-programming , and as a ASP.NET developer, I have found it very similar to the concepts already implemented in ASP.NET (e.g.: Action filters). Let's take an overview of these core part of Nest:
@Controller([prefix]): indicates a controller. The controllers layer is responsible for handling incoming requests and returning a response to the client;
@Component(): everything is a component. Repositories, Services, Helper must be threat as components. Components can be injected into other components through the constructor;
@Modules(): it simply groups a set of components. Furthermore, they also are responsible of the dependency injection of contained components, helpers and controllers (They might be compared to the C# class libraries;
@Middleware(): middlewares stand between the our incoming request and the server. It works through a pipeline flow, and they can be useful for authentication, logging, redirects;
Let's see an concrete example of Nest.js architecture. This example would be a way to understand the basic concepts behind the Nest.js architecture. You can find the repository @ the following link: https://github.com/samueleresca/Blog.NestGettingStarted .
In addition, we will use it as term of comparison in the next chapter, in order to understand the similarity with others conventional frameworks. It simply exposes some rest APIs to store informations on a Sql server database. Let's take an overview of the project key parts...
Infrastructure/DependencyInstaller.ts contains the definitions of all the components injected through dependency injection:
Models/Label.ts entity generates a new table on our data source, it will be used to store informations about some labels. The application uses TypeOrm as ORM framework. Here is the definition of the label entity:
Services/ILabelsService.ts defines the interface which wraps the TypeOrm repository. It provides useful methods in order to perfom CRUD operation on our database through TypeOrm.
Controllers/LabelsController.tsis entry point of our HTTP requests. It defines some DTO
models in order to expose any sort of APIs to allow to modify data:
As said before, Nest.js architecture is closer to a lot of MVC frameworks. That can be an advantage for all the people who comes from a "classic" MVC framework. Let's compare the
LabelsController.ts with the same controller implemented on ASP.NET Core. Here is a similar implementation using ASP.NET Core:
As you can see, the C# controller brings the same key concept of the Typescript controller: both use an dependency injection approach, and both uses decorators in order to provide and enhance the controller actions. Obviously, also two ORMs can be similar. Let's take two implementations made by using TypeOrm and Entity Framework ; This is the comparison between
Also in that case, decorators represent a key part of out implementation. They describe some important informations about the structure of the data source. Finally both
ILabelsServices.ts , and
ILabelsService.cs wrap data and provide it on higher level of abstraction. This is the implementation of the
In both cases,
LabelsServices.ts , and
LabelsService.cs , are middle-layer between data and controller. They are used to manipulate data in order to expose them through the controller.
In conclusion, Nest.js groups the best ideas which come from the classic MVC pattern and it applies them to the Node.js world. It provides a good infrastructure in order to build server side architecture with Node and Typescript. It also might be familiar to all the developer who comes from others popular frameworks and languages, such as ASP.NET, Spring and Django. Finally, it may be used as "entry point" to the Node.js world by everyone who comes from other frameworks.
Cover credits: La Fée Electricité - Raoul Dufy