Source Map
通过构建编译之类的操作我们可以将开发阶段的源代码转换为能够在生产环境当中运行的代码。这是一种进步,但是这种进步的同时也就意味着我们在实际生产环境当中运行的代码与我们开发阶段所编写的代码之间会有很大的差异。
那在这种情况下如果我们需要去调试我们的应用,又或是我们运行应用的过程中出现了意料之外的错误,那我们将无从下手。
这是因为我们无论是调试还是报错,那他都是基于转换过后的代码来运行的。那Source Map就是解决这一类问题最好的一个办法。
他的名字就已经表述了他的作用叫做源代码地图,那他就是用来映射我们转换过后的代码与源代码的关系,那一段转换过后的代码呢我们通过转换过程当中生成的这个source map文件就可以逆向得到源代码。
那目前很多第三方的库再去发布的文件当中都会有一个.map后缀的source map文件,那例如jQuery,我们可以打开jQuery的source map文件然后看一下,这是一个JSON格式的文件,为了更容易阅读我们格式化一下。
那这个JSON文件里面记录的就是我们转换过后的代码与转换之前代码之间的映射关系。主要有这么几个属性我们简单来看一下。
首先就是version这个属性指的是我们当前这个文件所使用的的source map标准的版本。
然后就是source属性,那这个属性记录的就是我们转换之前源文件的名称。那因为很有可能是多个文件合并,转换成了一个文件,所以说这里的属性是一个数组。
再然后就是names属性,这个属性指的是我们的源代码当中使用的一些成员名称,我们都知道,在压缩代码时我们会将开发阶段编写的那些有意义的变量去替换为一些简短的字符从而去压缩我们整体代码的体积。那这个属性中记录的就是我们原始对应的那些名称。
最后是mappings属性, 那这个属性其实是我们整个source map文件的核心属性。那他是一个base64-vl编码的字符串。那这个字符串他记录的信息就是我们转换过后代码当中的字符与我们转换之前所对应的映射关系。
{
"version": 3,
"file": "jquery.min.js",
"sources": [
"jquery.js"
],
"names": [
"window",
"undefined",
"readyList",
"rootjQuery",
"core_strundefined",
"location",
"document",
"docElem",
"documentElement",
"_jQuery",
"jQuery",
"_$",
"$",
"class2type"
...
],
"mappings": ";;;CAaA,SAAWA,EAAQC,GAOnB,GAECC,GAGAC,EAIAC,QAA2BH,GAG3BI,EAAWL,EAAOK,SAClBC,EAAWN,EAAOM,SAClBC,EAAUD,EAASE,gBAGnBC,EAAUT,EAAOU,OAGjBC,EAAKX,EAAOY,EAGZC,KAGAC,
...
"
}
有了这样一个文件过后一般我们会在转换过后的代码当中通过添加一行注释的方式来去引入这个source map文件。
不过呢,source map这个特性只是帮助开发者更容易去调试和定位错误的,所以说他对生产环境其实没有什么太大的意义。
在最新版的jQuery当中他已经去除了引用source map的注释,我们这里想要去尝试的话需要手动的添加回来。这里我们在jQuery.min.js这个文件当中最后一行我们去添加一个这样的注释。这个注释有一个特定的格式。
就是以#开头,然后source mapping url = 我们jQuery的map文件
//# sourceMappingURL = jquery-3.4.1.min.map
那这样的话,我们在浏览器当中如果说打开了开发人员工具的话,那开发人员工具去加载到的这个js文件最后有这么一行注释他就会自动去请求这个source map文件。
然后根据这个文件的内容逆向解析出来我们对应的源代码。以便于我们的调试,同时因为有了映射的关系所以说我们源代码当中如果说出现了错误那也就很容易能定位到源代码当中对应的位置了。
那我们这里回到浏览器。然后我们打开开发人员工具找到source面板,那在source面板我们就能看到转换之前的jquery源代码。
他也可以显示在里面,那我们这里还可以在我们的代码当中添加一个断点,然后我们刷新页面。这个时候我们就可以单步去调试整个jquery的源代码。
那此时调试过程当中使用的就不再是我们之前所使用的的压缩过后的代码,而是真正意义上的源代码,这就是source map的一个作用。
那这里简单总结一下,source map的作用解决的就是我们在前端方向引入了构建编译之类的概念过后导致我们前端编写的源代码与运行的代码之间不一样所产生的那些调试的问题。
Webpack 配置source map
webpack可以为我们的打包结果生成对应的source map文件,那用法上也非常简单,不过他提供了很多不同的模式。那这就导致大部分的初学者可能会比较懵。
那接下来我们一起来研究一下,webpack中如何去配置使用source map以及他几种不同模式之间的差异,那我们回到配置文件当中。
这哭我们需要使用的一个配置属性叫做devTool 这个属性就是用来配置我们开发过程中的辅助工具,也就是与source map 相关的一些功能配置。
const path = require('path');
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
},
devtool: 'source-map&#