- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Webpack 实战系列一:正确使用 Sourcemap由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Sourcemap 协议最初由 Google 设计并率先在 Closure Inspector 实现,它能够将经过压缩、混淆、合并的代码还原回未打包状态,帮助开发者在生产环境中精确定位问题发生的行列位置.
发展至今,Sourcemap 已广泛受 Webpack、Rollup、Babel、Less、Typescript、Chrome、Safari、VS Code 等工具支持.
参考:https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k 。
实现上,Sourcemap 由三部分组成
页面初始运行时只会加载编译构建产物,直到特定事件发生 —— 例如在 Chrome 打开 Devtool 面板时,才会根据 //# sourceMappingURL 内容自动加载 Map 文件,并按 Sourcemap 协议约定的映射规则将代码重构还原回原始形态,这既能保证终端用户的性能体验,又能帮助开发者快速还原现场,提升线上问题的定位与调试效率.
以 Webpack 为例,设置 devtool = 'source-map' 即可同时打包出代码产物 xxx.js 文件与同名 xxx.js.map 文件,Map 文件通常为 JSON 格式,内容如:
各字段含义分别为:
使用时,浏览器会按照 mappings 记录的数值关系,将产物代码映射回 sourcesContent 数组所记录的原始代码文件、行、列位置,这里面最复杂难懂的点就在于 mappings 字段的规则.
Sourcemap 最初版本生成的 .map 文件非常大,体积大概为编译产物的 10 倍;V2 引入 base64 编码等算法将之减少 20% ~ 30%;而最新版本 V3 又在 V2 基础上引入 VLQ 等算法,体积进一步压缩了 50%。这一系列进化造就了一个效率极高的 Sourcemap 体系,但伴随而来的则是较为复杂的 mappings 编码规则.
1.2.1 mappings 编码规则 。
举个例子,对于下面的代码:
当 devtool = 'source-map' 时,Webpack 生成的 mappings 字段为:
字段内容包含三层结构:
第三层逻辑为片段映射到源码的具体位置,以上例 IAAMA 为例:
上述第1、2层逻辑比较简单,唯一需要注意的是片段之间是一种相对偏移关系,例如对于上例第六行映射值:AAAA,IAAMA,IAAI,GAAG,QAAb,每一个片段的第一位 —— 即片段列数为 A,I,I,G,Q,分别代表:
这种相对偏移能减少 Sourcemap 产物的体积,提升整体性能.
而第三层的片段位置映射则用到了一种比较高效数值编码算法 —— VLQ(Variable-length Quantity).
1.2.2 VLQ编码 。
参考:https://en.wikipedia.org/wiki/Variable-lengsth_quantity 。
VLQ 本质上是一种将整数数值转换为 Base64 的编码算法,它先将任意大的整数转换为一系列六位字节码,再按 Base64 规则转换为一串可见字符。VLQ 使用六位比特存储一个编码分组,例如:
数字 7 经过 VLQ 编码后,结果为 001110,其中:
这样一个六位编码分组,就可以按照 Base64 的映射规则转换为 ABC 等可见字符,例如上述数字 7 编码结果 001110,等于十进制的 14,按 Base64 字码表可映射为字母 O.
但是,分组中只有中间的 4 个字节用于表示数值,因此单个分组只能表达 「-15 ~ 15」 之间的数值范围,对于超过这个范围的整数需要组合多个分组共同表达同一数字,组合规则:
例如对于十进制 -17,其二进制为 10001 (取 17 的二进制) 共5位,首先从后到前拆分为两组,后四位 0001 为第一组,连续标志位为 1,符号位为 1,结果为 1,0001,1;剩下的 1 分配到第二个 —— 也是最后一个分组,连续标志位为 0,结果为 0,00001。按 Base64 规则 [100011, 000001] 最终映射为 jA.
同样的,对于更大的数字,例如 1200,其二进制为 10010110000,分组为 [10, 01011, 0000],从后到前编码,第一个分组为 1,0000,0;第二个分组为 1,01011;最后一个分组为 0,00010。按 Base64 映射为 grC.
1.2.3 解码 mappings 。
结合 VLQ 编码知识,我们再回过来头来解读本章开头的例子,对于代码:
编译生成 mappings:
按行、片段规则分割后,得出如下片段:
以第 6 行 ['AAAA', 'IAAMA', 'IAAI', 'GAAG', 'QAAb'] 为例:
其它片段以此类推.
Webpack 提供了两种设置 Sourcemap 的方式,一是通过 devtool 配置项设置 Sourcemap 规则短语;二是直接使用 SourceMapDevToolPlugin 或 EvalSourceMapDevToolPlugin 插件深度定制 Sourcemap 的生成逻辑.
下面我们先展开介绍比较晦涩的 devtool 配置项,理解 Webpack 所提供的各种 Sourcemap 功能规则.
支持 25 种字符串枚举值,包括 eval、source-map、eval-source-map 等,分开来看都特别晦涩,但仔细观察可发现这些值都是由 inline、eval、source-map、nosources、hidden、cheap、module 七种关键词组合而成,这些关键词各自代表一项 Sourcemap 规则.
2.1.1 eval 。
当 devtool 值包含 eval 时,生成的模块代码会被包裹进一段 eval 函数中,且模块的 Sourcemap 信息通过 //# sourceURL 直接挂载在模块代码内。例如:
eval 模式编译速度通常比较快,但产物中直接包含了 Sourcemap 信息,因此只推荐在开发环境中使用.
2.1.2 source-map 。
当 devtool 包含 source-map 时,Webpack 才会生成 Sourcemap 内容。例如,对于 devtool = 'source-map',产物会额外生成 .map 文件,形如:
实际上,除 eval 之外的其它枚举值都包含该字段.
2.1.3 cheap 。
当 devtool 包含 cheap 时,生成的 Sourcemap 内容会抛弃「列」维度的信息,这就意味着浏览器只能映射到代码行维度。例如 devtool = 'cheap-source-map' 时,产物:
浏览器映射效果:
虽然 Sourcemap 提供的映射功能可精确定位到文件、行、列粒度,但有时在「行」级别已经足够帮助我们达到调试定位的目的,此时可选择使用 cheap 关键字,简化 Sourcemap 内容,减少 Sourcemap 文件体积.
2.1.4 modulemodule 。
关键字只在 cheap 场景下生效,例如 cheap-module-source-map、eval-cheap-module-source-map。当 devtool 包含 cheap 时,Webpack 根据 module 关键字判断按 loader 联调处理结果作为 source,还是按处理之前的代码作为 source。例如:
注意观察上例 sourcesContent 字段,左边 devtool 带 module 关键字,因此此处映射的是包含 class Person 的最原始代码;而右边生成的 sourcesContent 则是经过 babel-loader 编译处理的内容.
2.1.5 nosources 。
当 devtool 包含 nosources 时,生成的 Sourcemap 内容中不包含源码内容 —— 即 sourcesContent 字段。例如 devtool = 'nosources-source-map' 时,产物:
虽然没有带上源码,但 .map 产物中还带有文件名、 mappings 字段、变量名等信息,依然能够帮助开发者定位到代码对应的原始位置,配合 sentry 等工具提供的源码映射功能,可在异地还原诸如错误堆栈之类的信息.
2.1.6 inline 。
当 devtool 包含 inline 时,Webpack 会将 Sourcemap 内容编码为 Base64 DataURL,直接追加到产物文件中。例如对于 devtool = 'inline-source-map',产物:
inline 模式编译速度较慢,且产物体积非常大,只适合开发环境使用.
2.1.7 hidden 。
通常情况下,产物中必须携带 //# sourceMappingURL= 指令,浏览器才能正确找到 Sourcemap 文件, 。
当 devtool 包含 hidden 时,编译产物中不包含 //# sourceMappingURL= 指令。例如:
两者区别仅在于编译产物最后一行的 //# sourceMappingURL= 指令,当你需要 Sourcemap 功能,又不希望浏览器 Devtool 工具自动加载时,可使用此选项。你也可以通过以下操作手动打开 Sourcemap:
2.1.8 小结 。
总结一下,Webpack 的 devtool 值都是由以上七种关键字的一个或多个组成,虽然提供了 27 种候选项,但逻辑上都是由上述规则叠加而成,例如:
其它选项以此类推。最后再总结一下:
对于开发环境,适合使用:
对于生产环境,则适合使用:
上面介绍的 devtool 配置项本质上只是一种方便记忆、使用的规则缩写短语,Sourcemap 的底层处理逻辑实际由 SourceMapDevToolPlugin 与 EvalSourceMapDevToolPlugin 插件实现.
参考:https://webpack.js.org/plugins/source-map-dev-tool-plugin/ 。
在 devtool 基础上,插件还提供了更多更细粒度的配置项,用于满足更复杂的需求场景,包括:
使用方法与其它插件无异,如:
插件配置规则较简单,此处不赘述.
至此,有关 Sourcemap 的大部分内容就讲解完毕了,读者们需要了解 Sourcemap 是一种高效位置映射算法,它将产物到源码之间的位置关系表达为 mappings 分层设计与 VLQ 编码规则,再通过 Chrome、Safari、VS Code、Sentry 等工具异地还原为接近开发状态的源码形式.
在 Webpack 场景下,通常只需要选择适当的 devtool 短语即可满足大多数场景需求,特殊情况下也可以直接使用 SourceMapDevToolPlugin 做更深度的定制化.
原文链接:https://mp.weixin.qq.com/s/-y35QBSIx2jMvG5dNklcPQ 。
最后此篇关于Webpack 实战系列一:正确使用 Sourcemap的文章就讲到这里了,如果你想了解更多关于Webpack 实战系列一:正确使用 Sourcemap的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这是 gulpfile: widgets.forEach(function(widget){ gulp.src('widgets/' + widget + "/Widget.es6")
我无法让 firefox(或与此相关的任何浏览器)识别 X-SourceMap header 。对于我的代码。 //# SourceMappingURL 注释对我来说在浏览器端有效,但由于我系统的特定
我试图让 Gulp sourcemaps 写入文件,但我无法在任何地方看到这些文件。如果在工作树中创建了任何新文件,我会在 git status 中看到它们,但找不到任何新文件。 下面是我的 gulp
我无法让我的 webpack 发出 css sourcemap。我把 sourcemap: true 放在任何可能的地方,但没有效果,所有在线解决方案都建议这个或其他一些插件配置,但我没有任何其他插件
在过去的几个月里,我现在每天都在使用 nodejs 和“Jenkins”。无需对我的 package.json 进行任何更改。在“jenkins”构建我的项目时出现以下错误 - gifsicle@3.
所以我有以下任务: gulp.task('sass', function () { gulp.src(['./angular/app/**/*.s+(a|c)ss']) .pi
我的文件结构如下所示(为简洁起见,进行了简化): /less/ /styles.less /public/ /css/ /styles.css
这是最烦人的问题。我遇到了this before here ,但是我的 webpack 配置和 gulp 中有相同的设置,但我无法在 Chrome Devtools 中正确设置断点。 我已经删除了我的
我正在努力让我的 SASS 源映射正常工作。问题似乎是源映射中的“sources”属性以及我的 SASS 文件的嵌套方式。 我有一个 Gulp 任务将 SASS 编译为 CSS。这是一个例子 var
我正在使用 rake 管道来了解构建 emberjs 应用程序。 让它工作起来相当简单,这里有一个例子:https://github.com/emberjs/todos 但我正在努力寻找有关如何让 s
大家好! 我正在使用 VSCode 与 lerna 一起处理 monorepo 中的 OpenSource 项目,我想提供一个包,其中包含轻松做出贡献所需的工具。 为了以一种对我来说非常干净的方式来做
样式 无样式 @import "one.less"; @import "two.less"; 少一个 body { background:red; } 少了两个 body { font-size: 1
我需要在一个目录中有两个合并的 CSS 文件——一个有 sourcemap 而另一个没有。例如,我尝试的是这样的: .pipe(sourcemaps.init()) .pipe(concat('xxx
我启用了 CSS 源映射,但谷歌浏览器的行为就像它们被禁用一样。在我查看的所有资源中,我需要做的就是在 DevTools 首选项中启用源映射。它显然在那里启用: 源映射位于我的 CCS 文件旁边,如下
尝试创建一个 gulp 文件来获取我们的 LESS 文件并生成适当的 .css、.min.css 和 .css.map 文件。关闭,但 sourcemaps 正在将 map 写入扩展名为 .css.m
我正在从我的站点记录 javascript 错误,但文件已最小化,因此我无法获得有意义的行号。但是,我确实有源 map 。 是否有服务、脚本、npm 模块或任何可以帮助我将行号从缩小版本“翻译”成有用
我在生产中遇到了一些来自缩小代码的错误。我有不在生产中的源 map 。我想(事后)以某种方式使用源映射将我的堆栈跟踪转换为人类可读的堆栈跟踪。以前有人这样做过吗? 最佳答案 我也在研究这方面的东西,想
我正在部署我的网站——一个用 GatsbyJS 构建的静态网站——我的源 map 是迄今为止我最大的文件。我有 3 个大约 3MB 的 sourcemap 文件。总体而言,它们可能占我构建的 70%。
我正在尝试让我的 Webpack 项目拥有源映射文件。 我终于得到了正确的设置,所以它会这样做,但现在我收到这个错误: DevTools failed to parse SourceMap: http
1、什么是 Sourcemap Sourcemap 协议最初由 Google 设计并率先在 Closure Inspector 实现,它能够将经过压缩、混淆、合并的代码还原回未打包状态
我是一名优秀的程序员,十分优秀!