Source maps y debugging de TypeScript: configurar VS Code, Node.js y tests con breakpoints

Los source maps son el puente entre el código TypeScript que escribes y el JavaScript que Node.js ejecuta. Con la configuración correcta, puedes poner breakpoints en tus archivos .ts y ver la pila de llamadas con nombres y líneas de TypeScript, sin tener que descifrar el JS compilado.

Configurar source maps en tsconfig.json

// tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,           // genera .js.map junto a cada .js
    "inlineSources": true,       // incluye el fuente .ts dentro del .map (útil en producción)
    "sourceRoot": "",            // raíz de los fuentes en el .map
    "outDir": "dist",
    "rootDir": "src",
    "target": "ES2022",
    "module": "NodeNext",
    "strict": true
  }
}

Con inlineSources: true el archivo .map incluye el contenido de los .ts originales, lo que permite depurar en producción aunque el servidor no tenga acceso a los fuentes.

Node.js con source maps activados

// Antes de compilar, durante desarrollo con tsx:
// npx tsx src/index.ts

// Con Node.js y el código compilado:
// node --enable-source-maps dist/index.js

// Con source maps, el stack trace mostrará:
// Error: algo salió mal
//     at procesarUsuario (src/servicio.ts:42:9)   // ? línea TypeScript original
//     at main (src/index.ts:15:3)

// Sin source maps:
// Error: algo salió mal
//     at procesarUsuario (dist/servicio.js:18:4)   // ? línea JS compilada

Depurar con VS Code: launch.json

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Depurar TypeScript (Node)",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/src/index.ts",
      "runtimeExecutable": "tsx",           // o "ts-node"
      "runtimeArgs": ["--inspect-brk"],
      "sourceMaps": true,
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "env": { "NODE_ENV": "development" }
    },
    {
      "name": "Depurar dist compilado",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/dist/index.js",
      "runtimeArgs": ["--enable-source-maps"],
      "sourceMaps": true,
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "resolveSourceMapLocations": [
        "${workspaceFolder}/**",
        "!**/node_modules/**"
      ]
    }
  ]
}

tsx con --inspect-brk

Para adjuntar el depurador al inicio de la ejecución (el proceso pausa hasta que se adjunta un debugger):

// Terminal:
// node --import tsx/esm --inspect-brk src/index.ts

// O con tsx directamente:
// npx tsx --inspect-brk src/index.ts

// Luego en VS Code:
// "Ejecutar y depurar" ? "Adjuntar a proceso Node.js"
// El breakpoint en el .ts original funciona directamente

Tests de Jest con --runInBand y source maps

// jest.config.ts
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json',
      diagnostics: false,
    },
  },
};

export default config;

// launch.json para depurar tests de Jest:
{
  "name": "Depurar tests Jest",
  "type": "node",
  "request": "launch",
  "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/jest",
  "args": ["--runInBand", "--no-coverage", "${file}"],
  "sourceMaps": true,
  "outFiles": ["${workspaceFolder}/dist/**/*.js"],
  "internalConsoleOptions": "openOnSessionStart"
}

Source maps en Vitest

// Vitest usa Vite internamente y activa source maps automáticamente.
// Para depurar con VS Code y Vitest:
{
  "name": "Depurar tests Vitest",
  "type": "node",
  "request": "launch",
  "autoAttachChildProcesses": true,
  "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
  "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
  "args": ["run", "--reporter=verbose"],
  "smartStep": true
}

Imagen: Pexels / Pixabay

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP