26种source-map看花了眼?别急,理解这几个全弄懂
上一篇 webpack处理模块化源码 的文章中提到了 "source map",这一篇来详细说说。
有什么作用
source map 用于映射编译后的代码与源码,这样如果编译后的代码出错了,可以很快速的定位到源文件的位置。
我们在 format.js 文件中打印一个不存在的 hello 变量, 当没有 source map 的时候,没有办法看到报错内容在源码的哪个位置。
生产环境提示报错是在编译后的 bundle.js 文件,点击该文件后,只能看到压缩和丑化之后的代码。

开发环境中会告知报错文件路径在 src/utils/format.js 中,点击 bundle.js 文件看到的代码也是经过编译的,和源码仍有些出入。

当设置了 source map 之后,源代码的目录结构、报错内容在哪个源文件、哪一行、列都能够清晰的看到。

这样可以快速的定位问题并进行代码修复。
如何使用
在配置文件 webpack.config.js 中,mode 字段用于定义模式,默认生产模式 "production",这里设置为开发模式便于调试,"dev-tool" 用于设置 source map,为了能看到 source map 定位到行与列的区别,增加 babel-loader。
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
devtool: "inline-source-map",
output: {
filename: "./bundle.js",
path: path.resolve(__dirname, "./dist"),
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
],
},
],
},
};
source map 有26种值可以设置,performance 表示构建速度,production 表示是否建议在"生产环境"使用,建议 source map 仅在开发及测试中使用,因为在生产中暴露源码是非常不安全的。

但这26种 source map 是有规律可循的,弄懂几种类型就可以全部理解。
source map 文件
当 devtool 设置为 source-map 时,webpack 会生成一个 source map 文件,并在打包后的 bundle.js 文件最后添加一行注释,指向 source map 文件。

source map文件中有这些字段用于记录编译后代码与源码的映射关系
- version:版本,第一个版本的 source map 文件大小是源文件的 10 倍左右,第二版减少了 50%,第三版又减少了 50%,现在是第三版。
- file:编译后的文件名,用于浏览器加载的
- mappings:用来保存和源文件的映射信息(比如行、列位置信息、变量等)
- sources:转换前的源文件、打包所用webpack代码
- sourceContent:转换前的具体代码信息(与sources是对应的关系)
- names:转换前的变量和属性名称
- sourceRoot:所有sources相对的根目录

以上是生成 source map 文件时的标准版本,除了某些不生成 source map 文件的配置,其它都是以类似这种方式来设置映射关系的。
不生成 source map 文件
也有可能存在不需要 source map 文件的情况,有两种方式来配置 devtool,使之不不生成 source map 文件。
- false:不使用 source map
- none:mode 为 production 的默认值(没有定义 devtool 时)
这两种方式不会生成 bundle.js.map 文件,也不会在 bundle.js 引入 bundle.js.map 。
内联 source-map
除了直接生成 source map 文件,还可以将 source map 内容直接内联到编译后的 bundle.js 中,有三种方式来配置 devtool。
- eval:development 模式下的默认值(没有定义 devtool 时),通过 eval 函数来执行文件内容,并在最后增加指向该内容所在的源文件地址
- eval-source-map:生成的 source map 以 base64 编码的形式添加到 eval 函数中
- inline-source-map:生成的 source map 以 base64 编码放置在打包后文件的最后面
eval
当 devtool 设置为 eval 时,在编译的 bundle.js 文件中,使用 eval 执行文件内容,并通过 //# sourceURL= 指向源文件地址。

此时可以获取到报错的文件、行、列,但看到的代码与源码会有一点不同,增加了 webpack 处理的部分。

eval-source-map
当 devtool 设置为 eval-source-map 时,文件内容通过 eval 函数执行,source map 通过base64编码后添加到了eval函数中。

此时通过控制台可以看到具体源代码,报错提醒具体到行与列。

inline-source-map
当 devtool 设置为 inline-source-map 时,source map 通过base64编码后添加到了文件最末尾处。

