为了提升性能,通常我们会把源码压缩混淆后再发布到服务器上。
当线上出现问题时我们很难根据混淆后的代码去具体定位问题出现在哪。
Source Map 的出现正是为了解决这个难题,通过在压缩后的代码中加入如下注释:
// 注意此处的 sourceMappingURL 支持 http uri 以及 data uri 俩种形式
//# sourceMappingURL=/path/to/script.js.map
并在压缩混淆同时生成相应的 map 文件:
{
version: 3,
file: "script.js.map",
sources: [
"a.js",
"b.js",
"c.js"
], // 所有源文件的路径
sourceRoot: "/",
names: ["foo", "bar", "func"], // 所有源文件中出现的变量名 函数名
// 关键所在 具体原理就不管了 有点复杂 大致是通过 Base64-VQL 编码做映射
mappings: "AABASD,ASDFDSA,OAAOC,OAAO..."
}
这样浏览器就可以反向定位到错误具体出现在源码中的哪个文件的哪一行中
浏览器默认只会在打开开发者工具时才去请求 .map 文件,所以在 network 中看不到记录。
很不幸,答案是会的。更不幸的是,通过 .map 文件以及压缩后的代码可以反向生成源代码。
这意味着在公开的生产环境下我们不应该去使用 Source Map,因为这样相当于把整个 App 的源码暴露在外,是一种很危险的行为。
建议在类似预发环境(也就是与正式环境相同但是是私有的环境)下来利用 Source Map 进行 Debug。
Ps: 还可以通过服务器端的配置来禁止普通用户下载 .map 文件,这样就可以安全的把 .map 文件也放到正式环境上
开发环境我们通常不会采用混淆代码,对于简单的 Javascript 应用可能意义并不大。
但当我们在使用 React 或者 Vue 时,Source Map 可以将 Webpack 打包后的文件直接映射为源代码中的 .jsx/.vue 文件。而不利用 Source Map 我们就只能去 Debug 编译过后的文件。所以即使在开发环境下,Source Map 也是能给开发者带来很大帮助的。
Webpack 中可以通过这项配置来决定具体使用何种 Source Map,默认值为 false
也就是不启用 Source Map。
从方便 Debug 的角度从差到好排列,Webpack 一共提供了如下几种形式的 Source Map
关于 Devtool 的配置大致由如下几种关键字组合而来,每个关键字代表着不同特性
就目前来说,个人感觉在开发环境下设为 cheap-module-eval-source-map
,可以获得较好的 Debug 体验,以及较快的编译速度。
在预发/正式环境下设为 source-map
可以获得最完整的映射。
Ps: Webpack V4 中,当 mode 设为 'production' 时,默认使用的 uglifyjs-webpack-plugin
会默认设置 sourceMap: true
。当我们手动去新配置 uglifyjs-webpack-plugin
时会覆盖掉默认配置,所以要注意像如下配置一样加上 sourceMap: true
否则 SourceMap 会不生效。
// webpack.prod.config.js
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
module.exports = {
// ...
mode: 'production',
optimization: {
minimizer: [
new UglifyJsPlugin({
// ...
sourceMap: true // 注意这里!!!!!!
// ...
})
]
}
// ...
}