Skip to main content
This covers effective debugging methods using TypeScript source maps.

What are Source Maps?

Source maps are files that map compiled JavaScript code back to the original TypeScript code. This allows you to see the original TypeScript code in error stack traces and debuggers. Usage:
  • View original TypeScript locations in error stack traces
  • Set breakpoints in TypeScript code in debuggers
  • Map production errors to original code

Enabling Source Maps

tsconfig.json Configuration

{
  "compilerOptions": {
    "sourceMap": true,           // Generate source maps
    "inlineSourceMap": false,    // Generate as separate files
    "inlineSources": false,      // Don't include original sources
    "outDir": "dist"
  }
}
Generated files:
📁dist/
📄JSindex.js
📄MAPindex.js.map - Source map file
📁models/
📄JSuser.model.js
📄MAPuser.model.js.map

inlineSourceMap vs sourceMap

// Recommended: Separate files (for both development and production)
{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSourceMap": false
  }
}

// Inline (increases bundle size)
{
  "compilerOptions": {
    "sourceMap": false,
    "inlineSourceMap": true  // Included in .js files
  }
}

Error Stack Traces

Without Source Maps

Error: User not found
    at UserModelClass.findById (dist/models/user.model.js:45:15)
    at processUser (dist/services/user.service.js:12:28)
    at async main (dist/index.js:8:20)
Only compiled JavaScript locations are shown, making debugging difficult.

With Source Maps

Error: User not found
    at UserModelClass.findById (src/models/user.model.ts:32:11)
    at processUser (src/services/user.service.ts:8:24)
    at async main (src/index.ts:5:15)
Shows the original TypeScript file and line numbers accurately.

Using Source Maps in Node.js

—enable-source-maps Flag

# Node.js 12.12.0 or later
node --enable-source-maps dist/index.js
Or in package.json:
{
  "scripts": {
    "start": "node --enable-source-maps dist/index.js",
    "dev": "node --enable-source-maps --watch dist/index.js"
  }
}
# tsx automatically supports source maps
pnpm dev
Sonamu uses tsx, so source maps work without additional configuration.

VSCode Debugger Configuration

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Sonamu Dev Server",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["dev"],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "sourceMaps": true,
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "skipFiles": [
        "<node_internals>/**",
        "node_modules/**"
      ]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Run Test",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["test", "${file}"],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "sourceMaps": true
    }
  ]
}

Debugging Steps

  1. Set breakpoints
    • Click to the left of the line number in TypeScript files (.ts)
  2. Start debugger
    • Press F5 or run from the “Run and Debug” panel
  3. Inspect variables
    • When paused at a breakpoint, examine variable values
    • Evaluate expressions in the Watch panel
  4. Step execution
    • F10: Step Over (next line)
    • F11: Step Into (inside function)
    • Shift+F11: Step Out (outside function)

Production Source Maps

Security Considerations

// Development environment
{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSources": false  // Don't include original sources
  }
}
When deploying to production:
# Exclude source map files
dist/
├── index.js Deploy
├── index.js.map Exclude (or store separately)

Integration with Error Tracking Services

Upload source maps to error tracking services like Sentry:
# Sentry CLI example
sentry-cli releases files VERSION upload-sourcemaps ./dist

Troubleshooting Source Maps

1. Source Maps Not Generated

Check:
# Check tsconfig.json
cat tsconfig.json | grep sourceMap

# Check for .map files after build
ls -la dist/**/*.map
Solution:
{
  "compilerOptions": {
    "sourceMap": true  // Explicitly enable
  }
}

2. Stack Trace Still Points to .js Files

Cause: Node.js is not recognizing source maps Solution:
# Add --enable-source-maps flag
node --enable-source-maps dist/index.js

# Or use tsx (automatic support)
pnpm tsx dist/index.js

3. VSCode Debugger Not Working

Check:
// launch.json
{
  "sourceMaps": true,  // Verify enabled
  "outFiles": [
    "${workspaceFolder}/dist/**/*.js"  // Correct path
  ]
}
Solution:
  1. Reset .vscode/launch.json
  2. Restart TypeScript server: Cmd+Shift+P → “TypeScript: Restart TS Server”
  3. Restart debugger

4. Incorrect Line Numbers

Cause: Source maps are out of sync with code Solution:
# Clean build
rm -rf dist/
pnpm build

# Or restart development mode
pnpm dev

Validating Source Maps

Manual Validation

# Check source map file
cat dist/index.js.map | jq .sources

# Example output:
# [
#   "../src/index.ts",
#   "../src/models/user.model.ts"
# ]

Validation with source-map Package

import { SourceMapConsumer } from "source-map";
import fs from "fs";

const rawSourceMap = JSON.parse(
  fs.readFileSync("dist/index.js.map", "utf-8")
);

SourceMapConsumer.with(rawSourceMap, null, (consumer) => {
  // Compiled position -> Original position
  const pos = consumer.originalPositionFor({
    line: 45,
    column: 15
  });

  console.log(pos);
  // {
  //   source: '../src/index.ts',
  //   line: 32,
  //   column: 11,
  //   name: 'findUser'
  // }
});

Source Maps in the Browser

Vite Development Server

Vite automatically generates and serves source maps:
// vite.config.ts
export default defineConfig({
  build: {
    sourcemap: true  // Include in production builds
  }
});

Chrome DevTools

  1. Open Sources tab
    • F12 → Sources tab
  2. Find TypeScript files
    • Look for .ts files under webpack:// or src/
  3. Set breakpoints
    • Click on line numbers in TypeScript files
  4. Debug
    • Refresh the page to hit breakpoints

Best Practices

1. Always Enable in Development

{
  "compilerOptions": {
    "sourceMap": true  // Essential for development
  }
}

2. Exclude .map Files from Git

# Source maps are generated during build
dist/**/*.map

# Manage production source maps separately
production-sourcemaps/

3. Selective Use in Production

// Environment-specific tsconfig
// tsconfig.prod.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "sourceMap": false  // Disable in production
  }
}
// package.json
{
  "scripts": {
    "build:dev": "tsc",
    "build:prod": "tsc -p tsconfig.prod.json"
  }
}

4. Error Monitoring Integration

In production, provide source maps only to error tracking services:
// Map original location when error occurs
import { SourceMapConsumer } from "source-map";

async function mapError(error: Error) {
  // Parse stack trace
  const match = error.stack?.match(/dist\/(.+):(\d+):(\d+)/);
  if (!match) return error;

  const [, file, line, column] = match;
  const mapFile = `sourcemaps/${file}.map`;

  // Find original location with source map
  const rawMap = JSON.parse(fs.readFileSync(mapFile, "utf-8"));
  const consumer = await new SourceMapConsumer(rawMap);

  const original = consumer.originalPositionFor({
    line: parseInt(line),
    column: parseInt(column)
  });

  return {
    ...error,
    originalFile: original.source,
    originalLine: original.line,
    originalColumn: original.column
  };
}

1. source-map-support

Automatically apply source maps at runtime:
pnpm add source-map-support
// Top of index.ts
import "source-map-support/register";

2. @esbuild-kit/core-utils

Source map support for esbuild-based build tools:
import { installSourceMapSupport } from "@esbuild-kit/core-utils";
installSourceMapSupport();

3. Chrome DevTools

  • Map compiled CSS to original SCSS/LESS in Elements tab
  • Check source map downloads in Network tab
  • Click original file links in Console