前端开发调试

前端调试,除了用 console.log,有没有其他办法呢?

Chrome Workspace 调试

可能有的人已经在使用 Chrome 提供的 Sources 功能进行调试了,但是你有没有发现,即使你通过 Chrome 调试发现了问题,你并不能直接在上面进行修改,而是需要切换回你的 IDE 或编辑器去纠正它,非常低效。

对于这样一个出错:

006tKfTcly1g1dtrhhxz3j32lc0dk7c9

我们点击右边的 index.js?4cba 即可以跳到 Sources 页面,可以看到如下:

NlrumTYOetVotvlsoSrL

但我们没办法直接在这里进行纠正。那有没有办法可以做到我们利用 Chrome 的调试功能调试代码的同时,也能直接修改代码呢?

办法肯定是有的,Chrome 已经提供了这个功能,就是 Workspace,但是我敢说在阿里,几乎没有人去使用它,原因是什么,后面会解释。

需要做两步工作:

  1. 配置 Webpack devtoolModuleFilenameTemplatedevtool

    nUxBVWIKChRTOtvmNWvO

    如果你需要列信息,可以使用 eval-source-map,他可以像上图一样定位到 373 行。

    如果你不需要列信息,可以只使用 cheap-module-eval-source-map,这样只会定位到 372 行,不会有列信息。(虽然拆成多行写,但是本质上他们是可以作为一条代码被解析的)。

    当然 devtool 并不只有这两个配置项,只不过这两个确实用的可能相对多些,根据情况选择吧。个人认为用列信息缺失换取编译速度提升是值得的。

  2. 进到 Source 下的 FileSystem 里面,添加文件夹到 Workspace

    JjBvYDoeMoeKIrxElMdp

    如果上一步配置好了之后,这里添加之后你会发现 src 文件夹下面几乎每个文件右下角都带了一个小绿点,这个小绿点代表的意思是它已经和本地文件关联成功了。我们可以直接在这里修改文件,所有的修改保存之后会写到本地。同时,本地的修改也会触发这边的更新。

重新触发刚刚的错误:

sCeukgccPsCsygXBlzFo

留意右边提示,已经指向了本地文件,单击它:

axXDGPCGRqjhBZranIVi

注意这个 index.js 上面同样有个小绿点,此时进行编辑修改可以进行保存,保存后会同步到本地,Webpack 检测到文件修改后会重新构建。

如果我们改了本地的文件,这里也会自动更新。

但这并不是说我们可以脱离编辑器或者 IDE 了,对于某些情况,当我们使用 Chrome 调试功能,发现一些显而易见的 BUG,或者我们仍然想插几句 console.log 的话,直接在这里写还是比较方便的~

Chrome Workspace 有 BUG

但我前面为什么说阿里内部没有什么人使用这个功能呢?

这一切要从一个困扰了我一个多月的 BUG 开始。。。

这个 BUG 是这样的,当我打开 Chrome,开始我的工作的时候。过了一会,我的风扇就停不下来了。再过了一会,我明显感觉到我的电脑变卡了。最后,甚至出现了内存不足的警告。。

wycxaqjLfSNGnECIoLcU

我的 Chrome 占用了接近 78G 的内存(大部分是交换内存),CPU 也是接近 100% 的跑。然后,我刚截完图,我的 VSCode 被系统由于内存不足强杀了。甚至有一次,系统被强制注销了。。。

而我却无可奈何,找不出原因,因为这并不是插件问题或者某个页面内存泄漏的问题。。。我尝试过禁用所有插件。尝试了 Chrome,Chromium,Chrome Canary 三个版本,问题依旧存在。

我的内心是奔溃的,我开始怀疑是不是我的电脑有问题了。中间我还换了 Firefox 使用一阵子,但是 Firefox 在 MacOS 表现真的不行,速度明显比 Chrome 慢。怎么办怎么办。。。最后克军老大都让我去换个电脑了。。。

最后想想还是提一个 BUG 给官方吧:

gvlgdcsXUpxtlsGeqBUK

地址在:https://bugs.chromium.org/p/chromium/issues/detail?id=880692

BUG 果然没白提,很快就有 Chromium 团队的人根据我给出的 Sample 说明可能是 DevTools 的问题:

The CPU profile suggests it spends most of the time in allocating strings for DevToolsFileWatcher::SharedFileWatcher
So I think that's likely the cause.

并且他把问题 assigned 给了DevTools 团队的人,并且询问是否是因为 Workspace 太大的问题。

但是 DevTools 的人也回复了,他说他尝试了一个 80GB 的 Workspace,没有问题。

看到之后,我就又了思路,尝试了下,打开 Chrome,不打开 Devtools,结果风平浪静,什么事都没有。

但是当我打开 Devtools 的时候,内存就开始每秒几十M的上升了。。。

果然就是 Devtools 的锅,我喵了一眼躺在我 Workspace 的一个前端项目文件夹。。。

当我第一反应不是把它移除了,而是去到项目里面把它的 node_modules 删了。

嗯,果然就没事了。但问题不是因为 node_modules 太大了,DevTools 团队的人导入一个 80GB 的项目都没问题。问题是 tnpm 会在 node_modules 中大量使用软链接。我当时就认为是软链接导致的,所以第一时间删除的时 node_modules。

之后我给了他们一个复现过程,自己确认了下这的确是能导致问题的。

Reproduce:
1. Create a folder name A
2. In A folder, create two folder B and C
3. In B folder, make two symlink to B and C
4. In C folder, make two symlink to B and C
5. Create some dirty file in B or C
6. Open Chrome and add A folder into workspace(filesystem)

很快他们就修复了这个问题了,但是还没发布到最新的 Canary 版本上,Canary 71.0.3552.2 已经修复了这个问题。开发者还说:

Other than that I'd say it's of moderate safety, but crucial for DevTools users who use workspaces and npm. We expect increase of the amount of such users in the coming month, so we definitely would like to see this fix merged.

感觉修复的速度很快哈,给 Google Chromium Team 👍。

所以,如果阿里内部真的有人在用 Workspace 的话。。。应该都会出现这个问题。。。但是我在网上各种搜索都没有找到有人反馈过这个问题。。。

好吧,扯远了。扯这么多,还有一个目的就是告知下,虽然有这么个调试功能,但是如果你用的 tnpm 或者 cnpm,就暂时不要使用了。

VSCode 调试

除了上述的 Chrome 调试方式,其实还有另外一种调试方法也是我偶尔会使用的。那就是直接用 VSCode 的调试。

kchoGEQNyVhWTcwBUWhq

这种调试相比在 Chrome 调试,感觉更加符合程序员一贯的调试思维。并且浏览器的输出信息都会打印到这边的调试控制台,我们也可以在调试控制台下面直接执行 JavaScript 代码。

使用这种调试方式,需要安装下 Debugger for Chrome 这个插件,同时还要配置下,配置方法可以参考下这个插件的说明:https://github.com/Microsoft/vscode-chrome-debug

我简单说说我怎么配置的:

你需要一个在你的 .vscode 文件夹下创建一个 launch.json 文件,我的文件内容是这样的:

{
  // 使用 IntelliSense 了解相关属性。
  // 悬停以查看现有属性的描述。
  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "yundun-ddoscoo",
      "type": "chrome",
      "request": "launch",
      "runtimeExecutable": "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}",
      "userDataDir": true,
    }
  ]
}

之后 F5 就可以开启调试了,就这么简单。