Introduction to nestjs


代码分析

入口main.ts

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  await app.listen(3000);
}
bootstrap();

NestFactory构造

public async create(
    module: any,
    serverOrOptions?: any,
    options?: NestApplicationOptions,
  ): Promise<
    INestApplication & (INestExpressApplication | INestFastifyApplication)
  > {
    const isHttpServer = serverOrOptions && serverOrOptions.patch;
    // tslint:disable-next-line:prefer-const
    let [httpServer, appOptions] = isHttpServer
      ? [serverOrOptions, options]
      : [ExpressFactory.create()/* 默认使用Express*/, serverOrOptions];

    const applicationConfig = new ApplicationConfig();
    const container = new NestContainer(applicationConfig);//生成容器container;传入了配置对象
    httpServer = this.applyExpressAdapter(httpServer);//初始化http服务

    this.applyLogger(appOptions);//日志输出对象
    await this.initialize(module, container, applicationConfig, httpServer);
    return this.createNestInstance<NestApplication>(
      new NestApplication(container, httpServer, applicationConfig, appOptions),
    );
  }

初始化模块

private async initialize(
    module,
    container: NestContainer,
    config = new ApplicationConfig(),
    httpServer: HttpServer = null,
  ) {
    //生成实例加载器和依赖扫描器
    const instanceLoader = new InstanceLoader(container);
    const dependenciesScanner = new DependenciesScanner(
      container,
      new MetadataScanner(),
      config,
    );
    container.setApplicationRef(httpServer);
    try {
      this.logger.log(messages.APPLICATION_START);
      await ExceptionsZone.asyncRun(async () => {
        await dependenciesScanner.scan(module);
        await instanceLoader.createInstancesOfDependencies();
        dependenciesScanner.applyApplicationProviders();
      });
    } catch (e) {
      process.abort();
    }
  }

扫描当前文件的依赖

public async scan(module: Type<any>) {
    await this.scanForModules(module);
    await this.scanModulesForDependencies();
    this.container.bindGlobalScope();
  }

scanForModules扫描及保存模块(包括imports进来的模块)

public async scanForModules(
    module: Type<any> | DynamicModule,
    scope: Type<any>[] = [],
  ) {
    await this.insertModule(module, scope);

    const modules = this.reflectMetadata(module, metadata.MODULES);
    for (const innerModule of modules) {
      await this.scanForModules(innerModule, [].concat(scope, module));
    }
  }

容器对象的insertModule


public async insertModule(
    metatype: Type<any> | DynamicModule | Promise<DynamicModule>,
    scope: Type<any>[],
  ): Promise<Module> {
    if (!metatype) {
      throw new InvalidModuleException(scope);
    }
    //模块编译器先编译模块
    const { type, dynamicMetadata, token } = await this.moduleCompiler.compile(
      metatype,
      scope,
    );
    //根据token判断是否已保存。没有保存则创建一个Module实例。
    if (this.modules.has(token)) {
      return;
    }
    //Module对象能保存组件、注入的服务、路由、导出的对象及相关模块。创建时先保存核心的注入(模块的实例,模块的配置、映射器、MVC对象、外部的上下文生成器、该模块的的所有模块)
    const module = new Module(type, scope, this);
    this.modules.set(token, module);
    //动态模块保存在dynamicModulesMetadata对象中,然后对动态模块里的模块(modules\imports)都执行下addModule方法,共用一个作用域数组
    this.addDynamicMetadata(token, dynamicMetadata, [].concat(scope, type));
    //全局模块则添加到globalModules的Set对象中
    this.isGlobalModule(type) && this.addGlobalModule(module);

    return module;
  }

扫描模块里的依赖项,作依赖注入的准备工作,其实就是处理Module的配置项await this.scanModulesForDependencies();

async scanModulesForDependencies() {
        const modules = this.container.getModules();
        for (const [token, { metatype }] of modules) {
            await this.reflectImports(metatype, token, metatype.name);
            this.reflectProviders(metatype, token);
            this.reflectControllers(metatype, token);
            this.reflectExports(metatype, token);
        }
        this.calculateModulesDistance(modules);
    }