源映射(sourceMap)
什么是 SourceMap
在前端开发过程中,通常我们编写的源代码会经过多重处理(编译、封装、压缩...),最后形成产物代码。于是在浏览器中调试代码时, 我们往往会发现代码变得面目全非,因此,我们需要在调试时将产物显示成源代码的形式,这就是 SourceMap
的作用。
SourceMap
的基本原理是在编译处理的过程中,在生成产物代码的同时生成产物代码中被转换的部分与源代码中相应部分的映射关系表。 有这张映射表,我们就可以通过浏览器控制台的 Enable Javascript source map
实现调试时的显示与定位源代码功能。
提示
我们在控制台的网络面板通常看不到 SourceMap
文件的请求,其原因是出于安全考虑隐藏了 SourceMap
请求,需要通过 net-log
来查询
Webpack 中的 SourceMap
在 Webpack 中,通过设置 devtool 来选择 source map 的预设类型,文档中包含多种 source map
的预设,包含了eval
,cheap
,module
, inline
, hidden
、nosource
、source-map
等关键字的组合,如下:
// webpack/lib/WebpackOptionsApply.js:232
if (options.devtool) {
if (options.devtool.includes("source-map")) {
const hidden = options.devtool.includes("hidden");
const inline = options.devtool.includes("inline");
const evalWrapped = options.devtool.includes("eval");
const cheap = options.devtool.includes("cheap");
const moduleMaps = options.devtool.includes("module");
const noSources = options.devtool.includes("nosources");
const Plugin = evalWrapped
? require("./EvalSourceMapDevToolPlugin")
: require("./SourceMapDevToolPlugin");
new Plugin({
filename: inline ? null : options.output.sourceMapFilename,
moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
fallbackModuleFilenameTemplate:
options.output.devtoolFallbackModuleFilenameTemplate,
append: hidden ? false : undefined,
module: moduleMaps ? true : !cheap,
columns: !cheap,
noSources,
namespace: options.output.devtoolNamespace,
}).apply(compiler);
} else if (options.devtool.includes("eval")) {
const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
new EvalDevToolModulePlugin({
moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
namespace: options.output.devtoolNamespace,
}).apply(compiler);
}
}
根据上面的代码,我们可以看到根据不同规则,Webpack 是从三种插件中选择其一作为 source map
的生成插件。
EvalDevToolModulePlugin:模块代码后添加
sourceURL=webpack:///+模块路径
的形式,不生成独立的source map
文件,模块产物代码通过eval()
封装。EvalSourceMapDevToolPlugin:生成 base64 编码格式的
source map
并附加在产物代码的末尾,source map
后添加sourceURL=webpack:///+模块路径
,不单独生成文件,模块产物代码通过eval()
封装。SourceMapDevToolPlugin:生成单独的
.map
文件,产物代码不通过eval()
封装。
简单配置
// webpack.config.js
module.exports = {
// ...
devtool: "source-map",
// ...
};
提示
上面这种防止生成的 source map
是最完整的,但性能较差,适合在开发环境中使用。
在 DevTools 中启用 SourceMap
以 Microsoft Edge 为例:
在 Microsoft Edge 中右键单机网页,然后选择检查,或者按 F12、Ctrl+Shift+I(windows、Linux)、Command+Option+I(macOS) 。
在 DevTools 中,单击 自定义和控制 DevTools 按钮,然后选择 设置 中的 首选项 选项卡。
在 首选项 选项卡的 源代码 部分,确保勾选中 启用 JavaScript 源映射 和 **启用 CSS 源映射复选框。
启用从远程文件路径加载源映射
当源映射 URL 是远程文件路径时,DevTools 不会加载源映射,例如:当源映射 URL 以 file://
开头,并且目标文件不在当前设备上时。
在 DevTools 中,单击 自定义和控制 DevTools 按钮,然后选择 设置 中的 首选项 选项卡。
在 首选项 选项卡的 源代码 部分,确保勾选中 允许 DevTools 从远程文件路径加载资源,如源映射。出于安全原因,默认为禁用。) 复选框。
使用源映射调试
调试代码和启用源映射时,会在多个位置使用源映射:
在 控制台 工具中,从日志消息到源文件的链接将转到原始文件,而不是已编译的文件。
在 源代码 工具中单步执行代码时,原始文件将显示在左侧的 导航器 窗格中。打开原始文件时,会显示原始代码,可以在其中添加断点。