Lesson 1
Understanding NestJS
Introduction

Welcome to your course on building your first NestJS application. This lesson will get you familiar with NestJS and its project structure. As we embark on this journey, we'll dive into the basics of NestJS — a framework designed for building efficient and scalable server-side applications. Unlike other frameworks like Express.js or Koa, NestJS leverages TypeScript and a modular architecture, making it not only easy to use but also highly maintainable and scalable. At the same time, NestJS uses Express.js under the hood (by default).

Please note that we will not delve into the details of TypeScript or other foundational concepts in this lesson, as our focus will primarily be on understanding NestJS and its project structure.

By the end of this lesson, you should be comfortable setting up a NestJS project and understanding its fundamental structure, which will lay the groundwork for our ToDo app. Let's get started!

What is NestJS?

NestJS is a progressive Node.js framework for building efficient and scalable server-side applications. It uses modern JavaScript, is built with TypeScript (preserving compatibility with plain JavaScript), and combines elements of Object-Oriented Programming (OOP), Functional Programming (FP), and Functional Reactive Programming (FRP). NestJS is inspired by Angular.js so if you are familiar with Angular.js, a lot of these concepts will feel familiar.

Why Use NestJS?
  1. TypeScript Support: NestJS makes use of TypeScript, offering strong typing, advanced code completion, and the ability to catch errors at compile time, leading to more robust applications.

  2. Modular Architecture: The framework's modular structure allows for the organization of code into manageable parts, making it scalable and maintainable. Modules can be easily reused across different parts of the application.

  3. Dependency Injection: NestJS provides a powerful dependency injection system that promotes loose coupling and makes testing and scaling easier.

  4. Extensible: With an adaptable ecosystem, NestJS leverages a vast number of external libraries and offers an easy way to integrate them into projects. It's built on top of Express.js by default but even that is configurable to use something else like Fastify.

  5. Community and Documentation: NestJS boasts a vibrant community and comprehensive documentation, reducing the learning curve and providing support for developers.

Don't worry if you are unfamiliar with any of these terms or concepts. We will cover them throughout the course.

Setting Up the NestJS Project

To bootstrap a sample NestJS project, you can use the NestJS CLI. You can see the installation instruction in the official NestJS documentation. After NestJS CLI is installed on your machine, you can use the following command to create a new project:

Bash
1npm i -g @nestjs/cli 2nest new project-name

In CodeSignal Learn the project is already initialized for you and you can dive straight into coding so you don't need to run these commands here.

Understanding the Project Structure

When you create a new NestJS project using NestJS CLI, various files and directories are automatically generated. Let's break down the key components:

  • app.controller.ts: Controllers handle incoming requests and return responses to the client. This file contains a basic example of a controller.
  • app.service.ts: Services are used to handle business logic. This file contains a simple service that returns a "Hello World!" message.
  • app.module.ts: This is the root module of your application. It defines how your app is organized by configuring modules, controllers, and providers.
  • main.ts: This file is the entry point of your application, responsible for bootstrapping the app.
app.controller.ts

The app.controller.ts file contains a controller, which handles incoming requests and returns responses to the client. This is the entry point for a route and the controller handles it. Here's the relevant code snippet:

TypeScript
1import { Controller, Get } from '@nestjs/common'; 2import { AppService } from './app.service'; 3 4@Controller() 5export class AppController { 6 constructor(private readonly appService: AppService) {} 7 8 @Get() 9 getHello(): string { 10 return this.appService.getHello(); 11 } 12}

The controller handles the request (in this case, it handles the / route by default) and delegates the "business logic" to the service. In an architecture with controllers, the controller is more of an "orchistrator". It receives requests, calls the "business logic", and formats the response.

app.service.ts

The app.service.ts file contains a service, which handles the "business logic". Here's the relevant code snippet:

TypeScript
1import { Injectable } from '@nestjs/common'; 2 3@Injectable() 4export class AppService { 5 getHello(): string { 6 return 'Hello World!'; 7 } 8}

Services can do a lot of different things related to the buisiness needs of the application. In this case, it defines the greeting data of "Hello World!"

app.module.ts

The app.module.ts file is the root module of your application. It defines how your app is organized by configuring modules, controllers, and providers. Here's the relevant code snippet:

TypeScript
1import { Module } from '@nestjs/common'; 2import { AppController } from './app.controller'; 3import { AppService } from './app.service'; 4 5@Module({ 6 imports: [], 7 controllers: [AppController], 8 providers: [AppService], 9}) 10export class AppModule {}

Modules encapsulate different parts of your application and are intended to be specific. We'll get into Modules in future units but for now it is important to understand that your NestJS application needs a root module that is called AppModule in this case.

main.ts

The main.ts file is the entry point of your application, responsible for bootstrapping the app. Here's the relevant code snippet:

TypeScript
1import { NestFactory } from '@nestjs/core'; 2import { AppModule } from './app.module'; 3 4async function bootstrap() { 5 const app = await NestFactory.create(AppModule); 6 await app.listen(3000); 7 console.log('NestJS App is running on http://127.0.0.1:3000'); 8} 9bootstrap();

In this snippet, we import NestFactory from @nestjs/core and AppModule from the ./app.module file. The bootstrap function initializes the NestJS application using the root module (AppModule) and makes it listen on port 3000.

Running a NestJS Application

If you're new to web development, you might be accustomed to writing programs that run for a finite duration and then terminate. However, when building a web application with NestJS, the application needs to run continuously to receive requests from users and respond to them.

When you start a NestJS application, it internally sets up a server (usually based on Express.js by default), and this server runs the application indefinitely, listening for incoming web requests. By default, the application runs on port 3000. As a result, when you run the npm run start command, your application doesn't simply run and exit; it starts up and remains active until you manually stop it. When you are developing your application, it is often better to run npm run start:dev which will watch for any changes you make and re-load the server.

Summary and Next Steps

Congratulations! You've just learned about the basics of a NestJS application and explored its structure. We've covered project setup, understanding key files, and bootstrapping the application. This foundational knowledge will be invaluable as you start building your ToDo app.

In the next practice exercises, you'll have the opportunity to customize and extend the functionality of your app. Keep up the great work, and let's continue this journey towards mastering NestJS!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.