VsCode前端调试速速上手指南

背景

之前调试一直是在项目里写 console.log() 和 debugger调试,简单快捷,但其实也不算方便,而且还经常忘记删,虽然打包时有插件可以移除,但总归不算优雅;

一直想把 vscode 的调试器用起来,但就是太懒了?,这么多配置懒得看;终于痛定思痛花重金购入神光的调试小册,学会之后发现使用起来还是很简单的;这里对学习的内容做一下总结梳理。

文末有简单的示例,带有注释,如果你也很懒就可以直接拿来先用起来;

优势

使用调试器的优势如下:

  • 保持业务代码干净不用加了调试代码又忘了删除

  • 可以随时中止流程

  • 能查看所有可用的变量,不用写一堆console,漏写又要重跑流程等等等等

基本配置

我们先创建一个demo项目

// 环境 node v18.16.0
yarn create react-app react-debug-demo

进入 vscode 的 debugger 面板,点击 create a launch file ,输入Web App,选择 Web App(Chrome) ,vscode 会在 .vscode 文件夹下自动创建配置文件 launch.json,里面是调试器的基本配置

image-20230616175829537

当然如果项目下已经有 .vscode/launch.json 文件,左侧 debugger 面板就是这样的

image-20230619162638468

version 是配置文件的版本,用来确保和调试器的兼容性,默认即可;

configurations 数组里每个对象对应一个调试器启动项,通过name字段的值选择,可以配置多个;可以看到除了我们自定义的,还有一些默认选项;

image-20230619163734486

我们先来过一下这几个配置项

type

type 表示调试器的运行环境,比如我们想通过 chrome 调试 react 应用,type 值就用 chrome;如果我们想调试项目的打包过程或者是node应用,type 值就是 node,当然还有很多其它可选项,注意不同的 type 值会影响其它配置项的可用性,以下配置都以 chrome 或 node 为例

image-20230619164604295

request

request 有两个取值,attachlaunch

launch 可以帮我们以调试模式启动 chrome 或 node (具体看你的type配置),并与 vscode 调试器建立连接

attach 用于与已经处于调试模式的 chrome 或 node 建立连接

启动 chrome 或 node 的调试模式需要用到命令行,可以自行了解,一般用 launch 就好

name

上面讲过,就是当前配置项的名称,作为启动器的选项

url

调试器要访问的地址,本地调试的话就是 npm run start 启动项目时的地址,只有 requestlaunch 时才生效

对应的,如果 requestattach,则url字段无效, 需要设置的字段就是 port ,即以调试模式启动应用时的端口

webRoot

设置项目代码所在的根目录,${workspaceFolder} 是 vscode 的内置变量,表示 vscode 当前打开的文件夹的路径

最基本的字段就这些,现在就可以用起来啦

调试

我们先改造下 App.js 模拟一个非常常见的场景,加工接口返回的列表,然后展示(为了展示清晰,我用了两次循环?)

import './App.css';
import { useEffect, useState } from 'react';

const fetchData = () => {
  return new Promise((res) => {
    setTimeout(() => {
      res([
        {
          id: 'top',
          title: 'title',
          content: 'content',
        },
        {
          id: 'middle',
          title: 'title',
          content: 'content',
        },
        {
          id: 'bottom',
          title: 'title',
          content: 'content',
        },
      ]);
    }, 1000);
  });
};

