1.sourcemap的还还原认知与运用
2.vue反编译dist包到源码
3.弄懂 SourceMap,前端开发提效 100%
4.Source Map 原理及源码探索
5.source-map原理及应用
6.何为SourceMap?讲讲SourceMap食用姿势
sourcemap的原源认知与运用
在讨论sourcemap之前,我们首先需要了解编程语言的还还原编译过程。
编译是原源将编程语言转换为可执行代码的过程。然而,还还原可执行代码和源代码是原源大型网页布局源码完全不同的两种格式。如果在执行过程中出现错误,还还原很难定位源代码编写过程中出现的原源问题。因此,还还原现代编译器基本上都支持一种标准的原源可执行代码与源代码之间的映射,以特定格式将这种映射关系持久化存储到文件中。还还原当程序执行出现问题时,原源根据堆栈信息使用映射文件逆向还原到源代码,还还原可以清晰地、原源语义化地查找编写过程中的还还原错误。
在常见的C Family languages中,这种可执行代码和源码之间映射的格式已经是一种标准化的东西了,称为DWARF。尽管在每个厂商应用的平台上产生的文件格式不尽相同,但它们内里遵循的映射格式都遵循了DWARF调试标准。
回到Web前端领域讨论这个问题,类似地,我们有sourcemap这个东西。或者我们应该称它为sourcemap调试格式标准。因为目前我们对sourcemap的格式都遵循了一定的标准,但在它的用途上,却出现了千差万别。
本文中讨论sourcemap的格式组成是没有意义的,sourcemap的格式应当是一种持续发展的标准,每当标准更新,自然会有健壮的工具帮助解读。理解sourcemap的格式对它的应用不会有太明显的帮助。
按照我的理解,最早sourcemap是为了协助JavaScript代码混淆(或者压缩)而产生的。框架的作者为了缩小代码体积、避免生产环境的JavaScript代码能被轻松地阅读,使用压缩、混淆工具对源码进行了处理。如果产生了问题,有sourcemap还能轻松地还原代码。但当时的sourcemap并不是web标准之一,这为今日的web前端工程化体系埋下了隐患。
在上一节中提到,sourcemap是一种“可执行代码”和源码之间的映射关系,那么只要是产生编译的地方,就应该会有sourcemap产生。
首先想到了Babel这个工具,它是javascript 源码加密应用最广泛的JavaScript编译器,接下来我们尝试一个示例:
接着,我们安装babel,指定sourcemap参数为inline,并对其进行转换,得到:
可以看到,转换后的代码和源码产生了很大的区别,并且sourcemap以注释的形式紧跟在可执行代码尾部,它的链接指向了一个data URL。
这么看就很容易了解到,sourcemap是一个基于之前的web标准拓展的功能,它只需要以固定的注释格式跟随在一个脚本文件的末尾即可。那么不同的浏览器厂商想要兼容这个标准,只需要加以识别这个格式即可。
但上文可以看出,data URL加在注释中,任何外部人员都可以轻易获得。因此在做代码转换时,可以将sourcemap生成到一个单独的文件中,一般是文件名加.map后缀,那么对应的sourcemap的地址也就变成:
sourcemap的这种设计方法并不是独一份的。例如在C Family Language的构建交付体系中,为了调试方便,对于测试环境交付的库、可执行代码,并不会将它们的"sourcemap"从可执行代码中分离出来。它们的执行环境和大部分JavaScript引擎一样,在调试断点或者Exception时,都能自动地载入"sourcemap"并且给出对应的源码栈信息。而在生产交付时,都会在构建时将"sourcemap"从库和可执行文件中提取出来单独保存。这样既减小了交付的产物体积,还能保证源码信息不被外部人员知晓。
既然sourcemap在逐渐地成为一个标准,那么自然就有配套的标准工具对这种格式进行解析。除了Chrome devtools自带的以外,还可以使用常见的库,接下来我们使用mozilla的source-map库,对刚才的代码进行一些还原的操作。
这是断点调试常见经常会碰到的场景,比如某个exception发生在了我们刚才代码的line 9; column 2; 即console.log的位置。那么我们可以这么做:
通过载入map文件,然后查找line 9 column 2对应的源代码位置可得:
然后我们去index.ts中的3行2列,正好是ts文件中的console.log
可以看到,sourcemap不仅记录了代码行列数,还记录了源文件的位置,那么不用翻sourcemap的manual也能说明,sourcemap也像其他编译系统一样,筹码去向源码支持多个文件、库的代码映射的集成合并。这对于大型工程的构建十分有用,大型工程往往由数以千计万计的库和代码文件组成,在这种复杂的构建中,我们往往只想要获得有限几个产物。除了可执行代码,sourcemap的统一产出也有利于我们方便地追溯生产环境的问题。
mozilla的source-map标准库不止有查找映射位置的这个作用,更能直接还原代码。我们可以直接载入一个sourcemap文件,然后查看它对应了那些源代码文件,然后根据这些文件进行逐个还原内容:
由于我们只有一个,得到的输出是
在实际开发场景中,我们碰到的sourcemap运用比上面提到的情况复杂得多,但是问题又没有办法一一枚举,所以这里讨论一些常见的例子
前面就见过两种形式:dataURL放在JavaScript文件结尾的、和独立写入文件的。他们的形式是显而易见的,并且特点也能清楚地看出来。前者内联,增大了体积,但是降低了使用的门槛。后者独立,可以隐藏保存起来,非必要时不使用。
但在webpack这种打包构建工具中,对sourcemap做了更多更详细的定义,其基本分类的依据也遵循以下几个维度:
具体的规则可以翻阅webpack对应的文档,光靠脑子记是没办法的。
对库、预编译/转换的sourcemap处理
日常开发中,使用库或者预编译的组件是很常见的事,例如:
预编译文件的处理
像这些场景对工程的构建提出了比较多的要求。这里就针对常用的webpack做一个处理的展示,还是以前面的工程为例,我们的Typescript库导出了函数a,然后我们直接引用dist/index.js(而非src/index.ts)
然后我们通过webpack打包并且导出它的sourcemap
最后我们得到了./dist/demo.dist.js.map(名字有点诡异哈)
然后我们再通过刚才写的sourcemap工具进行还原看看:
可以看到,webpack默认情况下可以识别预编译的文件它的sourcemap,并且进行合理的目录转换,保证指向正确
那么我们如果删除预编译文件的sourcemap呢?我对a函数的库重新编译了一遍,并且不导出任何sourcemap,结果对引入的a函数库的文件还原就变成了
库的处理
如果a函数是从npm库引用的呢?我尝试了下把函数a放到了库中,然后将源码引用改成了
结果虽然node_modules中带了sourcemap,但是还原后并不是原本的ts代码
这时候需要对webpack进行配置,增加source-map-loader作为预处理,且不能排除node_modules目录:
然后再进行打包编译出来的adb源码 windowsmap我们对其进行还原发现:
webpack成功帮我们提取了node_modules库中的sourcemap
本文主要阐述了sourcemap的基本知识,包含了几个方面:
vue反编译dist包到源码
在处理老项目源码缺失问题时,可以通过反编译dist包获取部分源码。以下是具体步骤:
当面临源码缺失的挑战时,可以通过反编译dist包来补全代码。首先,需要在管理员权限下启动命令行工具(cmd)。 在dist包的static/js目录下,找到如0.7ab7dffccc1ca.js.map这样的编译映射文件。以这个文件为例,执行反编译操作,可以全局安装reverse-sourcemap插件,然后执行命令:reverse-sourcemap --output-dir source 0.7ab7dffccc1ca.js.map 为了自动化这个过程,可以编写脚本利用Node.js的child_process模块。通过fs模块遍历文件夹,找出所有.map文件,将其存入数组,然后使用递归调用reverse-sourcemap命令。以下是关键步骤的脚本编写方法:创建一个函数,用于执行反编译命令(reverse-sourcemap)。
使用fs模块读取文件并使用正则表达式匹配.map文件。
遍历匹配到的.map文件,并调用执行函数。
通过这些步骤,你将能够从dist包反编译出部分源码,尽管可能只限于Vue文件,但这已能满足基本需求。最终,你会看到source目录下反编译得到的源码文件。弄懂 SourceMap,前端开发提效 %
深入理解 Source Map,提升前端开发效率
一、Source Map 的基本概念
Source Map 是一个 JSON 描述文件,用于记录代码打包转换后的映射关系,帮助开发者在遇到线上代码问题时快速定位到原始代码位置。
二、Source Map 的作用
在复杂代码环境下,转换后的代码与原始代码不一致,使得调试变得困难。Source Map 提供了从转换后的代码到原始代码的映射关系,帮助开发者轻松定位错误位置。
三、如何生成 Source Map
主流前端工具如 UglifyJS、Grunt、Gulp、SystemJS 和 Webpack 都支持生成 Source Map。通过配置工具或插件,即可实现代码打包时自动生成 Source Map 文件。python import 源码
四、使用 Source Map
生成 Source Map 后,通过浏览器开发者工具开启相关功能,即可查看到真实源代码位置,辅助调试过程。
五、Source Map 的工作原理
Source Map 通过注释或响应头指示源代码位置,打包后的文件在浏览器中解析时,根据 Source Map 文件定位原始代码。Mappings 字段定义了代码位置的映射关系。
六、Webpack 中的 Source Map
Webpack 配置 devtool 属性即可使用 Source Map。不同类型如 source-map、inline-source-map 等在开发和生产环境中提供了不同的调试体验。
七、总结
Source Map 是前端开发中不可或缺的工具,通过它,开发者可以轻松定位错误,提高代码调试效率。掌握 Source Map 的应用,能够帮助开发者更好地解决实际开发过程中的问题。
Source Map 原理及源码探索
前端开发中,代码经过转换后发布到线上时,通常会遇到压缩或混淆的问题,这虽然减小了代码体积,降低了网络开销,但同时也给开发者调试代码带来了不便。为解决这一难题,Source Map应运而生,旨在提供一种方式,使得开发者能够在压缩或混淆后的代码上进行源代码级别的调试。
从Source Map的诞生和演变可以看出,它经历了几个版本的更新,以适应不同场景的需求。最初由Joseph Schorr创建的v1版,旨在让闭包检查器在优化JS代码时进行源代码级别的调试。随着项目规模的扩大,v1版的映射结果变得异常冗长。v2版对此进行了优化,增加了映射文件的灵活性和简便性,减少了映射文件的总体大小,相较于v1版减少了约%至%。然而,v2版仍存在一些问题,因此v3版应运而生,进一步缩减了映射文件的大小,相较于v2版减少了大约%。
在v3规范格式中,mappings数据遵循一定的规则,其中VLQ(Variable-Length Quantized)编码起到了关键作用。VLQ编码的原理基于简化数字表示,通过使用特殊字符分隔数字,减少不必要的字符,实现数据的紧凑存储。VLQ背后的想法很简单,即根据数字位数调整分隔符,当数字位数减少时,可以省去分隔符,从而减少存储空间。
VLQ的进制表示和2进制表示展示了其灵活性。进制表示时,通过在数字之间插入分隔符来区分不同数字。二进制表示中,使用由6位组成的二进制组来表示数值,其中第一位作为连续标记位,确定后续字节组是否需要连续表示,最后一位作为符号标记位,指示数值的正负。这种编码方式允许更高效地表示数值,特别是当数值位数减少时,可以显著节省空间。
在实际应用中,通过Base编码,VLQ编码的数字可以进一步压缩,使得映射文件更加紧凑。在生成映射文件时,通常需要考虑输入文件的行号,但随着内容的增多,映射编码会快速增多,占用大量空间。为解决这一问题,可以采取以下改进措施:
1. 省略输出文件的行号,使用“;”换行来节省空间。
2. 名称和输入文件列表按索引引用,提取出两个索引表,减少重复记录。
3. 使用相对偏移,而不是绝对偏移,减少映射编码的长度,特别是在处理大型文件时。
4. 通过VLQ+Base编码进一步压缩映射数据。
5. 省略不必要的字段,优化映射长度,使其更紧凑。
在源码探索部分,以uglify-js为例,它利用source-map库生成SourceMap。生成过程涉及source-map库中的SourceMapGenerator类,通过调用generator.toJSON()方法输出SourceMap。在实际应用中,通过了解这些源码,开发者可以更深入地理解Source Map的生成机制,并在需要时进行定制或优化。
最后,以JS压缩为例,通过应用上述改进措施,可以生成紧凑的SourceMap文件。在实际环境中,使用命令行工具验证生成的SourceMap文件,可以确保其正确性和一致性。
在前端开发中,合理利用Source Map可以提高调试效率,同时优化代码发布流程。通过源码探索,开发者能够更好地理解Source Map的底层机制,为项目调试和维护提供强有力的支持。
source-map原理及应用
源码映射(Source Map)是存放源代码与编译代码对应位置映射信息的文件,帮助开发者在生产环境中精确定位问题。当开启source-map编译后,构建工具生成的sourcemap文件可以在特定事件触发时,自动加载并重构代码回原始形态。
sourcemap文件由多个部分组成,V3版本的文件包括文件名、源码根目录、变量名、源码文件、源码内容以及位置映射。映射数据使用VLQ编码进行压缩,以减小文件体积。
当页面运行时加载编译构建产物,特定事件如打开Chrome Devtool面板时,系统会根据源码映射加载相应Map文件,重构代码至原始形态。
sourcemap文件内容包括文件名、源码根目录、变量名、源码文件、源码内容以及位置映射。位置映射由VLQ编码表示,用于还原编译产物到源码位置。
Webpack提供多种设置源码映射的方式,包括通过配置项设置规则短语或使用插件深度定制生成逻辑。这些设置符合特定正则表达式,如source-map、eval-source-map、cheap-source-map等,分别对应不同的生成策略。
cheap-source-map和module-cheap-source-map在cheap场景下生效,允许根据loader联调处理结果或原始代码作为source。nosources-source-map则不包含源码内容,而inline-source-map将sourcemap编码为Base DataURL,直接追加到产物文件中。
通常,产物中需要携带`# sourceMappingURL=`指令以正确找到sourcemap文件。当使用hidden-source-map时,编译产物中不包含此指令。需要时,可手动加载sourcemap文件。
通过sourcemap文件,开发者可以上传至远端,根据报错信息定位源码出错位置,实现高效问题定位与调试。
何为SourceMap?讲讲SourceMap食用姿势
在前端开发中,我们经常面临代码错误定位的问题。尽管打包后的代码难以直接阅读,但神奇的是,我们仍能在控制台找到问题的根源。这一切得益于幕后英雄——source map。它是一种机制,帮助我们在编译和压缩后的代码中追溯到原始代码的位置。
source map的工作原理是通过生成一份映射文件,将编译后的代码与原始代码建立起对应关系。举个例子,当你使用babel编译代码时,会同时生成一份包含原始信息的.sourcemap文件。这个文件中,如names数组、mappings字段等属性记录了代码转换过程中的详细映射,包括原始代码的行号和字符位置。
生成source map的过程涉及对原始代码和编译后的代码进行一一对应,记录下每个编译后的代码片段在原始代码中的位置。通过一系列的优化,如省去行号、使用分隔符和VLQ编码等技术,使得这个映射文件尽可能地紧凑。
在webpack等打包工具中,devtool属性决定如何生成和处理source map。常见的模式有source-map、inline-source-map、eval-source-map等,各有优缺点。开发环境中推荐使用eval-source-map,它提供了原始代码的可见性;生产环境则倾向于hidden-source-map,以保护源代码隐私。
source map的精度有时可能会受到影响,这可能是由于打包过程中的配置问题或者在某些模式下牺牲了一些信息。一旦遇到定位不准,尝试调整devtool模式或检查打包过程中的代码转换设置通常能解决问题。
SourceMap-使用教程
源码映射(SourceMap)是一个存储源代码与编译代码对应位置映射的信息文件,主要在前端开发中解决以下三个方面的问题:
a. 代码压缩混淆后
b. 利用sass、typescript等其他语言编译成css或JS后
c. 利用webpack等打包工具进行多文件合并后
使用源码映射可以在控制台中将编译后的代码转换为源代码,方便进行调试。
源码映射实际上是一个JSON键值对,使用VLQ编码与特定规则存储位置信息,原理了解具体实现即可,因为它是工具生成的文件,不需要手动编写。
在Chrome中启用源码映射功能,进入开发者模式设置,勾选允许JS和css源码映射。生成源码映射文件可以通过多种方法,如使用Google的Closure编译器、Gulp、Grunt等工具。在Gulp中,通过使用gulp-sourcemaps插件来生成源码映射文件。
在Gulp中使用源码映射文件,首先需要在文件中添加注释以指示源码映射文件的位置,当打开原文件时可以查看到该注释。使用源码映射文件时,需要在Chrome开发者模式下查看Sources中的文件,理解其三个感叹号代表的内容。
了解gulp-sourcemaps API可以进一步优化源码映射的使用,包括初始化、生成、源路径定义和映射生成等操作。熟悉API用法,可以更好地管理和优化源码映射。
在使用Gulp-sourcemaps插件时,需要注意其支持的插件类型,如通用、JS和CSS等,并可添加插件以扩展功能。目前,了解详细插件用法和制作插件的步骤仍需进一步探索。
综上所述,源码映射是前端开发中解决代码压缩混淆、编译和其他语言转换后调试问题的重要工具。理解其原理和使用方法,可以显著提升开发效率和调试体验。希望本文提供的内容能够帮助您更好地理解和利用源码映射技术。
认识 sourceMap
sourceMap是什么?
当我们的代码在浏览器中运行时,实际上是通过打包压缩后的代码来执行的,并不是我们编写的原始源代码。然而,当遇到代码报错需要进行调试时,这个过程变得相当繁琐。那么,如何来调试这种经过转换的代码呢?答案是使用sourceMap。
sourceMap的作用是从已转换的代码中映射到原始的源文件。换句话说,转换后的代码中的每一个位置,都对应着转换前的确切位置。
例如,没有使用sourceMap时,调试起来非常困难,因为代码已经被压缩。而使用sourceMap后,一旦代码出现报错,就会直接指向源文件,帮助我们迅速定位到错误的准确位置。
如何使用sourceMap?
在webpack打包过程中,我们可以通过配置来生成sourceMap。具体来说,需要在打包配置中设置devtool属性。打包完成后,会在文件夹下面生成一个以.map为后缀名的文件。这个文件是一个对象,其中包含了version、sources、mappings、names等属性。在出口文件的最后,会添加一个注释,指向sourceMap的路径,例如://# sourceMappingURL=hh.js.map