首页 > 其他分享 >Source Map入门教程

Source Map入门教程

时间:2022-10-04 22:42:23浏览次数:84  
标签:Map Name min 入门教程 js Source hello

部署前端之前,开发者通常会对代码进行打包压缩,这样可以减少代码大小,从而有效提高访问速度。然而,压缩代码的报错信息是很难Debug的,因为它的行号和列号已经失真。这时就需要Source Map来还原真实的出错位置了。

Source Map入门教程_chrome

 

为啥变换代码?

前端代码越来越复杂的情况下,开发者通常会使用​​webpack​​​、​​UglifyJS2​​​等工具对代码进行打包变换,这样可以减少代码大小,有效提高访问速度。关于变换代码的原因,这里不妨引用一下大神​​阮一峰​​​的​​JavaScript Source Map 详解​​:

  • 压缩,减小体积。比如jQuery 1.9的源码,压缩前是252KB,压缩后是32KB。
  • 多个文件合并,减少HTTP请求数。
  • 其他语言编译成JavaScript。最常见的例子就是CoffeeScript。

如何变换代码?

下面是一个简单的“hello World”程序hello.js

function sayHello()
{
var name = "Fundebug";
var greeting = "Hello, " + Name;
console.log(greeting);
}

sayHello();

使用​​UglifyJS2​​对源代码进行压缩变换:

uglifyjs hello.js \
-m toplevel=true \
-c unused=true,collapse_vars=true \
-o hello.min.js

压缩后的代码hello.min.js

function o(){var o="Hello, "+Name;console.log(o)}o();

为啥需要Source Map?

使用Firefox执行hello.js的报错信息是这样:

ReferenceError: Name is not defined
sayHello file:///Users/fundebug/sourcemap-tutorial/hello.js:4:9
<匿名> file:///Users/fundebug/sourcemap-tutorial/hello.js:8:1

而hello.min.js的报错信息是这样:

ReferenceError: Name is not defined
o file:///Users/fundebug/sourcemap-tutorial/hello.min.js:1:18
<匿名> file:///Users/fundebug/sourcemap-tutorial/hello.min.js:1:59

对比压缩前后的出错信息,我们会发现,错误行号和列号已经失真,且函数名也经过了变换。而对于真实的前端项目,开发者会将数十个源文件压缩为一个文件,这时,错误的列号可能多达数千,且出错的真实文件名也是很难确定的,这样的话,压缩代码的报错信息是很难Debug的。

而Source Map则可以用于还原真实的出错位置,帮助开发者更快的Debug。

什么是Source Map?

使用​​UglifyJS2​​时指定source-map选项即可生成Source Map:

uglifyjs hello.js \
-m toplevel=true \
-c unused=true,collapse_vars=true \
--source-map hello.min.js.map \
--source-map-include-sources \
--source-map-root \
-o hello.min.js

各种主流前端任务管理工具,打包工具都支持生成Source Map,具体可以查看​​生成Source Map - Fundebug文档​​。

生成的hello.min.js多了sourceMappingURL,表示Source Map文件的位置。

function o(){var o="Hello, "+Name;console.log(o)}o();
//# sourceMappingURL=hello.min.js.map

生成的Source Map为hello.min.js.map:

{
"version": 3,
"sources": ["hello.js"],
"names": ["sayHello", "greeting", "Name", "console", "log"],
"mappings": "AAAA,QAASA,KAEL,GACIC,GAAW,UAAYC,IAC3BC,SAAQC,IAAIH,GAGhBD",
"file": "hello.min.js",
"sourceRoot": "",
"sourcesContent": ["function sayHello()\n{\n var name = \"Fundebug\";\n var greeting = \"Hello, \" + Name;\n console.log(greeting);\n}\n\nsayHello();\n"]
}

由hello.min.js.map可知,Source Map是一个JSON文件,而它包含了代码转换前后的位置信息。也就是说,给定一个转换之后的压缩代码的位置,就可以通过Source Map获取转换之前的代码位置,反过来也一样。Source Map各个属性的含义如下:

  • version:Source Map的版本号。
  • sources:转换前的文件列表。
  • names:转换前的所有变量名和属性名。
  • mappings:记录位置信息的字符串,经过编码。
  • file:(可选)转换后的文件名。
  • sourceRoot:(可选)转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空。
  • sourcesContent:(可选)转换前的文件内容列表,与sources列表依次对应。