function App() {
  const [list, setList] = useState([]);
  useEffect(() => {
    const promiseResCall = (res) => {
      const result = res.map(i => {
        return {
          ...i,
          title: `${i.id} ${i.title}`,
          content: `${i.id} ${i.content}`
        }
      })
      setList(result);
    }
    fetchData().then(promiseResCall);
  }, []);

  return (
    <div className='App'>
      <ul>
        {list.map((item) => (
          <li key={item.id}>
            <h4>{item.title}</h4>
            <p>{item.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

接下来我们给需要调试的位置打上断点,在代码行数旁点击一下出现小红点即可

image-20230620101510442

npm run start

项目启动!

再选择我们的配置,点击启动按钮

image-20230619180141244

调试器启动!

image-20230619180312183

可以看到浏览器被自动打开,之后又自动切到了vscode界面我们断点的位置;

接下来我们看下界面右上角的操作按钮

image-20230620092315298

image-20230620093416673恢复运行

image-20230620093444830可以理解为每次执行”一行”,遇到函数时不进入函数内部

image-20230620093506551每次执行”一行”,遇到函数时进入函数内部

image-20230620093625601跳出当前函数

image-20230620093717320重启调试器

image-20230620093757537停止调试器

界面左侧的面板,最常用到的就是

VARIABLES :变量,依据作用域划分

image-20230620101632058

CALL STACK:调用栈,对于屎山?项目,调用栈可以大大提高调试效率;需要注意的是,匿名函数会被展示为 anonymous;

image-20230620101745678

调用栈里一堆 commitxxxx 的函数是 react 的源码调用,我们调试业务代码的时候,可能并不需要关注第三方库如何运作,可以在 launch.json 里加上配置

"skipFiles": ["${workspaceFolder}/node_modules/**/*.js"]

这样可以折叠 node_modules 里js文件的调用,停止调试模式后重新启动(直接用刷新按钮配置可能不会生效)

image-20230620112012705可以看到刚刚 react 的调用栈已经被折叠了,这个字段有个默认配置 "<node_internals>/**",它会折叠 node 的调用栈

BREAKPOINTS:就是我们打的所有断点,最右上角的两个按钮分别是所有断点的启禁用切换和清空断点; 勾选 Caught ExceptionsUncaught Exceptions可以分别在捕获到错误和抛出未被捕获的错误时断住

image-20230620112716387

以上就是使用调试器最基本的内容啦,除此之外我们还需要一些技巧来提高我们的调试效率

image-20230620114942621

右键点击断点,可以看到断点是能编辑的

image-20230620115101356

里面有三个选项,用法其实已经写明了,主要用到的是

Expression:表达式返回true时断点生效;这个在循环里很有用,输入条件,敲回车即可;程序会在达成条件时断住image-20230620115419438

Log Message:在控制台打印输出,用{} 包裹变量即可,调试器的默认控制台是 DEBUG CONSOLE

image-20230620115944762

userDataDir

userDataDir 这个字段用来设置调试器启动的chrome的用户数据储存目录;

可以看到,调试器打开的chrome是没有任何书签,插件和cookie等本地储存的,这是因为 userDataDir 的默认值是 true,即每次启动都使用临时目录;这样每次调试插件和cookie都会被清空,很不方便;

image-20230620140033063

userDataDir 设置为 false 的话可以使用默认的用户数据目录;重启调试器,可以看到各种插件都是在的;

image-20230620142311572

但是这样有个问题,同一个数据目录同一时间只能被一个 chrome 实例使用,也就是说,当我们用chrome打开网页之后,调试器就不能用这个chrome调试了

可以看到,因为我已经开了其它网页,所以地址栏并没有成功访问我们的调试地址 http://localhost:3000,而是about:blank, vscode 也报错了;需要退出 chrome ,重启调试器才行;这样我们调试的时候就不能正常使用 chrome 了,也很不方便

image-20230620142435781

有两个解决办法

一个是设置一个目录专门用来储存调试时的用户数据 ,比如

"userDataDir": "${workspaceFolder}/data"

还有一个办法是下载另一个版本的 chrome,比如 canary,这是chrome的每日构建版,需要先到官网去下载,下载安装完成,设置 runtimeExecutable 字段为 canary

"runtimeExecutable": "canary",
"userDataDir": false,

type 为 chrome 时,runtimeExecutable 可以设置为可执行文件的绝对路径 或者 浏览器的版本,比如 stable(默认值),canarydev 等,当然你要先下载安装这些版本浏览器才可用;

这样我们就可以将一个版本的浏览器用来开发,一个用来日用了;

当然如果你想同时调试多个项目还是需要给每个项目的userDataDir 设置为不同的值的;

还有几个常用的配置

runtimeArgs 调试器启动时携带的额外参数

env 设置环境变量

console 设置输出的控制台,internalConsole 为默认值,输出在 DEBUG CONSOLEintegratedTerminal 输出在 TERMINAL,需要注意这个字段是受 type 影响的

image-20230620150207929

理解了每个字段的含义其实我们就能组装出各种调试配置了,比如下面是一个简单的node调试器的配置,可以用来调试项目打包

    {

      "type": "node",

      "request": "launch",

      "name": "Launch via NPM",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "build"],
      "env": {

        "NODE_ENV": "production"

      },

      "console": "integratedTerminal"

    },

很好理解,其实就是调试器帮我们运行了 npm run build,并设置了一个环境变量 NODE_ENV, 将日志打印在 TERMINAL;如果你想运行别的版本的node,可以直接替换掉 runtimeExecutable 换成别的版本的node绝对路径,注意,换成执行 node 后参数也要从 npm 的 run build 改成实际执行的脚本,比如

    {

      "type": "node",

      "request": "launch",

      "name": "Launch via node",
      "runtimeExecutable": "/Users/dqqbl/.nvm/versions/node/v18.16.0/bin/node",
      "runtimeArgs": ["scripts/build.js"],
      "env": {

        "NODE_ENV": "production"

      },

      "console": "integratedTerminal"

    },

打断点和调试的方式都是一样的,配置好,选择配置,加上断点,启动即可;当然调试到的可能是编译后的代码,如何调试源码就要学习 sourcemap 的知识了,这个可以去看看小册;

image-20230620151849429

示例

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "debug react",
            "request": "launch",
            "type": "chrome", // 调试器运行环境
            "runtimeExecutable": "canary", // 可执行文件的绝对路径或浏览器版本,如果是浏览器版本需要先下载安装
            "userDataDir": false, // chrome 保存的用户数据目录
            "url": "http://localhost:8080", // 浏览器访问的url
            "runtimeArgs": [
                "--auto-open-devtools-for-tabs" // 启动时自动打开开发者工具
            ], // 启动时携带的参数
            "webRoot": "${workspaceFolder}" // 项目根目录
        },
        {
            "name": "Launch via NPM",
            "request": "launch",
            "type": "node",
            "runtimeExecutable": "npm",
            "runtimeArgs": ["run", "build"],
            "console": "integratedTerminal"
        },
        {
            "name": "Launch via Node",
            "request": "launch",
            "type": "node",
            "runtimeExecutable": "/Users/dqqbl/.nvm/versions/node/v18.16.0/bin/node",
            "runtimeArgs": ["scripts/build.js"],
            "console": "integratedTerminal"
        },
    ]
}

本文专注于先用起来,还有很多其它的可配置项,学会了基本用法其它就是选项的灵活搭配组合而已,如果碰到不认识的可以直接上 vscode 的官网上搜,注意区分 type 不同时可用配置不同

参考

掘金小册-前端调试通关秘籍

VsCode官方文档

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYZr2lsx' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片