Опция sourceRoot

Назначение и роль в системе source map

sourceRoot — это параметр конфигурации esbuild, который влияет на формирование source map и определяет базовый путь (корневую директорию) для исходных файлов при отладке. Он используется совместно с sourceMap и позволяет управлять тем, как инструменты разработчика браузера интерпретируют пути к исходному коду.

Source map представляет собой структуру сопоставления между минифицированным или транспилированным кодом и оригинальными исходными файлами. Внутри этой структуры хранятся пути к исходникам, и именно здесь sourceRoot играет ключевую роль, задавая общий префикс для этих путей.


Поведение без sourceRoot

При включённой генерации source map:

esbuild app.js --bundle --sourcemap

esbuild формирует .map файл, в котором пути к исходным файлам записываются относительно текущей структуры проекта или входных точек.

Пример содержимого source map:

{
  "version": 3,
  "sources": [
    "src/utils/math.js",
    "src/index.js"
  ],
  "mappings": "..."
}

В таком виде браузер пытается интерпретировать пути напрямую, что может приводить к:

  • некорректному отображению структуры исходников в DevTools;
  • невозможности сопоставления файлов при другой корневой структуре;
  • проблемам при деплое, если исходные файлы находятся в другом каталоге или домене.

Смысл sourceRoot

sourceRoot задаёт базовый путь, который добавляется к каждому элементу массива sources внутри source map.

Пример:

esbuild app.js --bundle --sourcemap --source-root=/static/src

Результирующий source map:

{
  "version": 3,
  "sources": [
    "utils/math.js",
    "index.js"
  ],
  "sourceRoot": "/static/src",
  "mappings": "..."
}

Логика интерпретации в браузере:

/static/src + utils/math.js  → /static/src/utils/math.js
/static/src + index.js       → /static/src/index.js

Практическое назначение

1. Унификация структуры при деплое

При сборке проекта часто исходные файлы перемещаются или обслуживаются с другого пути (CDN, сервер статических файлов).

Пример ситуации:

  • локально: /Users/dev/project/src/...
  • продакшн: https://cdn.example.com/assets/src/...

Использование sourceRoot позволяет нормализовать отображение путей:

esbuild src/index.js --bundle --sourcemap --source-root=https://cdn.example.com/assets

2. Упрощение отладки в DevTools

Без sourceRoot DevTools могут отображать длинные или нерелевантные пути:

../. ./. ./. ./project/src/components/Button.js

С sourceRoot структура становится логической и читаемой:

components/Button.js

3. Работа с монорепозиториями

В монорепозиториях часто присутствует вложенная структура:

repo/
  packages/
    ui/
      src/
    app/
      src/

При сборке одного пакета пути могут терять контекст. sourceRoot позволяет зафиксировать базовую точку:

esbuild packages/ui/src/index.js --bundle --sourcemap --source-root=/packages/ui/src

Использование в JavaScript API

В Node.js API esbuild параметр задаётся через объект конфигурации:

import * as esbuild from 'esbuild';

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  sourcemap: true,
  sourceRoot: '/static/src'
});

Взаимодействие с sourcesContent

Source map может содержать не только пути, но и сами исходные тексты файлов (sourcesContent).

Структура:

{
  "sources": ["utils/math.js"],
  "sourcesContent": ["export const sum = (a, b) => a + b;"]
}

sourceRoot в этом случае влияет только на интерпретацию путей, но не изменяет содержимое sourcesContent. Это означает:

  • код остаётся встроенным в source map;
  • пути используются только для навигации в DevTools;
  • sourceRoot не влияет на фактический код выполнения.

Особенности поведения

Абсолютные и относительные пути
  • Если sources содержат относительные пути, sourceRoot добавляется как префикс.
  • Если пути уже абсолютные (например, URL), поведение зависит от браузера, но обычно sourceRoot игнорируется или не применяется.

Пример:

"sourceRoot": "/app",
"sources": ["src/a.js"]

/app/src/a.js


Влияние на source map resolution

Некоторые инструменты (Webpack DevTools, Chrome DevTools, VS Code Debugger) используют следующую логику:

  1. Берут sourceRoot
  2. Конкатенируют с sources[i]
  3. Пытаются найти файл в файловой системе или по URL

Ошибки в sourceRoot приводят к:

  • “Source not found”
  • пустым вкладкам исходников
  • невозможности установки breakpoint’ов

Сравнение с альтернативными инструментами

В отличие от некоторых сборщиков, где sourceRoot автоматически вычисляется, esbuild требует явного указания при необходимости корректировки путей.

Например:

  • Webpack использует devtoolModuleFilenameTemplate
  • Rollup использует output.sourcemapPathTransform
  • esbuild — минималистичен и использует только sourceRoot как базовый механизм

Типичные сценарии конфигурации

Локальная разработка без CDN
esbuild src/index.js --bundle --sourcemap

sourceRoot не требуется.


Продакшн с CDN
esbuild src/index.js \
  --bundle \
  --minify \
  --sourcemap \
  --source-root=https://cdn.example.com/app

Встраивание в серверный рендеринг
esbuild.build({
  entryPoints: ['src/server.js'],
  bundle: true,
  sourcemap: true,
  sourceRoot: '/assets/server'
});

Ограничения и нюансы

  • sourceRoot не переписывает физическое расположение файлов.
  • Не влияет на bundling, tree-shaking или minification.
  • Используется исключительно в metadata source map.
  • Не решает проблему неверных путей, если исходники вообще не включены в sourcesContent.

Ошибки конфигурации

Несовпадение с реальной структурой
sourceRoot: "/static/src"
sources: ["app.js"]

Если файл фактически находится в /static/app.js, DevTools не найдёт его.


Избыточные префиксы
--source-root=/project/src/src

Приводит к дублированию путей:

/project/src/src/utils.js

Использование без source map
--source-root=/src
--sourcemap=false

В этом случае параметр полностью игнорируется, так как отсутствует карта источников.


Влияние на производственный пайплайн

sourceRoot часто становится частью стратегии управления отладочными артефактами:

  • разделение dev/prod source maps;
  • контроль публичных путей к исходникам;
  • интеграция с CI/CD пайплайнами;
  • обеспечение корректного stack trace в production debugging.

В связке с --sourcemap=external позволяет хранить карты отдельно:

esbuild src/index.js \
  --bundle \
  --sourcemap=external \
  --source-root=/src

Поведение в браузерных DevTools

Chrome DevTools интерпретирует sourceRoot следующим образом:

  • если значение является URL — используется как базовый адрес;
  • если путь относительный — применяется к виртуальной структуре source map;
  • если значение отсутствует — используется путь из sources напрямую.

В результате дерево исходников может выглядеть как:

static/
  src/
    components/
    utils/

или без структуры вовсе, если sourceRoot не задан.