前言

任何一门语言都有对应的调试方法,也有对应的调试工具,JavaScript当然也不例外。最常用的莫过于浏览器这个调试工具了。而今天我们要讲的对于这个基础调试就不细说,我会将目前所有调试javascript(nodejs)的方法以及工具(主要是VS Code)介绍一下,然后顺便讲解一下webpack的sourcemap功能。

1 前置条件


  1. Chrome: 55+
  2. Nodejs: ​​6.3+​

我当前使用的Nodejs(7.10)和Chome(Version 59.0.3071.104)

该文章配合了一个demo:

2 如何利用sourceMap来调试或者定位我们的错误

现代的网页越来越复杂,加上有babel这类的工具来对我们写的Js代码转译,然后有uglify这类工具进行压缩,最后我们看到的代码与原先的代码相差将会很大,单纯靠打印调试是效率极低的,于是这个时候sourceMap这个功能便应运而生。

在这里我们结合最火爆的打包工具webpack来说说如果利用webpack的sourcemap功能来调试以及定位错误的位置。

首先使用chrome调试带有sourcemap功能的js文件需要有下面的条件:


  1. chrome开启支持​​sourcemap​​的功能
  2. webpack配置​​devtool​​参数

开启chrome的sourcemap支持:

我所知道的JS调试_2d

如果配置webpack但是没有开启支持,那么chrome的控制台将会是这样的:

我所知道的JS调试_bundle_02

我所知道的JS调试_bundle_03

如果开启支持但是没有对应的sourcemap文件:

我所知道的JS调试_2d_04

我所知道的JS调试_bundle_05

满足以上两个条件就可以:

我所知道的JS调试_node.js_06

在​​webpack的官网文档​​中提供了10中方法,那么这10种方法有哪些区别,我们要如何更好地利用这些参数去调试呢?下面我们一一通过图片来简单地过一遍。

2.1 ​​eval​

该方法官方文档标榜是效率最高的,它会使用​​eval​​​执行每一个module,然后每个module后面都会跟着​​//@ sourceURL​​。如下图:

配置如图:

我所知道的JS调试_调试工具_07

生成的文件如下图:

我所知道的JS调试_bundle_08

官网文档说该方法的最大缺点是不能准确地显示行号,但下面的报错图是我截取的,貌似行号是正确的显示的。不建议用于产品环境下。

我所知道的JS调试_chrome_09

2.2 ​​eval-source-map​

这个就是把​​eval​​​的​​sourceURL​​​换成了完整souremap信息的​​DataUrl​​,刚开始第一次编译的时候是比较慢,但重新编译的时候速度会大大地变快。其对应的行号可以正确显示因为其是从原始代码来做映射的。对应的配置和报错图如下:

我所知道的JS调试_node.js_10

报错提示:

我所知道的JS调试_2d_11

不建议用于产品环境下。

2.3 ​​inline-source-map​

