El plugin de CLI
El fix recomendado para webpack: true, automático, en cada build, sin ningún paso aparte que recordar.
Este es el mismo mecanismo que usa el propio plugin de CLI de @nestjs/swagger para funcionar bajo webpack: true. Por eso @ApiProperty() no es obligatorio en cada propiedad de un DTO incluso en un build con webpack. El Nest CLI alimenta un hook de plugin de compilador TypeScript (compilerOptions.plugins) tanto al builder tsc como al de webpack (ts-loader) de forma idéntica.
Registra el plugin
Registra nestjs-docfy en nest-cli.json:
{
"compilerOptions": {
"webpack": true,
"plugins": ["nestjs-docfy"]
}
}import { applyDocfyMetadata } from 'nestjs-docfy';
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, applyDocfyMetadata(document));| Option | Type | Default | Description |
|---|---|---|---|
metadataPath | string | docfy-metadata.json next to the running entry file | Where to read the plugin-generated metadata from. |
strict | boolean | false | Throw instead of warning when the metadata file is missing or invalid. |
Detección automática
Olvidar registrar el plugin es fácil de pasar por alto hasta que un build sale sin documentación, así que cada ejecución de generate ya comprueba nest-cli.json e imprime un aviso cuando webpack: true está activado sin el plugin. Pasa --register-plugin para que lo arregle por ti en vez de editar el archivo a mano:
npx nestjs-docfy generate --register-pluginEsto es opt-in a propósito, ya que algunos equipos se quedan deliberadamente con patch-spec en vez de un plugin de compilador, así que generate nunca edita nest-cli.json a menos que se lo pidas explícitamente. Añade al final de cualquier array compilerOptions.plugins existente (reconociendo entradas tanto en forma de string como de objeto como ya registradas) y respeta --dry-run.
Cómo funciona
El plugin de nestjs-docfy no reescribe ninguna sintaxis de decorator ni toca el AST en absoluto. En cada compilación vuelve a ejecutar exactamente el mismo análisis estático que ya hacen generate/check/patch-spec (vía ts-morph, contra el árbol fuente, no el bundle) y escribe el patch resultante en docfy-metadata.json junto a la salida del build.
Luego, justo después de SwaggerModule.createDocument(), applyDocfyMetadata() lee ese archivo y lo fusiona. No hay ningún require.cache involucrado ni problema de identidad de clase en el bundle, porque nunca necesita que la app en ejecución calcule nada.
vs. patch-spec
Si prefieres no añadir un plugin de compilador (por ejemplo, un pipeline de build que no es el Nest CLI, o una política más estricta sobre qué se ejecuta durante la compilación), patch-spec calcula el mismo patch a mano contra un documento ya construido. Esa era la única opción antes de que existiera el plugin, y sigue siendo útil para parcheos puntuales.
Builder SWC
@nestjs/cli trata el builder SWC de forma distinta. Nunca llama a before() bajo "builder": "swc", solo un ReadonlyVisitor, y solo cuando "typeCheck": true también está activado (si no, SWC se salta el chequeo de tipos por su cuenta). Este plugin exporta ambos hooks, así que activar esa opción es todo lo que hace falta:
{
"compilerOptions": {
"builder": "swc",
"typeCheck": true,
"plugins": ["nestjs-docfy"]
}
}Algo que conviene saber: registrar el plugin así escribe un archivo metadata.ts junto a la raíz de tu source en cada build. Es el mismo artefacto que el propio soporte de SWC de @nestjs/swagger ya produce ahí, vacío e inofensivo si ese plugin no está registrado también.
Deja fuera typeCheck y el plugin simplemente se queda callado. El build sigue funcionando, pero no se escribe ningún docfy-metadata.json y applyDocfyMetadata() no tiene nada que fusionar. generate detecta justo esa combinación y avisa.
Nada de esto afecta al discovery en runtime de DocfyModule. Funciona bajo SWC exactamente igual que bajo tsc, ya que SWC sigue compilando un archivo por módulo y el require.cache termina poblado de la misma forma. Si activar typeCheck no es una opción, @WithDocs() junto con DocfyModule.forRoot() te lleva ahí igual, sin el plugin.