MVC
MVC stands for Model-View-Controller. Under the MVC architecture, it generally refers to rendering the page on the server, then sending the page as the response body to the client (browser), similar to the traditional server-side rendering pattern.
By default, Nest uses the Express library under the hood. Therefore, every technique for using the MVC (Model-View-Controller) pattern in Express applies to Nest as well.
First, use the CLI tool to build a simple Nest application:
$ npm i -g @nestjs/cli
$ nest new project
To create an MVC application, you will also need a template engine to render HTML views:
$ npm install --save hbs
Here we use the hbs (Handlebars) engine, but you can use any compatible engine. Once the installation is complete, you will need to configure the Express instance using the following code:
import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; import { AppModule } from './app.module';async function bootstrap() {
const app = await NestFactory.create(
AppModule,
);app.useStaticAssets(join(__dirname, ‘..’, ‘public’));
app.setBaseViewsDir(join(__dirname, ‘..’, ‘views’));
app.setViewEngine(‘hbs’);
await app.listen(3000);
}
bootstrap();
This tells Express that the public directory will be used to store static assets, the views directory will contain templates, and the hbs template engine should be used to render HTML output.
Template Rendering
Now, create a views directory and an index.hbs template, which will print the message passed from the controller:
App{{ message }}
Open the app.controller file and replace the root() method with the following code:
import { Get, Controller, Render } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Render(‘index’)
root() {
return { message: ‘Hello world!’ };
}
}
In this code, you specify the template to use in the @Render() decorator, and pass the return value of the route handler method to the template for rendering. Note that the return value is an object with a message property, which matches the message placeholder created in the template.
When the application is running, open your browser and navigate to http://localhost:3000. You will see the Hello world! message.
Dynamic Template Rendering
If your application logic needs to dynamically decide which template to render, you should use the @Res() decorator and provide the view name in the route handler instead of in the @Render() decorator:
Tip: When Nest detects the @Res() decorator, it will inject the library-specific response object. You can use this object to dynamically render the template.
import { Get, Controller, Res, Render } from '@nestjs/common'; import { Response } from 'express'; import { AppService } from './app.service';@Controller()
export class AppController {
constructor(private appService: AppService) {}
@Get()
root(@Res() res: Response) {
return res.render(
this.appService.getViewName(),
{ message: ‘Hello world!’ },
);
}
}
Standalone Applications
There are several ways to set up a Nest application: you can create a web application, a microservice, or just a simple standalone Nest application (without any network listeners). A Nest standalone application is a wrapper around the Nest IoC container, which holds all instantiated classes. You can directly use the standalone application object to get a reference to any existing instance from any imported module. Therefore, you can leverage the Nest framework anywhere, including scripted CRON jobs, etc. You can even build a CLI on top of it.
Getting Started
To create a Nest standalone application, use the following structure:
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
// application logic...
}
bootstrap();
The standalone application object allows you to get a reference to any instance registered in the Nest application. Suppose you have a TasksService in TasksModule. This class provides a set of methods that you want to call from a CRON job.
const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.get(TasksService);
To access the TasksService instance, use the get() method. The get() method acts as a query that searches across each registered module for the instance. Alternatively, for strict context checking, pass an options object with the strict: true property. When this option is enabled, you must navigate to a specific module to retrieve a specific instance from the selected context.
const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.select(TasksModule).get(TasksService, { strict: true });
Below is a summary of the methods you can use to retrieve instance references from the standalone application object:
| get() | Retrieves an instance of a controller or provider (including guards, filters, etc.) available in the application context |
|---|---|
| select() | Navigates the module graph to extract a specific instance from the selected module (used with strict mode as noted above) |
Tip: In non-strict mode, the root module is selected by default. To select any other module, you need to manually navigate the module graph step by step.
If you want your Node.js application to shut down after the script finishes (for example, for a CRON job script), add await app.close() to the end of your bootstrap function:
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
// application logic...
await app.close();
}
bootstrap();
Scaffolding
Overview
The Nest CLI is a command-line interface tool that initializes, develops, and maintains Nest applications. It helps in many ways, including scaffolding projects, serving in development mode, and building and packaging applications for production distribution. It embodies best-practice architectural patterns to encourage well-structured applications.
Installation
Note: Here we use npm to install packages, including the Nest CLI. You are free to use other package managers if you prefer. With npm, you have several options for managing how your OS command line resolves the Nest CLI binary location. This guide describes installing the Nest binary globally using the -g flag. Please note that globally installing any npm package leaves the responsibility of ensuring the correct version runs up to the user. This means that if you have different projects, each will run the same version of the CLI. A reasonable alternative is to use the npx tool built into the npm CLI (or similar functionality for other package managers) to ensure you run the hosted version of the Nest CLI.
Install the CLI globally using the npm install -g command:
$ npm install -g @nestjs/cli
Tip: Alternatively, you can use the command npx @nestjs/cli@latest without installing the CLI globally.
Basic Workflow
Once installed, you can call CLI commands directly from your OS command line via the nest executable. View the available nest commands by entering:
$ nest --help
Use the following structure to get help for a single command. Replace any command, such as new, add, etc., as seen in the example below with generate, to get detailed help for that command:
$ nest generate --help
To create, build, and run a new basic Nest project in development mode, go to the folder that should be the parent of your new project, then run the following commands:
$ nest new my-nest-project
$ cd my-nest-project
$ npm run start:dev
In your browser, open http://localhost:3000 to see your new running application. The application will automatically recompile and reload when you change any source files.
Tip: It is recommended to use the SWC Builder for faster builds (10x faster performance than the default TypeScript compiler).
Project Structure
When you run nest new, Nest generates a boilerplate application structure by creating a new folder and populating it with a set of initial files. You can continue using this default structure and add new components. The project structure generated by nest new is called standard mode. Nest also supports an alternative structure for managing multiple projects and libraries called monorepo mode.
Aside from some specific considerations around how the build process works (essentially, monorepo mode simplifies the build complexity that can sometimes arise with monorepo-style project structures) and built-in library support, the rest of the Nest features and this documentation apply equally to standard and monorepo project structures. In fact, you can easily switch from standard mode to monorepo mode at any time.
You can use either pattern to manage multiple projects. Below is a summary of the differences:
| Feature | Standard Mode | Monorepo Mode |
|---|---|---|
| Multiple Projects | Separate filesystem structures | Single filesystem structure |
| node_modules & package.json | Separate instances | Shared across monorepo |
| Default Compiler | tsc | webpack |
| Compiler Settings | Specified individually | Monorepo defaults that can be overridden per project |
| Config Files (e.g. .eslintrc.js, .prettierrc, etc.) | Specified individually | Shared across monorepo |
| nest build and nest start Commands | Target automatically defaults to the (only) project in context | Target defaults to the default project in the monorepo |
| Libraries | Managed manually, typically packaged via npm | Built-in support, including path management and packaging |
CLI Command Syntax
All nest commands follow the same format:
nest commandOrAlias requiredArg [optionalArg] [options]
For example:
$ nest new my-nest-project --dry-run
Here, new is the commandOrAlias. The alias for the new command is n. my-nest-project is the required argument. If the requiredArg is not provided on the command line, nest will prompt for it. Additionally, --dry-run has an equivalent shorthand form -d. With that in mind, the following command is equivalent to the one above:
$ nest n my-nest-project -d
Most commands and some options have aliases. Try running nest new --help to see these options and aliases and confirm your understanding of the above structure.
Command Overview
Run nest --help for any of the following commands to see command-specific options
| Command | Alias | Description |
|---|---|---|
| new | n | Scaffolds a new standard mode application with all boilerplate files needed to run |
| generate | g | Generates and/or modifies files based on schematics |
| build | Compiles an application or workspace into an output folder | |
| start | Compiles and runs an application (or the default project in the workspace) | |
| add | Imports a library packaged as a Nest library, runs its installation schematic | |
| info | i | Displays information about installed Nest packages and other useful system information |
Requirements
The Nest CLI requires Node.js binaries built with internationalization support (ICU), such as the official binaries from the Node.js project page. If you encounter ICU-related errors, check that your binary meets this requirement.
node -p process.versions.icu
If this command prints undefined, your Node.js binary does not support internationalization.
This is a discussion topic split from the original thread at https://juejin.cn/post/7368701816441159731