NestJS Project Structure

Project structure

NestJS, unlike other frameworks, offers flexibility in how we structure our projects. However, it’s essential to start with a solid foundation that aligns with best practices and real-world development scenarios.

In this lesson, we’ll delve into the NestJS project structure before discussing the core concepts of the framework. After understanding the project structure, we can navigate and comprehend the framework more effectively. We will also introduce some related concepts at the same time.

Let’s first take a look at what the project structure usually looks like.

Project Root
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── main.ts
├── test
│ ├── jest-e2e.json
│ ├── app.e2e-spec.ts
├── package.json
├── tsconfig.json
├── nest-cli.json
├── README.md
├── dist

Let’s explore the key components and directories of this structure and discover their roles in the development journey.

Entry point

When launching a NestJS application, it begins execution with main.ts (line 7), which serves as the entry point for bootstrapping the runtime environment. This process involves several vital steps.

The first step is the setup of the essential dependencies required for our application’s functionality. Next, it initializes the application instance, establishing the core of the NestJS project. During this stage, we can tailor the application to our needs. We can apply middleware (which enhances the request-response cycle), introduce custom global configurations, and integrate third-party tools. As the bootstrap process concludes, our application—which often utilizes Express as the default web server—becomes operational, running on port 30003000 and ready to handle incoming requests.

Root module

In a NestJS application, app.module.ts (line 5) serves as the root module. Modules in NestJS are used to organize and encapsulate code, acting as containers for registering controllers, services, and components.

By default, in app.module.ts, we’ll find the registration of two fundamental components: AppController (defined in app.controller.ts, see line 4) and AppService (defined in app.service.ts, see line 6). We’ll delve deeper into these components later, but, for now, we need to understand that we import all child modules and declare controllers and providers as needed in the root module.

Controller and service

The controller and service components are vital components that collaborate to manage incoming requests and execute business logic. Within our sample project structure, we encounter the following files:

  • app.controller.ts: This serves as our primary NestJS controller, handling incoming HTTP requests.

  • app.service.ts: This service is injected into the AppController class, enabling it to manage the application’s business logic.

  • app.controller.spec.ts (line 3): This file functions as our unit test suite for the app.controller.ts component. The .spec suffix signifies that it contains the test specifications.

Manifest file

The package.json (line 11) file is the most crucial file in a NestJS project. It’s a JSON file and serves as the project manifest, including script commands, metadata, and project dependencies.

Some of the essential commands in the package.json file are listed below:

  • npm run build: This will trigger the build process, compile the TypeScript, and generate a set of app bundle files that can be deployed to the server.

  • npm run start:dev: This will start the development web server, allowing hot reload, which enables us to change the code and see the updates reflected without needing to restart the server manually.

  • npm run test: This will trigger the execution of unit tests in the project.

Question

Given the command examples above, what’s the command to start the app in debug mode?

Show Answer

Feature module

Feature modules, such as UserModule and AddressModule, serve as containers for related components, like controllers, services, and potentially other modules. They help maintain a clean and organized codebase by grouping related code in one place.

When developing a NestJS application, we typically generate the skeleton of feature modules using the Nest command line tool.

The following illustration shows a root module and its associated feature modules: UserModule and AddressModule.

Root modules and feature modules
Root modules and feature modules

Using UserModule as an example, it contains UserController and UserService, which handle user-related functionalities.

The CommonModule module is a shared module that contains utilities or cross-cutting concerns, like logging or authentication.

Tests

There are two types of tests in NestJS. They are detailed below:

  • Unit tests: Unit tests are typically created as separate files, following a naming convention like [original-file-name].spec.ts. For example, we have app.controller.ts in the sample project, so the corresponding unit test file is app.controller.spec.ts.

  • E2E tests: E2E tests are placed under the test folder, following a naming convention of e2e or e2e-spec. In the sample project, there is a file named app.e2e-spec.ts (line 10). In this course, we use Jest for E2E tests.

Note: Jest is an open-source JavaScript testing framework. It’s popular for its simplicity and good performance. It provides rich features, including parallel execution, snapshot testing, built-in code coverage, and more.

The dist folder

NestJS applications are often written in TypeScript. TypeScript code needs to be transpiled (converted) into standard JavaScript code to be executed by NodeJS or browsers. The dist folder is where the transpiled JavaScript code is placed.

When we deploy a NestJS application, we deploy the contents of the dist folder. Keeping the transpiled code separate from the source code, which is typically found in the src folder, is a good practice. It ensures that the source code remains clean and that there is a clear separation between development and production code.

Other configuration files and the README file

The example project also has a few configuration files and a README file. They are described below:

  • tsconfig.json (line 12): This file contains the TypeScript configuration for our NestJS project. It specifies various TypeScript compiler options.

  • nest-cli.json (line 13): This file provides the project-specific settings for the NestJS CLI, including paths to directories and the naming convention for generated files.

  • README.md (line 14): This file is the documentation file for the project. It typically contains the overview, installation instructions, and other details that users need to know.