此时通过控制台可以看到具体源代码,报错提醒也具体到行与列。

因为 source map 会占据较大空间,将 source map 内联到 bundle.js 文件中,会使打包后文件体积变大。
报错精确到行
以上的报错信息都是精确到"列"的,提示具体哪个字段报错,而精确到"行"的话,只会告知这一行中有错误。

只精确到行,编译速度会稍快一点,有两种方式设置 devtool,这两种文件都会生成 source map 文件,也就是 bunlde.js.map。
- cheap-source-map:只精确到行,对于有loader的情况,会不够准确。
- cheap-module-source-map:只精确到行,可以很好的处理有loader的情况。
为了方便演示,将普通函数改成箭头函数。
可以看到,两者都是精确到"列"的,"cheap-source-map" 定位到的代码和实际的源码有些出入,并且行列顺序也有点不同,但"cheap-module-source-map" 就与源码完全一致。

不显示源码
有没有方法既生成 sourcemap,又不会显示源代码呢?webpack 也提供了两种 devtool 的配置。
- hidden-source-map:与 devtool 定义成 source-map 一样都会生成 source map 文件,只是在打包后文件 bundle.js 中,没有对 source-map 的引用,如果手动加入,也是会生效的。
- nosources-source-map:会生成source map,但是生成的source map只有错误信息的提示,不会生成源代码文件, 会在控制台告诉错误的内容及文件,但是点击文件名的时候看不到源码
hidden-source-map
没有引入 source map,在报错信息处也就不会指向源码

nosources-source-map
此时会生成 source map 文件,打包后的 bundle.js 也会引入map文件,也可以看到报错内容所在文件,但无法获取源码。

组合规则
通过表格总结一下上面所提到的 source map

