我们可以在官方文档看一下对于SourceMap的配置,devtool用来配置SourceMap的类型居然有26种,而且SourceMap又是作为webpack一个很重要的一点,所以我们有必要对SourceMap进行详细的学习。

官方文档SourceMap相关内容:https://webpack.js.org/configuration/devtool/

为什么需要SourceMap

当我们打包项目后,那浏览器所解析的文件就是我们打包后生成的js文件。这个文件我们是很难看懂的,毕竟打包压缩后,代码会经过一系列的处理后,可能会发生很大的差异。
比如说,ES6转化为ES5、行号列号发生改变、TS转化为JS、代码的丑化压缩后变量名被改变等等。

这样的情况下如果发生报错,我们想要去调试就会有很大的困难。我们可以看下打开控制台的报错信息,这样的报错信息我们就很难找到报错的相关代码。哪怕点开bundle.js,打开的是打包压缩后的代码,我们基本很难定位到是哪里发生了报错。
wps3.jpg
这样就会很影响我们的开发效率。
怎么解决这样的问题呢?答案就是:SourceMap

SourceMap可以帮助我们从已转化的代码映射到原始的源文件。而且浏览器是可以通过SourceMap在控制台显示源文件的。
具体的错误提示:
wps4.jpg
点击错误提示,也可以查看源码:
wps5.jpg

SourceMap的使用

webpack配置:

  1. //webpack.config.js
  2. module.exports = {
  3. mode: "development",
  4. devtool: "source-map",
  5. }

当我们配置好想要的SourceMap,就会进行两个步骤

  • 会根据源文件生成一个SourceMap文件
  • 在转化后的代码的最后,添加一行注释,注释指向SourceMap文件

(浏览器在解析转化后的代码时,就会根据最后的注释,找到SourceMap文件,并且会根据SourceMap还原我们的代码,方便调试)
wps6.jpg
wps7.jpg

我们还需要在浏览器打开source-map的设置

在Chrome中打开source-map设置

wps9.jpg

我们可以看一下SourceMap文件都包含什么内容(了解):
wps8.jpg

  • Version:SourceMap对应的版本号。当前最新版本为3。(SourceMap随着版本更新,体积越来越小,在性能上不断优化升级)
  • Sources:保存使用到的源文件;
  • Names:保存转化之前的变量名、属性名;
  • Mappings:base64 VLQ(可变长度)编码,映射了很多信息,这些信息结合打包好的js文件一起,就能让浏览器还原出我们写的源代码;
  • File:打包好的js文件
  • SourcesContent:保留我们的源代码内容。
  • SourceRoot:根目录

SourceMap 26种类型

SourceMap的配置选项多达26种,它们各自有什么区别?我们又该怎么选择呢?
生成出来SourceMap文件是非常大的,比我们打包出来的js文件大很多(比如133kb的文件对应的SourceMap文件位300kb)。SourceMap对性能的影响很大,所以我们应该根据需要选择对合适的SourceMap类型。

None与eval

none:production模式下的默认值,不生成source-map文件。
(这种模式下浏览器不支持具体的错误提示、不支持查看源码)

eval:development模式下的默认值
eval的效果:会将打包后要执行的代码都包装在eval函数里,并且在最后添加sourceUrl(但是不生成SourceMap文件,不会在浏览器还原我们原来的代码。所以浏览器只知道报错对应具体的错误提示,而不支持查看源码)
wps10.jpg

source-map、eval-source-map与inline-source-map

source-map:生成一个独立的source-map文件,并且在bundle文件中有一个注释,指向source-map文件;
(这种模式下浏览器支持显示具体的错误提示、支持查看源码)

eval-source-map:会生成sourcemap,但是source-map文件是以DataUrl添加到每一个eval函数的后面
(DataUrl的内容为base64编码方式)
(这种模式下浏览器支持显示具体的错误提示、支持查看源码)
wps11.jpg

inline-source-map:会生成sourcemap,但是source-map文件是以DataUrl添加到bundle.js出口文件的最后面
(DataUrl的内容为base64编码方式)
(这种模式下浏览器支持显示具体的错误提示、支持查看源码)

eval-source-map与inline-source-map的区别:
eval-source-map模式下,有多个DataUrl,分别保存在出口js文件的每一个对应的eval函数的最后边。
而iniline-source-map模式下的DataUrl只有一个,放在出口js文件的最后。

cheap-source-map与cheap-module-source-map

cheap-source-map:
会生成sourcemap,但是会更加高效一些(cheap低开销),因为它没有生成列映射
(我们根据报错找到我们还原的代码时,只能定位到具体的对应文件的对应那一行,而无法定位到那一行的那一列)。
(这种模式下浏览器支持显示具体的错误提示、支持查看源码)

cheap-module-source-map:
会生成sourcemap,类似于cheap-source-map,但是对源自loader的sourcemap处理会更好。
(这种模式下浏览器支持显示具体的错误提示、支持查看源码)

对源自loader的sourcemap处理会更好这句话怎么理解呢?
比如说我们使用bable-loader对我们的代码进行处理过,那bable会帮助我们将代码修改成我们想要的样子给浏览器解析。这时我们使用cheap-source-map去还原我们所写的代码,其实还原出来的就是经过bable转化后的代码。与我们调试时想要看到的自己编写的代码还是有出入的。这时用cheap-module-source-map就可以解决loader的影响直接看到我们写的代码。

hidden-source-map与nosources-source-map

hidden-source-map:会生成sourcemap,但是不会对source-map文件进行引用;
(相当于删除了打包文件中在最后对sourcemap的引用注释。但是如果我们手动添加回来,还是可以正常显示的。)
wps12.jpg
(这种模式下浏览器不支持显示具体的错误提示、不支持查看源码)

nosources-source-map:
会生成sourcemap,但是生成的sourcemap只有错误信息的提示,不会生成源代码文件;
(这种模式下浏览器支持显示具体的错误提示、不支持查看源码)

至此,我们其实已经学会了26种类型了,其实26种类型就是上边几种类型的拼接,我们只需要了解清楚一些关键字对应的功能,就能知道26种类型各自有什么用了。

26种类型拼接规则:
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

  • inline-|hidden-|eval:三个值时三选一;
  • nosources:可选值;
  • cheap可选值,并且可以跟随module的值;

最佳的方案

我们可以参考vue-cli与create-react-app这两个脚手架是用到哪种SourceMap类型的。

React对于SourceMap的配置如下:
如果是开发环境使用的是cheap-module-source-map。而生产环境会根据是否设置了shouldUseSourceMap来决定是否使用source-map
wps15.jpg

Vue则更为简单,直接设置开发环境为cheap-module-source-map,生产环境直接不设置(生产环境默认none)。

参考脚手架得出最佳方案:

  • 开发阶段:推荐使用 source-map或者cheap-module-source-map
  • 测试阶段:推荐使用 source-map或者cheap-module-source-map。(测试阶段我们也希望在浏览器下看到正确的错误提示;)
  • 发布阶段:false或者采用默认(默认none)