In this course we are going to be covering the NestJS framework from top to bottom, getting you up to speed and creating Enterprise-grade NodeJS applications with the help of NestJS, in no-time.
Almost everything we are going to be looking at, learning, and building in this course will be incremental.
By the end, you will have somewhat real world application, and be ready to fully take advantage of the NestJS framework; even using it as a great jumping off point for your future application.
Before we dive into exactly what what NestJS is, let’s take a step back and look at the NodeJS ecosystem as a whole. NodeJS makes no assumption and includes almost nothing by default, for it’s purposely meant to be very bare bones.
NodeJS by design has a minimalistic setup, and developers are in charge of setting up everything they want to use for their application.
With this situation, using NodeJS is, have applies to everything form how you handle routing, API calls, setting up WebSockets, to even rudimentary things like, code organization, file structure, and naming conventions.
As NodeJS has been around for may years, and there are plenty of framework that have helped make some of these requirements simpler, most notably ExpressJS; But they all still require A LOT of configuration and effort on the part of the developer.
This ultimately flexibility can be a bit of a double edged sword. Creating potential problems as applications or teams grow very large. NestJS tries to tackle some of these problems by creating an abstraction or overall framework around NodeJS; by letting you focus on the application problems at hand instead of the tiny implementation details such as, setting up TypeScript, API routing, Error handling, Middleware setup, and so on so much more.
NestJS provides an out of the box application architecture that allows developers and to create highly testable, scalable, loosely coupled, and easily maintainable application.
But, how is this achieved?
Think of NestJS as a layer above NodeJS itself, abstracting away difficult tasks, tools, and boilerplate code, while also adding a full fledged toolkit for your application development.
Using NestJS does not lock you into yet another framework,
But instead leverages readily[1] available and prominent[2] options and modules in the community, like those available in ExpressJS applications.
One interesting to note is, that NestJS can even be swapped to use "Fastify" under the hood instead of ExpressJS (which is used by default).
Note
|
Just keep in mind, that you may need to use different Fastify compliant library in your application if you do this. |
The flexibility that NestJS provides here, gives us the ability to create modules that are platform-agnostic[3] not only to HTTP frameworks such as ExpressJS or Fastify but even agnostic across different types of applications.
With NestJS you can build REST-API’s, MVC applications, micro services, GraphQL applications, WebSockets, and even CLI’s and Cron jobs.
With the help of the NestJS dependency injection system; We have the ability to swap out the underlying mechanisms effortlessly.
In this course, we are going to be focusing on creating a real world example REST-API application, utilizing and learning about all the great NestJS features, along the way.
By the time we finish, you will be ready to tackle any challenge with NestJS.
With Nest applications maintaining a separation of concerns, it has never been easier. This is because inside of Nest applications everything has a defined structure in place, letting you work on the task at hand rather than worrying about organization or convention.
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── .eslintrc.js
├── .gitignore
├── nest-cli.json
├── node_modules
├── package.json
├── package-lock.json
├── .prettierrc
├── README.md
├── tsconfig.build.json
└── tsconfig.json
.
If we look inside the root directory of our project, will see a lot of files
that you may be familiar with already, such as "package.json"
,
"tsconfig.json"
- files; ".gitignore"
the eslint configuration
".eslintrc"
.
But most notably here. We have a Nest specific file called, "nest-cli.json"
which will dive into later in this course.
But the core of our Nest application actually lives in the /src
directory,
let’s open it up and see what we have inside.
Firstly our entire Nest application starts with the "main.ts"
- file.
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
In this main.ts
file we can see that our Nest application is being created via
"NestFactory.create()"
taking in an "AppModule"
.
With this application reference we can now listen and "bootstrap()"
our
application to Port 3000
.
Think of this file like the "main starting" - file for your typical NodeJS application, or a lot of root level work needs to be done.
But what was this AppModule
we just passed in?
Well "AppModule"
the "root" - Module for our application. Containing
everything that our app needs to run.
This route module itself can contain other "small" - Modules that are all
different features or chunks of themselves. But when brought together here in
from "app.module.ts"
we get our complete application.
Don’t worry if this doesn’t totally make sense yet. We’ll be diving into Modules more later on.
Let’s open up this "app.module.ts"
- file and take a look inside.
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
As you can see we have a "regular" - class here but with NestJS @Module()
- typescript decorator on top.
If you’re not familiar with decorators, they are simply functions that apply logic.
Decorators can be applied to "classes"" like we’re seeing here, but also to "methods", "properties" and even "parameters".
NestJS utilizes decorators extensively. You’ll be seeing them throughout our code in this course.
We can see that within this @Module({})
- decorator here. We have
encapsulated everything that is important to this "Modules - context". We
even have a few "controllers" and "providers" included with our starter CLI
application.
Let’s take a look at the "app.controller.ts"
and see what it has inside.
// app.control.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
Similar to the app.module.ts
we just saw, a "NestJS - Controller" is also
just a class. But with a different "@Controller()"
- decorator on top, we’ll
be diving deeper into controllers shortly.
But for right now, know that "Controllers" are where "specific - Requests" are "handled" by your application.
In this "Controller". We can see that it utilizes the "AppService"
- Provider to help separate out "business logic" from the Controller itself.
We’ll also be diving into how "Providers" like this "work" and "Dependency Injection" (DI) in future lessons.
As we said "Controllers" handle specific request to our application. We can see
that our starter application includes one "GET - Request" ("@Get()"
) that is
set up for us.
This "GET - Request" utilizes the AppService
We just saw, calling the
"getHello()"
- method on it.
If we dive into the "app.service.ts"
provider here and go to definition. We
can see that it’s simply returning the string of Hello World!
we saw when we
ran our application moments ago.
// app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
That’s the extent [4] of our project so far.
Right now we have a very simple application with just one module. But as we grow this application, we’ll see how Nest - "modular project architecture" encourages us to group features such as routes, services into their "own - Modules".
In the end, this helps us maintain a higher level of reuseability, testability and even helps reduce - "disorganized code" in our applications.
Some of this doesn’t make sense yet, don’t worry, It will all come together as we build out the application throughout this course.
Now that we’ve seen some of the fundamental building blocks of Nest. Let’s beef up our sample application to really see Nest in action.