Source Map真正神奇之处在于mappings属性,它记录了位置是如何对应的。​​JavaScript Source Map 详解​​已经有很好的解释,这里不再赘述。

怎样使用Source Map?

主流浏览器均支持Source Map功能,不过Chrome与Firefox需要一些简单的配置,具体步骤请参考​​How to enable source maps​​。下面以MacBook上的Chrome浏览器为例,介绍一下配置方法:

1. 开启开发者工具

使用快捷键option + command + i;或者在菜单栏选择视图->开发者->开发者工具

Source Map入门教程_开发者_02

chrome-sourcemap1.png

2. 打开设置

使用快捷键fn + F1;或者点击右上角的三个点的图标,选择Settings

Source Map入门教程_开发者_03

chrome-sourcemap2.png

3. 开启Source Map

在Sources中,选中Enable JavaScript source maps

Source Map入门教程_开发者_04

chrome-sourcemap3.png

为了测试,我写了一个简单的HTML文件hello.min.html

<head>
<script type="text/javascript" src="hello.min.js"></script>
</head>

使用Chrome打开hello.min.html,在控制台看到的错误如下:

Uncaught ReferenceError: Name is not defined
at o (hello.min.js:1)
at hello.min.js:1

报错的文件仍然为hello.min.js,需要刷新一下Source Map才有作用:

Uncaught ReferenceError: Name is not defined
at o (hello.js:4)
at hello.js:8

注意,Chrome的报错信息没有列号,因此4为错误的行号。Chrome不仅可以通过Source Map还原真实的出错位置,还可以根据Source Map的sourcesContent还原出错的源代码。点击出错位置,即可跳转到源码,这样Debug将非常方便。

Source Map入门教程_chrome_05

 




标签:Map,Name,min,入门教程,js,Source,hello
From: https://blog.51cto.com/u_15707676/5731938

相关文章

  • golang中map基础了解
    map初识map是一个以键值对元素的数据集合,map是一个集合。map的优点是查找速度非常会,原因是map的底层存储是hash表。hash表的存储原理:对key进行计算,计算出hash值,对hash......
  • springboot项目 报错No mapping for GET /css/bootstrap.css,前端无法展示样式
    说来也奇怪,前几天刚写完的项目写的好好的现在打开他就加载不了前端的静态资源了报错NomappingforGET/css/bootstrap.css解决方法:新建一个配置类,将静态资源的路径......
  • <resultMap >继承 解决 Mybatis 统计类查询需求
    在使用Mybatis过程中,有需要通过SQL直接计数或求和的需求,需要自定义<resultMap>,而这些<resultMap>往往会与数据库映射直接生成的<resultMap>有关联,会用到resultMap继承,这......
  • 5.mapper出错原因
    1.总结:前个星期mapper出错,很大原因是自己的项目结构创建有问题,大项目下应该是springinit那种项目结构形式,但是在创建多模块的时候应该是使用moudle形式的项目结构;......
  • Tilemap-CustomRuleTile 的使用 Tile
     Tile中添加属性字段是比较麻烦的-Tile的创建是由Unity3d创建的,类似于预制体,他不包含在Hierarchy栏目中,同时无法挂脚本,没办法做到赋值,也不能操作自定义属性CustomRuleTi......
  • 003-Redis 中的 BitMaps
    1.BitMap1.1bitcount1.1.1基本信息BITCOUNTkey[startend]summary:Countsetbitsinastringsince:2.6.0Countthenumberofsetbits(populationcounti......
  • 【Azure 环境】Azure Resource Graph Explorer 中实现动态数组数据转换成多行记录模式
    问题描述想对Azure中全部VM的NSG资源进行收集,如果只是查看一个VM的NSG设定,可以在门户页面中查看表格模式,但是如果想把导出成表格,可以在AzureResourceGraphExplorer中查找......
  • Java中Map.Entry
    Map<String,String>map=newHashMap<String,String>();map.put("1","value1");map.put("2","value2");map.put("3","value3");遍历map方式1:Ma......
  • ubuntu 使用sudo vim /etc/apt/sources.list命令修改文件后该如何退出?
    ubuntu使用sudovim/etc/apt/sources.list命令修改文件后该如何退出? ubuntu使用sudovim/etc/apt/sources.list命令修改文件后该如何退出? Esc输入冒号(即shif......
  • MapStruct使用(二)
    批量转换#编写convertimportorg.mapstruct.factory.Mappers;importjava.util.List;@MapperpublicabstractclassCarConvert{publicstaticCarConvert......