Módulos dinámicos

Intermedio
Nest
Nest
Actualizado: 15/06/2025

Introducción a módulos dinámicos

Los módulos dinámicos en NestJS representan una evolución natural de los módulos estáticos que hemos visto anteriormente. Mientras que los módulos tradicionales tienen una configuración fija definida en tiempo de compilación, los módulos dinámicos permiten crear configuraciones flexibles que se determinan en tiempo de ejecución.

Esta capacidad resulta especialmente útil cuando necesitamos que un módulo se comporte de manera diferente según el entorno, la configuración del usuario, o parámetros específicos de la aplicación. Los módulos dinámicos son la base de muchas librerías populares del ecosistema NestJS, como @nestjs/config, @nestjs/typeorm y @nestjs/jwt.

Diferencias fundamentales con módulos estáticos

Un módulo estático tradicional se define con una estructura fija:

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

En contraste, un módulo dinámico se crea mediante métodos estáticos que retornan un objeto DynamicModule:

@Module({})
export class DatabaseModule {
  static forRoot(options: DatabaseOptions): DynamicModule {
    return {
      module: DatabaseModule,
      imports: [],
      providers: [
        {
          provide: 'DATABASE_OPTIONS',
          useValue: options,
        },
        DatabaseService,
      ],
      exports: [DatabaseService],
    };
  }
}

Estructura de un módulo dinámico

La interfaz DynamicModule extiende las propiedades de un módulo estático añadiendo la propiedad obligatoria module:

interface DynamicModule {
  module: Type<any>;
  imports?: Array<Type<any> | DynamicModule | Promise<DynamicModule>>;
  controllers?: Type<any>[];
  providers?: Provider[];
  exports?: Array<string | symbol | Type<any> | DynamicModule>;
  global?: boolean;
}

La propiedad module debe hacer referencia a la clase del módulo que está creando la configuración dinámica. Las demás propiedades funcionan igual que en los módulos estáticos, pero pueden ser calculadas dinámicamente.

Implementación básica de un módulo dinámico

Veamos cómo crear un módulo dinámico para gestionar configuraciones de base de datos:

import { Module, DynamicModule } from '@nestjs/common';

interface DatabaseConfig {
  host: string;
  port: number;
  database: string;
  username: string;
  password: string;
}

@Module({})
export class ConfigurableModule {
  static forRoot(config: DatabaseConfig): DynamicModule {
    const providers = [
      {
        provide: 'DATABASE_CONFIG',
        useValue: config,
      },
      {
        provide: 'DATABASE_CONNECTION',
        useFactory: (config: DatabaseConfig) => {
          // Lógica para crear conexión basada en la configuración
          return `Conectado a ${config.host}:${config.port}/${config.database}`;
        },
        inject: ['DATABASE_CONFIG'],
      },
    ];

    return {
      module: ConfigurableModule,
      providers,
      exports: ['DATABASE_CONNECTION'],
    };
  }
}

Uso de módulos dinámicos

Para utilizar un módulo dinámico, lo importamos llamando a su método estático de configuración:

@Module({
  imports: [
    ConfigurableModule.forRoot({
      host: 'localhost',
      port: 5432,
      database: 'myapp',
      username: 'admin',
      password: 'secret123'
    })
  ],
  controllers: [AppController],
})
export class AppModule {}

Esta flexibilidad permite que el mismo módulo se configure de manera diferente en distintos entornos:

// Configuración para desarrollo
ConfigurableModule.forRoot({
  host: 'localhost',
  port: 5432,
  database: 'myapp_dev',
  username: 'dev_user',
  password: 'dev_pass'
})

// Configuración para producción
ConfigurableModule.forRoot({
  host: 'prod-server.com',
  port: 5432,
  database: 'myapp_prod',
  username: 'prod_user',
  password: process.env.DB_PASSWORD
})

Patrones comunes de nomenclatura

Los módulos dinámicos suelen seguir patrones de nomenclatura específicos para sus métodos estáticos:

  • forRoot(): Configuración global del módulo, típicamente usado en el módulo raíz de la aplicación
  • forFeature(): Configuración específica para características particulares, usado en módulos de funcionalidad
  • register(): Configuración simple sin opciones asíncronas
  • registerAsync(): Configuración asíncrona que permite inyección de dependencias
@Module({})
export class FeatureModule {
  // Configuración síncrona
  static register(options: FeatureOptions): DynamicModule {
    return {
      module: FeatureModule,
      providers: [
        { provide: 'FEATURE_OPTIONS', useValue: options }
      ]
    };
  }

  // Configuración asíncrona
  static registerAsync(options: FeatureAsyncOptions): DynamicModule {
    return {
      module: FeatureModule,
      imports: options.imports || [],
      providers: [
        {
          provide: 'FEATURE_OPTIONS',
          useFactory: options.useFactory,
          inject: options.inject || []
        }
      ]
    };
  }
}

Ventajas de los módulos dinámicos

Los módulos dinámicos ofrecen múltiples beneficios en el desarrollo de aplicaciones NestJS:

  • Reutilización: Un mismo módulo puede servir diferentes propósitos según su configuración
  • Flexibilidad: Permiten adaptar el comportamiento según el entorno o parámetros específicos
  • Mantenibilidad: Centralizan la lógica de configuración en un solo lugar
  • Escalabilidad: Facilitan la creación de librerías y paquetes configurables

Esta aproximación es fundamental para entender cómo funcionan internamente muchas de las librerías más utilizadas en el ecosistema NestJS, y proporciona las bases para crear nuestros propios módulos configurables y reutilizables.

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en Nest

Documentación oficial de Nest
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Nest es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Nest

Explora más contenido relacionado con Nest y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  • Comprender la diferencia entre módulos estáticos y dinámicos en NestJS.
  • Aprender la estructura y propiedades de un módulo dinámico.
  • Implementar un módulo dinámico básico con configuración personalizada.
  • Utilizar módulos dinámicos en diferentes entornos mediante métodos estáticos.
  • Conocer patrones comunes de nomenclatura y ventajas de los módulos dinámicos.