NestJS is a server-side (backend) application framework beautifully crafted to support developers productivity and make their lives happier.
Well, it’s not only a framework, it’s an enabler of entering the world of advanced engineering concepts such as Domain Driven Design, Event Sourcing, Microservices architecture. All packaged in a simple and lightweight form so that the choice is yours – whether you decide to use the whole framework or just reuse its components.
I’m a huge fan of a PHP-written Symfony framework. I spent a good few years in my career developing large scale apps and it didn’t let me down any single time. It’s well written, having quality as an objective, modular web framework with a good documentation, delivering nice developer experience. Exactly the same way I’d describe Nest.
Node.js, along with the package manager NPM delivers fully functional server-side environment that is flexible, runs blazingly fast and huge flexibility to a developer, allowing reducing time from development to production to hours, not days.
However, with all its greatness, Node.js doesn’t solve the most common, and in my opinion the biggest problem, which all the modern frameworks seem to be not affected with – an architectural flexibility.
Someone could say – it’s not a matter of a framework to dictate project’s architecture. Well, I fully agree with that, but there are some well-known concepts and patterns that we see in almost every project. And in my opinion it’s a great thing if a framework pushes developers to good architectural decisions.
What exactly is NestJS?
According to the project’s website:
NEST IS A FRAMEWORK FOR BUILDING EFFICIENT, SCALABLE NODE.JS SERVER-SIDE APPLICATIONS.
The same sentence can be true to Node.js, so where is the difference? Well, devil is in the details:
IT USES MODERN JAVASCRIPT, IS BUILT WITH TYPESCRIPT (PRESERVES COMPATIBILITY WITH PURE JAVASCRIPT) AND COMBINES ELEMENTS OF OOP, FP, AND FRP.
That’s the thing. Nest framework in a very active way encourages developers to try, learn and use some well-known software engineering paradigms. And that’s not only the introductory slogan – in the project documentation we find lots of examples, recipes and code sources so that we can start using them in our project in minutes.
Additionally, Nest with all of these big words gives us the reference to the knowledge behind it. So if you don’t know some patterns – don’t worry, you’ll be lead through the process smoothly.
Batteries included
Here comes NestJS, a framework which is fully written in TypeScript (it supports JS too, but types are good), it’s easily testable and brings in all the necessary stuff you always think about but you don’t know what to choose.
- Dependency injection container – NestJS comes with its own DiC, an utility that seems to be forgotten in the JavaScript world but I can’t really live without it. There are a few solutions like Inversify or Bottle but NestJS has its own solution in place. And it supports factory injection too.
- Modularisation – in NestJS every logical part of the application which lives within the same domain boundary is a module and it encourages encapsulation.
- Testability – due to introducing DiC and Modularisation you can build your app pretty much based on services, keeping your controllers thing, which makes it easier to test.
- Written in TypeScript – types are good. They allow you to stop thinking that the thing you’re assigning to a variable is the one that’s needed. It has to be
Getting started: building a simple weather app
In this part of the article we’ll write a simple weather app using Nest framework and OpenWeatherMap API.
Prepare the project
First of all, let’s make sure you’ve got supported Node.js version installed:
node -v
If it’s higher than 6.11.0 you’re all sorted. If you don’t have Node.js installed or the version is incorrect, please install or update your runtime.
The second step is to retrieve API key from the OpenWeatherMap website. To achieve that we need to register and after successful registration we’ll be able to retrieve our API key from the API keys tab.
That’s enough of preparation. Let’s setup the project. For this purpose I’ll use Nest’s TypeScript starter repository (there’s also a way to build a project from scratch, but I’m lazy). It delivers a good beginner’s experience and has everything you need to start writing code.
$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd weather-app/
Install the dependencies and start the development server:
$ npm i
$ npm run start
When the project dependencies are installed and the app has successfully started you should see the following output in the console and heading to the url of http://localhost:3000/ in your browser should give you the warm and welcoming Hello World! text.
> nest-typescript-starter@1.0.0 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
Install HTTP client
We’ve got the project set up, API key to get the weather data and a development server, ready to deliver.
Let’s install a HTTP client now and in this area my personal preference is axios. Why axios? It’s a Promise based client which support both server and client side with a lot of useful features like: automatic response to JSON transforming and the dedicated mocking tool – moxios – which makes testing smooth and easy.
$ npm i --save axios
Build the first Service
Now we can start building our first service.
To make this happen let’s create a file in our src/ folder called weather.service.ts:
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;
}
}
We’re creating a class which will encapsulate the HTTP client making the actual API calls. One thing to notice is the class decorator @Component(), thanks to which the framework will know what this is a component we want to register in the DiC. It has one method, which is asynchronous – it’ll return a Promise – which returned to the controller will be smoothly handled by Nest.
HTTP communication layer
The next thing we need to build is the controller. Create a file named weather.controller.ts in your src/folder:
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;
}
}
The decorator @Controller(‘weather’) tells the framework that we expect this controller to respond on the /weather route.
Then we got our WeatherService injected in the class constructor and set to a private property called weatherService.
Finally there’s an async action called root which returns a Promise, eventually resolving to an object. Inside it calls our weatherService and gets the actual weather forecast in New York.
Connect the dots
To make our application working, the last thing we need to do is to connect all the pieces together in the Application Modul:
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 {}
Save the file, restart your development server and when you navigate to the url http://127.0.0.1:3000/weather in your browser, you should see response from the weather service.
The code above was written to show how quickly we can build something nice in NestJS. However I see a few improvements there, which haven’t been made because I wanted to keep it simple:
- Interfaces for return types. We can take a full advantage of using TypeScript and strongly type all the things
- Error handling. When the promise won’t resolve, our controller will very likely break
- Test suite. We haven’t written any tests yet
- We’re returning the whole data blob. We can strip out only the values we care about
Summary
We’ve discussed NestJS from the theory and did a practical example. For more information please refer to the official docs of the framework, which contain a lot of ready to use recipes and code snippets.
Node.js was created to scale and enable productive development of the real time network applications, which it does very well.
Now we’ve got NestJS framework solving architectural problems.
0 Comments