NestJs Learning Tour-Modular System

Keywords: node.js Database

Welcome to NestJs Travel Series

Modular

Modules in NestJs are the basic elements for building and organizing business units. Decorative module @Module() is used to declare the meta-information of the module:

  • Which service providers are exported by this module
  • Which dependency modules are imported into this module
  • Which controllers are provided in this module

Each NestJs has at least one follow module, which is defined by app.module.ts. The root module generally does not put specific business logic, the specific business logic should sink to each sub-business module to do.

For example, we develop a mall system, which has the following business modules:

  • Order Center
  • User Center
  • Payment Center
  • Commodity Center
  • Logistics Centre

Then we can define the following module structure:

|-- app.module.ts
|-- order
    |-- order.module.ts
    |-- services
        |-- order.service.ts
    |-- controllers
        |-- order.controller.ts
|-- user
    |-- user.module.ts
    |-- services
        |-- user.service.ts
    |-- controllers
        |-- user.controller.ts
|-- pay
    |-- pay.module.ts
    |-- services
        |-- wepay.service.ts
        |-- alipay.service.ts
        |-- pay.service.ts
    |-- controller
        |-- pay.controller.ts
...

Modularization has the following advantages:

  • Business Low Coupling
  • Clear boundary
  • Easy to sort out errors
  • Easy to maintain

Module declaration and configuration

@ Module() decorative classes are module classes. The typical usage of this decorative device is as follows:

@Module({
    providers: [UserService],
    controllers: [UserController],
    imports: [OrderModule],
    exports: [UserService]
})
export class UserModule {

}
Name of parameter Explain
proviers List of service providers. This module is available and can be injected automatically.
controllers Controller list, available in this module, for binding routing access
imports The module imported by this module, if the service provider of other modules needs to be used, must import other modules here.
exports The service provider exported by this module can only be used in other modules by the service provider defined here

Module Reexport

There are the following uses in ts:

// a.ts
export interface A {

}
// index.ts
export * from './a';

We can use the following code directly when we use it. Aspect encapsulation

import {A} from './index'

Modules in NestJs have similar usage, for example, we define two basic modules, which are basically imported together when they are used. At this time, we encapsulate them into a CoreModule through module re-export, and import them directly into CoreModule elsewhere.

@Module({
    providers: [CommonService],
    exports: [CommonService]
})
export class CommonModule {}
@Module({
    providers: [Util],
    exports: [Util]
})
export class UtilModule {}
@Module({
    imports: [CommonModule, UtilModule],
    exports: [CommonModule, UtilModule]
})
export class CoreModule {}

Module Initialization and Dependency Injection

If you need to run some logic when the module is instantiated and the logic has external dependencies, you can handle it in the following way

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
  controllers: [UserController],
  providers: [UserService],
})
export class catsModule {
  constructor(private readonly userService: UserService) { // No @Inject
    // Call userService
  }
}

Global module

All the modules defined above need to be imported manually. If some modules are highly usable, such as tool modules, then they can be declared as global modules.

Global modules can be declared using @Global().

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Global()
@Module({
  controllers: [UserController],
  providers: [UserService],
})
export class catsModule {
  
}

Dynamic module

All of the above definitions are static modules. If we need to declare our modules dynamically, such as database modules, I will return to the module only after the connection is successful. At this time, we need to use dynamic modules to process.

The module definition is returned using the module name. forRoot() method, which defines the dynamic module.

@Module({
    providers: [DatabaseProvider]
})
export class DatabaseModule {
    static async forRoot(env: string) {
         const provider =  createDatabaseProvider(env); // Connecting different databases according to environment variables
         return {
             module: DatabaseModule,
             providers: [provider],
             exports: [provider]
         }
    }
}
// user.module.ts
@Module({
    imports: [DatabaseModule.forRoot('production')]
})
export class UserModule {}

Posture in production environment

There is a module example of the mall system above. When our business module is developed, we need to register it with AppModule to take effect. This is also a good example. It's a bit like plug-in. When we need to drop a business, the business code will not move and we can cancel the registration in AppModule.

@Module({
    imports:[UserModule,GoodsModule,OrderModule,PayModule]
})
export class AppModule {}

Ending

Modular system is another important feature of NestJs, which I think is based on DDD idea. Each module is a separate domain business and can be developed independently by a group. Multiple modules can be developed at the same time. If there is a dependency problem, you can first expose the module and the response interface. Others call your interface normally. When the implementation class is developed, NestJs will automatically inject the implementation class, and the caller's code will not be changed.

If you feel you have gained something, please share it with more friends who need it. Thank you.

If you want to exchange more knowledge about NestJs, welcome to join the discussion!

Posted by TheBeginner on Wed, 21 Aug 2019 22:01:58 -0700