В Webpack параметр devtool управляет генерацией source
maps — файлов сопоставления минифицированного кода с исходным. В
продакшене прямое раскрытие исходников через обычные карты
(source-map) создаёт риск утечки бизнес-логики, внутренних
API-эндпоинтов и алгоритмов.
Режим hidden-source-map решает задачу разделения: карты
генерируются, но не становятся публично доступными через браузер.
При использовании:
module.exports = {
mode: "production",
devtool: "hidden-source-map"
};
Webpack:
.map файлы для каждого бандла//# sourceMappingURL= в итоговый
JSТаким образом, карта существует как артефакт сборки, но не является частью публичного фронтенд-ответа.
| Режим | Поведение | Безопасность | Отладка |
|---|---|---|---|
| source-map | карта доступна браузеру | низкая | высокая |
| hidden-source-map | карта не публикуется в JS | средняя/высокая | высокая (через внешние системы) |
| nosources-source-map | исходники скрыты, только стектрейсы | высокая | ограниченная |
hidden-source-map занимает промежуточную позицию:
отладка переносится в сторонние системы ошибок, а не в DevTools
конечного пользователя.
Типовая схема выглядит следующим образом:
.map файлы.map файлы загружаются в систему трекинга ошибокКлючевая идея — разделение публичного и приватного артефактов.
Sentry использует source maps для преобразования minified stack trace в читаемый вид с указанием оригинальных файлов, строк и функций.
npm install @sentry/webpack-plugin --save-dev
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
module.exports = {
mode: "production",
devtool: "hidden-source-map",
plugins: [
new SentryWebpackPlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: "my-org",
project: "my-project",
include: "./dist",
release: process.env.RELEASE_VERSION,
urlPrefix: "~/"
})
]
};
Плагин выполняет несколько операций:
dist на наличие .map файлов.map (опционально)Критический момент — корректная версия сборки.
RELEASE_VERSION=1.2.3 webpack --config webpack.prod.js
И в приложении:
Sentry.init({
dsn: "...",
release: "1.2.3"
});
Без совпадения release source maps не будут применяться
к ошибкам.
Несмотря на отсутствие прямой ссылки на .map, сами файлы
остаются чувствительными артефактами.
Риски:
Практика:
.map вне публичного CDNBugsnag поддерживает загрузку source maps через CLI и API.
npm install @bugsnag/source-maps --save-dev
npx bugsnag-source-maps upload \
--api-key $BUGSNAG_API_KEY \
--app-version 1.2.3 \
--minified-url https://cdn.example.com/assets/app.js \
--source-map dist/app.js.map \
--minified-file dist/app.js
Webpack конфигурация:
module.exports = {
mode: "production",
devtool: "hidden-source-map",
output: {
filename: "app.js",
path: __dirname + "/dist",
publicPath: "https://cdn.example.com/assets/"
}
};
После сборки выполняется отдельный CI-этап загрузки:
webpack --config webpack.prod.js
bugsnag-source-maps upload --app-version $VERSION ...
Типовой pipeline:
.map в публичную средуПример разделения этапов:
npm run build
npm run upload-sourcemaps
npm run deploy
Для минимизации риска утечек часто применяется постобработка:
find dist -name "*.map" -type f -delete
или через Webpack plugin:
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
Но чаще используется отдельный CI-степ, чтобы гарантировать успешную загрузку перед удалением.
Причины:
releaseurlPrefixПричины:
minified-urlПричины:
source-map вместо
hidden-source-map.mapWebpack поддерживает несколько режимов, используемых в зависимости от среды:
eval-source-map — разработка, быстрый rebuildcheap-source-map — ускоренная генерацияinline-source-map — встроенные картыhidden-source-map — продакшен с внешней загрузкойhidden-source-map остаётся наиболее распространённым
вариантом для production-инфраструктуры с внешними системами анализа
ошибок.
Source maps включают:
Минификаторы (Terser, SWC) сохраняют mapping через генерацию
специальных сегментов .map структуры, которая затем
интерпретируется Sentry и Bugsnag для восстановления stack trace.