我们项目的代码在经过编译打包后,会将开发时多个文件的代码合并到同一份文件中,而且还会经过各种压缩,合并,代码丑化等等操作,转换完最终生成的代码才会用于线上环境,所以我们线上实际运行的代码跟我们开发时的代码是有非常大的不同,如果此时出现了bug,那么我们只能定位到转换后代码的位置,但此时的代码已经面目全非了
转换后的代码类似下面这样
虽然这种代码对计算机非常友好,但是我们debug将会变得很困难,这时候就需要sourcemap了
简单来说,Sourcemap 就是一个信息文件,它里面存储着代码转换前后的对应位置信息,也就是转换压缩后的代码所对应的转换前的源代码位置,是源代码和生产代码的映射, Sourcemap 解决了在打包过程中,代码经过压缩,去空格以及 babel 编译转化后,由于代码之间差异性过大,debug 困难的问题
大家的项目在开发完进行build后,在打包文件夹里除了有js,css,图片等资源,一定还见过 .js.map文件,这种就是sourcemap文件
点开一个打包后的js文件,拉到最后一行,可以看到 //# sourceMappingURL=main.js.map
有了这行,就可以启用sourcemap,这个sourceMappingURL就是标记了该文件的sourcemap的地址,这个sourcemap文件可以放在本地,也可以放在网络上
再点开一个 .js.map 文件看看,有一堆类似乱码的东西,后面看一个简单一点的
生成的方法有很多,而且有很多前端的工具都支持,如webpack,uglifyjs,gulp等,这里就不详细讲述了,对怎么生成sourcemap感兴趣可以看这个文章
https://code.tutsplus.com/tutorials/source-maps-101--net-29173
我们看一个简单一点的代码
const value = 123;
console.log(value);
用webpack打包后的代码
console.log(123);
//# sourceMappingURL=bundle.js.map
生成的sourcemap文件
{
version : 3,
file : bundle.js ,
mappings : AACAA,QAAQC,IADM ,
sources : [
webpack://studysourcemap/./test.js
],
sourcesContent : [
const value = 123;\nconsole.log(value);
],
names : [
console ,
log
],
sourceRoot :
}
每个属性的含义如下
version:遵循的是哪一个sourcemap版本的规范(下面会浅提一下)
sources:转换前的源文件url数组(数组是因为存在多个文件合并的情况)
names:在mappings中引用的标识符数组(可以理解为转换前代码的所有变量名和属性名)
sourceRoot:源文件的根路径
sourcesContent:转换前源文件的原始内容,也是一个数组
mappings:记录源码和编译后代码的位置信息的base64 VLQ 字符串,是最重要的内容
file:生成的与该sourcemap文件关联的文件名,也就是打包编译后的文件名
关于sourcemap的版本
2009年,google介绍他的一个编译器Cloure Compiler时,也顺便推出了一个调试插件Closure Inspector,可以方便调试编译后的代码,这个就是 sourcemap 的雏形
2010年,Closure Compiler Source Map 2.0中,共同制定了一些标准,已决定使用base64编码,但是生成的map文件要比现在大很多
2011年,第三代出炉, Source Map Revision 3 Proposal,也就是我们现在用的 sourcemap 的版本,这也就是为什么我们上面map文件的 version=3 了,这一版对算法进行了优化,大大缩小了map文件的体积
第一版生成的map文件大概有转化后文件的10倍大,第二版则将体积减少了20%~30%,第三版又在v2的基础上体积减少了一半
正是因为有了第三代 Source Map Revision 3 Proposal 这个标准,不同的打包工具和浏览器才能使用sourcemap,github上的一个根据这个标准生成sourcemap的库 https://github.com/mozilla/source-map
这里主要关注mappings和names属性,mappings属性是一个很长的字符串,它分成三个部分
1 . 分号(;),表示行对应,生成的文件的每一行用分号(;)分隔,一个分号代表转换后源码的一行
2 . 逗号(,),位置对应,每一段用逗号(,)分隔,一个逗号对应转换后源码的一个位置
3 . 英文字母,每一段由1,4或5块可变长度的字段组成,记录原始代码的位置信息
举一个简单的例子,假设有如下的mappings属性
mappings : AACAA;QAAQC,IADM ,
有一个分号,说明有两行代码,分号前 AACAA
是第一行,后面 QAAQC,IADM
是第二行
第二行有一个逗号,说明这一行分为两段,QAAQC
和 IADM
分号跟逗号大家应该都没什么疑问,主要就是英文字母这一块的意义位置对应的原理
每一段最多有5个部分
第一部分,表示这个位置在(转换后的代码的)的第几列
第二部分,表示这个位置属于sources属性中的哪一个文件
第三部分,表示这个位置属于转换前代码的第几行
第四部分,表示这个位置属于转换前代码的第几列
第五部分,表示这个位置属于names属性中的哪一个变量
那么这五个部分是怎么来的,我们一步一步来看
假设文件a.js有一行代码 I Love SourceMap
,最终打包后输出的文件为bundle.js,内容为 Javascript is awesome
,如下
image.png
那么怎么表示映射关系
以 Love 为例,它原始的位置为(0,2),输出后是awesome,位置为(0,14),那么我们可以这样来映射
image.png
像这样写成一种固定的格式,里面包含了原始位置和输出后的位置,单词,同时还有原始文件名,因为可能把多个文件进行处理输出,如果不写文件名,就不知道输入位置来自哪个文件
输出后的单词 | 映射关系 |
---|---|
Javascript | 0 0 a.js 0 7 SourceMap |
is | 0 11 a.js 0 0 I |
awesome0 | 14 a.js 0 2 Love |
我们可以优化一下,把a.js和最后面的单词提出来各放到一个数组里,用sources记录所有的原始文件名,names记录原始文件中的所有单词,然后用下标表示他们,以Love为例,就变成
image.png
很多时候,我们输出的文件其实是只有一行的,所以可以把输出文件的行号省略掉,就变成
image.png
考虑到,如果文件特别大的话,那么行列的数值可能会特别大,所以可以考虑用相对位置来代替绝对位置来表示,只用绝对位置表示第一个单词的位置,后面的都使用相对前一个单词的位置
image.png
原始单词 | 输入位置 | 输出单词 | 输出位置 | 映射 |
---|---|---|---|---|
I | (0,0) 绝对位置 | is | (0,11)绝对位置 | 11 0 0 0 0 |
Love | (0,2) 相对I的位置 | awesome | (0,3)相对is的位置 | 3 0 0 2 1 |
SourceMap | (0,5) 相对Love的位置 | Javascript | (0,-14) 相对awesome的位置 | -14 0 0 5 2 |
所以我们现在可以得到这么一个初步的map文件
{
names: ['I', 'Love', 'SourceMap'],
sources: ['a.js'],
mappings: [11|0|0|0|0, 3|0|0|2|1, -14|0|0|5|2]
}
但是mappings这里十分难看,而且还需要用|
来分隔,多占一个位置,用 vlq 编码就可以解决分隔数字的问题,他的核心思路是在连续的数字上做标记,我们先来理解一下,拿上面 mappings 属性的第一个为例,去掉|
,然后在连续的字符上加上一个标记
110000
从左往右开始读取,数字1有标记,说明还有连续,再取下一个,是1,这个1没被标记,第一个数结束,所以第一个数是11
继续往下,0没被标记,说明是一个完整的数字,第二个数就是0
依此类推。。。
最终就能得到11,0,0,0,0
而 vlq 利用6位二进制数进行存储,其中第一位就表示是否连续的标识位,最后一位表示正数还是负数(0正数,1负数) ,中间只有4位,因此一个单元表示的范围为[-15,15],如果超过了就要用连续标识位了
看几个例子来理解,每一步的变化我都用不同颜色标记了
image.png
第三步(按...5554分割),最右边4位是因为他还需要额外多表示一位符号位,其余的都可以用5位来表示数值
倒数第二步倒顺序,是因为VLQ表示数据字节组的顺序是倒过来的
最终我们可以得到他们的 vlq 编码
十进制数值 | vlq编码 | vlq编码每一段对应的数值 |
---|---|---|
5 | 001010 | 10 |
-19 | 100111 000001 | 39和1 |
然后再把它转成base64编码,可以查下面这张表
就可以得到5和-19的base64 vlq编码了,因为5的 vlq 编码数值是10,所以查上表可得到K,同理-19可以得到n和B,最终能得到5和-19的 base64 vlq 编码分别是K和nB
这里有一个网站可以自己转换验证一下https://www.murzwin.com/base64vlq.html
然后我们回过头为我们最开始那个简单的js文件手动生成一下map文件来验证一下
const value = 123;
console.log(value);
打包后的代码
console.log(123);
//# sourceMappingURL=bundle.js.map
sources和names是可以先确定好的
{
sources : [ a.js ],
names : [ console , log ],
}
再得到 base64 vlq 编码
原始位置 | 输出位置 | sources索引 | names索引 | 映射 | 每一部分的vlq编码 | base64 vlq编码 | |
---|---|---|---|---|---|---|---|
console | (1,0)绝对 | (0,0)绝对 | 0 | 0 | 0 | 0 | 1 |
log | (0,8)相对 | (0,8)相对 | 0 | 1 | 8 | 0 | 0 |
123 | (-1,6)相对 | (0,4)相对 | 0 | 无 | 4 | 0 | -1 |
所以我们可以得到最终的map文件
{
sources : [ a.js ],
names : [ console , log ],
mappings : AACAA,QAAQC,IADM ,
// ...其他的
}
反过来也能根据sourcemap文件推出原始的位置,这里就不再演示了
映射转换过后的代码和源代码之间的关系
代码中引入 //# sourceMappingURL=xxx.js.map 启用
source Map 解决了源代码和运行代码不一致所产生的问题
不只是js文件有,css文件也有
核心原理是 base64 vlq 编码
https://juejin.cn/post/7023537118454480904
https://juejin.cn/post/6963076475020902436
https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.1ce2c87bpj24
https://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html
https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
http://www.qiutianaimeili.com/html/page/2019/05/89jrubx1soc.html
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/YVySzeCNpQpijwf8kwblFw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。