为每一个文件添加​​sourcemap​​​的​​DataUrl​​​,注意这里的文件是打包前的每一个文件而不是最后打包出来的,同时这个​​DataUrl​​​是包含一个文件完整​​souremap​​信息的`Base64 格式化后的字符串,而不是一个url。对应的配置文件:

我所知道的JS调试_2d_12

错误的定位情况以及生成的文件如下:

我所知道的JS调试_调试工具_13

不建议用于产品环境下。

2.4 ​​cheap-eval-source-map​

类似于​​eval-source-map​​​,但是取名为​​cheap​​是因为它没有列映射,只有行映射。对应的webpack配置如图:

我所知道的JS调试_2d_14

其生成的文件如下:

我所知道的JS调试_2d_15

报错的定位情况:

我所知道的JS调试_chrome_16

不建议用于产品环境下。

2.5 ​​cheap-module-eval-source-map​

类似于​​cheap-eval-source-map​​,但是官网称这个选项可以更好地处理映射。对应的配置如下:

我所知道的JS调试_chrome_17

错误的定位情况如下:

我所知道的JS调试_2d_18

不建议用于产品环境下。

2.6 ​​source-map​

该选项会生成一个sourcemap文件,然后在bundle文件中添加一个引用声明,这样开发工具可以知道在哪里找到sourcemap文件,对应的配置如下:

我所知道的JS调试_2d_19

生成的sourcemap文件大致如下:

我所知道的JS调试_node.js_20

错误定位情况如下:

我所知道的JS调试_bundle_21

2.7 ​​hidden-source-map​

和​​source-map​​一样,但是不会添加引用声明到bundle文件中。如果你只想要让sourcemap从错误报告中映射错误堆栈追溯,但是不想暴露你的sourcemap文件给开发者工具的话,这种方式很适合你的。对应的配置如下:

我所知道的JS调试_node.js_22

错误定位情况:

我所知道的JS调试_bundle_23

2.8 ​​cheap-source-map​

类似于​​source-map​​,但是没有列映射。对应的配置如下:

我所知道的JS调试_2d_24

错误定位情况:

我所知道的JS调试_node.js_25

bundle文件最后的注释如下:

我所知道的JS调试_2d_26

2.9 ​​cheap-module-source-map​

此种方法也没有列映射,同时 loader 的 sourcemap 也被简化为只包含对应行的。最终的​​sourcemap​​​只有一份,它是​​webpack​​​对 loader生成的​​sourcemap​​进行简化,然后再次生成的。对应的配置如下:

我所知道的JS调试_bundle_27

错误定位情况:

我所知道的JS调试_调试工具_28

2.10 ​​nosources-source-map​

该方法生成的sourcemap文件没有​​sourcesContent​​字段,如下:

我所知道的JS调试_2d_29

配置如下:

我所知道的JS调试_bundle_30

错误定位情况:

我所知道的JS调试_node.js_31

3 前端代码debugger调试

如果我们在前端代码中指定的位置打断点,除了可以直接在控制台中直接打断点,还可以在你的代码中添加​​debugger​​关键词来打断点:

我所知道的JS调试_2d_32

4 Nodejs的调试

Nodejs写多了,就免不了调试,而最低级的console打印貌似满足不了调试nodejs,于是我们就开始寻求新的调试方法,今天就给大家列举两种常用的调试工具。

首先我们需要开启Nodejs调试状态,只需要在启动的文件使用​​--inspect​​即可,如下图:

我所知道的JS调试_2d_33

于是在终端会打印出下面的红框中的重要的一行话:

Debugger listening on port 5859. [1] Warning: This is an experimental feature and could change at any time. [1] To start debugging, open the following URL in Chrome: [1]     chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:5859/39515fe7-3f4a-40b2-8b95-6196a2d22d73 

眼尖的童鞋肯定会发现为什么你的打印中出现了两次​​Debugger listening on port​​​,那是因为我使用的Nodejs文件监控重启包是​​piping​​,而这个包的一个最大的特点便是:

使用默认的设置的时候,那么将会启动第二个实例,这个实例由第一个实例监控。Piping在第一个实例中故意人为的引发uncaughtException操作来避免继续执行其他代码,所以真正执行服务器代码的是在第二个实例,这也就是我们应该使用第二个打印的原因。

4.1 Chrome调试Nodejs

基于上面的介绍,我们将第二个实例打印的调试地址粘贴复制到Chome地址栏中,即可打开调试窗口,然后在你想要打断点的地方加上断点即可:

我所知道的JS调试_调试工具_34

4.2 VSCODE调试Nodejs

除了使用chome,你还可以使用VSCode这个神器。使用VScode调试得配置一下:

使用如下的调试配置:

{   // Use IntelliSense to learn about possible Node.js debug attributes.   // Hover to view descriptions of existing attributes.   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387   "version": "0.2.0",   "configurations": [     {       "name": "Attach to Process",       "type": "node",       "protocol": "inspector",       "request": "attach",       "address": "localhost",       "port": 5859     }   ] } 

其中端口的配置记得和之前打印的调试端口一致,这里都是5859。

然后启动你的Nodejs服务,接着按下​​F5​​,就可以进入调试状态,打上断点,同样可以查看本地变量/堆栈等等信息。如下图:

我所知道的JS调试_node.js_35

参考


  1. ​Devtool​
  2. ​Node.js Debugging in VS Code​
  3. ​Node Debug Architecture​