1.1 什么是 sourceMap
-
sourceMap 是为了解决开发代码与实际运行代码不一致时,帮助我们 debug 到原始开发代码的技术。
-
Webpack 通过配置可以自动生成 sourceMap 文件。
.map
文件是一种建立编译后代码与源代码之间映射关系的方法。
Webpack devtool 配置选项概览 (影响构建速度与 sourceMap 质量):
关键类型含义补充说明:
-
hidden-source-map
: 和source-map
一样生成完整的.map
文件,但不在 bundle 中添加引用注释。浏览器不会自动加载,需通过错误监控工具(如 Sentry)使用。 -
cheap-module-eval-source-map
: 在 Webpack 4 文档中常见,等同于 Webpack 5 的eval-cheap-module-source-map
。提供原始源代码(行级),包含 loader sourceMap,sourceMap 作为 DataURL 嵌入,重建速度快。
1.2 配置项解析
配置项本质上是五个关键字的组合:eval
、source-map
、cheap
、module
和 inline
。

1.2.1 source-map (关键字效果)
源代码 (src/index.js
):
ini
let a = 1;
let b = 2;
let c = 3;
输出代码 (dist/main.js
):
ini
// ... (webpack 生成的模块包装函数代码)
(function (module, exports) {
let a = 1;
let b = 2;
let c = 3;
})
// ...
//# sourceMappingURL=main.js.map // 指向外部 .map 文件
1.2.2 eval (关键字效果)
-
使用
eval
执行模块代码。 -
为什么用
eval
? 官方推荐在开发环境下使用带eval
的配置(如eval-source-map
,eval-cheap-module-source-map
),因为它能缓存 sourceMap ,从而使得重建 (rebuild) 速度非常快。 -
eval-source-map
效果: 会带上原始源码的 sourceMap。
输出代码示例 (devtool: "eval"
):
javascript
复制
下载
swift
// ... (webpack 生成的模块包装函数代码)
(function (module, exports) {
eval("let a=1;\r\nlet b=2;\r\nlet c=3;\n\n//# sourceURL=webpack:///./src/index.js?");
});
// ...
输出代码示例 (devtool: "eval-source-map"
):
javascript
// ... (webpack 生成的模块包装函数代码)
(function (module, exports) {
eval("let a=1;\r\nlet b=2;\r\nlet c=3;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2Vz...");
});
// ...
官方说明:
devtool: "eval-source-map"
在 sourceMap 质量上实际等同于devtool: "source-map"
,但它能为模块缓存 sourceMap,使得重建速度要快得多。
1.2.3 inline (关键字效果)
-
inline
就是将 sourceMap 作为DataURL
直接嵌入到 bundle 文件中,不单独生成.map
文件。 -
inline-source-map
效果示例:// ... (webpack 生成的模块包装函数代码,包含原始代码或转换后代码) (function (module, exports) { let a = 1; let b = 2; let c = 3; }) // ... //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2Vz... // 长 base64 字符串
1.2.4 cheap (关键字效果)
-
cheap
(低开销) 的 sourceMap 只映射行(line)信息,不映射列(column)信息。 -
开发环境下,通常行映射已足够定位问题,因此可以使用
cheap
配置项来提高性能。 -
cheap-source-map
效果: 生成的 sourceMap 只包含行映射,不包含列映射,也不包含 loader 的 sourceMap。
1.2.5 module (关键字效果)
-
Webpack 利用 loader 将所有非 JS 模块(如 JSX, TypeScript, Vue SFC, 图片等)转化为它可处理的 JS 模块。
-
仅使用
cheap
配置(如cheap-source-map
)不会包含 loader 处理过程中生成的 sourceMap。 -
什么是模块之间的 sourceMap? 例如,一个
.jsx
文件会经过 Babel loader 处理成.js
文件,再可能被压缩混淆。如果没有 loader 的 sourceMap (module
),那么在 debug 时,你只能定位到压缩前的.js
文件位置,而无法追踪回原始的.jsx
文件。 -
module
的作用: 为了能映射到 loader 处理前的原始源代码 ,我们通常需要加上module
配置(如cheap-module-source-map
)。 -
cheap-module-source-map
效果: 生成的 sourceMap 包含行映射(无列映射),并且包含了 loader 的 sourceMap ,使你能够 debug 到像.jsx
这样的源文件。
1.3 最佳实践
1.3.1 开发环境
-
要求:构建和重建速度快 (
eval
),能映射到原始源代码 (module
),且由于代码未压缩,列信息通常不是必须的 (cheap
)。 -
推荐配置:
perldevtool: 'eval-cheap-module-source-map' // Webpack 4: cheap-module-eval-source-map
-
eval
: 极快的重建速度 (缓存 sourceMap)。 -
cheap
: 只生成行映射,开销小。 -
module
: 包含 loader sourceMap,可追溯到 loader 处理前的源文件(如 JSX, TS)。 -
source-map
: 提供原始源代码。
-
1.3.2 生产环境
-
要求:不应在浏览器中直接暴露未编译的源代码 ,但需要 sourceMap 供错误收集工具(如 Sentry, Bugsnag)定位线上错误。
-
推荐配置:
vbnetdevtool: 'hidden-source-map'
-
source-map
: 生成完整的、高质量的 sourceMap 文件 (.js.map
)。 -
hidden
: 关键点! 不在打包后的 JS 文件 (bundle.js
) 末尾添加//# sourceMappingURL=bundle.js.map
注释。浏览器不会自动请求加载这个 .map 文件,用户无法通过开发者工具直接看到未编译的源码。 -
使用方式: 将生成的
.map
文件上传到错误监控服务。当线上代码报错时,该服务能利用对应的.map
文件将错误堆栈还原到源代码位置。
-