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