理解这些 source map 之后,剩余的组合也可以推导出,比如
- eval-cheap-module-source-map:不会生成 source map 文件,而是将 source map 以 base64 编码的形式添加到eval函数中,不会精确到列,只精确到列,且
存在loader时,可准确定位源码 - inline-nosources-source-map:不生成 source map 文件,将 source map 以base 64 编码的形式添加到编译后文件的底部,不会展示源码。
但以上这些也不能随意的组合,要遵循以下规则
- inline-|hidden-|eval:三个值时三选一,可不选
- nosources:可选值
- cheap可选值,并且可以跟随module的值
总结起来如下
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
在开发、测试、生产阶段,也有一些推荐
- 开发阶段:source-map(vue脚手架默认值)或者 cheap-module-source-map(react脚手架默认值)
- 测试阶段:source-map 或者 cheap-module-source-map,可快速定位问题
- 发布阶段:false、none(即不写)
source map 可以帮助我们在开发、测试阶段更好的定位问题,正确的使用能够提升效率。
以上就是关于 source map 的详细介绍,更多有关webpack的内容可以参考我其它的博文,持续更新中~
26种source-map看花了眼?别急,理解这几个全弄懂的更多相关文章
- source map 的原理探究
线上产品代码一般是编译过的,前端的编译处理过程包括不限于 转译器/Transpilers (Babel, Traceur) 编译器/Compilers (Closure Compiler, TypeS ...
- 源映射(Source Map)详解
一.什么是源映射 为了提高性能,很多站点都会先压缩 JavaScript 代码然后上线, 但如果代码运行时出现错误,浏览器只会显示在已压缩的代码中的位置,很难确定真正的源码错误位置. 这时源映射就登场 ...
- JavaScript Source Map 详解
源码地址: http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html 上周,jQuery 1.9发布. 这是2.0版之前的最后 ...
- javascript source map 的使用
之前发现VS.NET会为压缩的js文添加一个与文件名同名的.map文件,一直没有搞懂他是用来做什么的,直接删除掉运行时浏览器又会报错,后来google了一直才真正搞懂了这个小小的map文件背后的巨大意 ...
- 【转】webpack中关于source map的配置
Webpack中sourcemap的配置 sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术.尤其是如今前端开发中大部分的代码都经过编译,打包等工程化转换 ...
- Javascript 如何生成Less和Js的Source map
为什么有Source map CSS和JS脚本正变得越来越复杂,为了解决网络瓶颈,大部分源代码都需要经过编译.合并.压缩才能运用到实际环境中.为了减少网络资源占用,源码一般都会经过以下方式处理: 使用 ...
- Fundebug微信小程序BUG监控服务支持Source Map
摘要: 自动还原真实出错位置,快速修复BUG. Source Map功能 微信小程序的Source Map功能目前只在 iOS 6.7.2 及以上版本支持. 微信小程序在打包时,会将所有 js 代码打 ...
- Source Map调试压缩后代码
在前端开发过程中,无论是样式还是脚本,运行时的文件可能是压缩后的,那这个时候调试起来就很麻烦. 这个时候,可以使用Source Map文件来优化调试,Source Map是一个信息文件,里面储存着原代 ...
- java source map
Chrome 更新后出现了 jquery.min.map 404 (Not Found) 的信息 这个到底是什么东西?查询了一下,得到了以下资料 JQuery 官方解释 摘录一下內容 从 jQuer ...
- Source Map入门教程
部署前端之前,开发者通常会对代码进行打包压缩,这样可以减少代码大小,从而有效提高访问速度.然而,压缩代码的报错信息是很难Debug的,因为它的行号和列号已经失真.这时就需要Source Map来还原真 ...
随机推荐
- 苦苦搞了半个通宵才搞定的直接使用Sliverlight将文件PUT到阿里云OSS
为了公司的项目,小的我各种折腾啊,不过高兴的是实现了Silverlight直接提交至阿里云OSS的文件上传,文件上传再也不用通过服务器中转了. 研究SDK发现还有个Node-oss.js,但还没进行测 ...
- TextArea设置MaxLength的代码(未测试在不同浏览器下的兼容性)
function SetTextAreaMaxLength(controlId,length) { // JScript File for TextArea // Keep user from ent ...
- Golang for循环遍历小坑
一.for循环 循环:让程序多次执行相同的代码块for循环是Go语言中唯一一个循环结构for循环经典语法先执行表达式1执行表达式2判断是否成立,如果成立执行循环体循环体执行完成后,执行表达式3再次执行 ...
- selenium文件上传和弹框处理
文件上传 input 标签可以直接使用send_keys(文件地址)上传文件 用法: el = driver.find_element_by_id('上传按钮id') el.send_keys(&qu ...
- proto中service 作用的理解
转载请注明出处: 在 proto 文件中,service 用于定义一组 RPC 方法,在服务端实现这些方法,并在客户端调用这些方法进行远程过程调用. service 的定义方式如下: service ...
- flutter apk启动闪退问题
今发布一个flutter apk 安装后启动时老是闪退,经过一遍又一遍查找,发现是指定了so的问题 看多次点击启动 一.比对打包后的apk 在出现该问题后也搜索了不少资料,参考过 https://bl ...
- pycham2022最新破解
pycharm破解方式常见有2种: 1 .破解插件+激活码,一般激活到2099年或者2089年! 2 .破解插件.该破解插件可以无限重置30天,也就是pycharm永远有30天的试用期,永不到期! ...
- 【RocketMQ】NameServer总结
NameServer是一个注册中心,提供服务注册和服务发现的功能.NameServer可以集群部署,集群中每个节点都是对等的关系(没有像ZooKeeper那样在集群中选举出一个Master节点),节点 ...
- 在R中子集化数据框的5种方法
由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. 通常,我们在使用大型数据集时,只会对其中的一小部分感兴趣,用以进行特定分析. 那么,我们应该如 ...
- python3使用pjsua进行呼叫测试
环境:CentOS 7.6_x64 Python版本 :3.9.12 pjsip版本:2.13 之前写过一篇CentOS7环境编译python3.9版本pjsua的文章: https://w ...