前端debug技巧

Daotin 于 2023-08-21 发布 编辑
  1. VSCode Debugger 调试网页
    1. VSCode Debugger 的配置
    2. 调试 Vue 项目
  2. 调试源码
    1. 调试 vue 源码
    2. 调试 vite 源码
    3. 调试 ElementUI 源码
    4. VSCode Debugger 打的断点是如何在网页里生效的
    5. 打断点的 7 种方式
  3. VSCode Debugger 调试 Node.js
    1. VSCode Node Debugger 配置
    2. 调试 npm scripts
    3. 调试 ESLint、Babel、TypeScript 的源码,Nest.js 源码。
  4. Chrome DevTools
  5. 如何调试移动端网页
  6. 调试工具的原理
    1. Chrome DevTools 的实现原理
    2. 实现 mini puppeteer

VSCode Debugger 调试网页

VSCode Debugger 的配置

{
  "name": "vscode调试",

  // launch:launch 的意思是把 url 对应的网页跑起来,指定调试端口,然后页面会自动attach到这个端口。
  // attach:如果你已经有一个在调试模式跑的浏览器了,那直接 attach上就行
  "request": "launch",

  // 浏览器
  "type": "chrome",

  "runtimeArgs": [
    "--auto-open-devtools-for-tabs" // 打开网页都默认调起 Chrome DevTools
    "--incognito" // 无痕模式
  ],

  // "canary""stable""custom" 或浏览器可执行文件的路径。 Custom 表示自定义包装器、自定义生成或 CHROME_PATH 环境变量。
  "runtimeExecutable": "canary",

  // userDataDir 是保存用户数据的地方,比如你的浏览记录、cookies、插件、书签、网站的数据等等
  // 默认是 true,代表创建一个临时目录来保存用户数据。
  // 设置为false,可以记录登录状态、历史记录
  // 也可以指定一个自定义的路径,这样用户数据就会保存在那个目录下
  // 注意:userDataDir 只能跑一个 Chrome 实例,所以我使用chrome调试,edge用作其他搜索
  "userDataDir": false,

  "url": "http://localhost:8080",

  // workspaceFolder:  /  url 映射到了 ${workspaceFoder} 项目根目录
  "webRoot": "${workspaceFolder}",

  // 是否关闭sourcemap映射
  "sourceMaps": false,

  // 除了启动开发服务器然后连上 url 调试之外,也可以直接指定某个文件,VSCode Debugger 会启动静态服务器提供服务
  "file": "$workspaceFolder}/index.html"

  // sourcemap重映射:有时候,sourcemap 到的文件路径在本地里找不到,代码就是只读的,这时候就需要再次手动映射到本地文件
  // 以下是:默认有三个值,分别是把 meteor、webpack 开头的 path 映射到了本地的目录下。
  // 其中 ?:* 代表匹配任意字符,但不映射,而 * 是用于匹配字符并映射的。
  // 举例:最后一个 webpack://?:/  ${workspaceFolder}/* 的映射,就是把 webpack:// 开头,后面接任意字符 + / 然后是任意字符的路径映射到了本地的项目目录
  "sourceMapPathOverrides": {
    "meteor://💻app/*": "${workspaceFolder}/*",
    "webpack:///./~/*": "${workspaceFolder}/node_modules/*",
    "webpack://?:*/*": "${workspaceFolder}/*"
  }
}

常用配置:

{
  "name": "vscode调试",
  "request": "launch",
  "type": "chrome",
  "runtimeArgs": ["--auto-open-devtools-for-tabs"],
  "runtimeExecutable": "canary",
  "userDataDir": false,
  "url": "http://localhost:8080",
  "webRoot": "${workspaceFolder}"
}

调试 Vue 项目

启动后,先打个断点发现不起效,分析是路径不对。

怎么找路径?

先在代码里面写 debugger,进入调试窗口,查看目前的状况。

但问题就出现在后面多了一个 ?hash 的字符串,导致路径不对了。所以在我们 vue 代码里面打断点会显示未关联,因为对应的本地文件没有。

那为什么会多这样一个 hash 呢?

这是因为 vue cli 默认的 devtool 设置是 eval-cheap-module-source-map,sourceURL 的路径是通过 [module] 指定的,而模块名后默认会带 ?hash。

解决办法就是:从 eval-cheap-module-source-map 变为 source-map。

调试源码

调试 vue 源码

1、下载 vue 源码

git clone https://github.com/vuejs/core vue3-core

2、使用 pnpm 安装

PS:注意去掉 package.json 中的 puppeteer,用来做集成测试的,一是用不到,二是网络问题不去掉一直安装失败。

pnpm install

3、生成 sourcemap

pnpm add cross-env

然后去 packages 下各个包下的 dist 产物,你就会发现有 sourcemap 了。

4、把 runtime-core 包下的 dist 复制出来,替换 vue 项目的 @vue/runtime-core 下的 对应的 dist 目录。

注意是替换而不是删了整个 dist,因为还有一个文件是需要的。

注意 1:vue 源码的版本一定要和 vue 项目中使用的 vue 版本相同,否则启动会报错!

注意 2:使用 vite 搭建的 vue 项目没有生效。原因:vite 没有 source-map-loader 这些东西,无法读取 node_modules 下模块的 sourcemap。解决办法:一是调试源码就用 webpack 的 vue3 项目。二是把 vite 中配置 optimizeDeps: { exclude: ["vue"], } 排除一下 deps,然后删除 node_modules 下 .Vite文件夹。

注意 3:如果无法打断点,就把 vue 项目重新安装跑一下。。。

按照流程跑起来后,确实链接的是本地路径,不过现在 sourcemap 到的路径不大对,没有 runtime-core 的包名,不能编辑:

解决方式有 2 种:

  1. 一种是配置下 sourceMapPathOverrides,把这段路径再做一次映射,映射到源码目录就可以了。
  2. 另一种方式就是改造下 vue3 的 build 脚本,让生成的 sourcemap 就直接是正确的路径。

但是第一种的话不太好找,所以采用第二种。

// output.sourcemap = !!process.env.SOURCE_MAP
output.sourcemapPathTransform = (relativeSourcePath, sourcemapPath) => {
  const newSourcePath = path.join(
    path.dirname(sourcemapPath),
    relativeSourcePath
  );
  return newSourcePath;
};

重新 build 一下,然后进行 dist 复制。

注意:对于 webpack 的项目,这里还需要清除一下 babel loader 的缓存,删除 node_modules/.cache/babel-loader 即可。

调试 vite 源码

TODO

调试 ElementUI 源码

一、首先定位 ElementUI 源码

1、可以通过事件断点的方式,慢慢进入组件的源码。

2、当有了 sourcemap 之后,Chrome DevTools 会直接把 vue 文件列在 sources 里,我们可以找到对应的 vue 文件来打断点,就不用通过事件断点来找了。

能够调试 Element UI 源码之后,想知道组件内部都有哪些逻辑的话,就可以直接在源码断点调试了。

VSCode Debugger 打的断点是如何在网页里生效的

比如源代码的路径是 /Users/xxx/vite-demo/src/App.vue ,最后打包后运行可能是http://xxx.com/bundle.js。

由于文件是关联了 sourcemap 的,所以就直接映射到了/Users/xxx/vite-demo/src/App.vue 文件,而 App.vue 中打的断点就是通过 CDP 调试协议进行通信的。

打断点的 7 种方式


VSCode Debugger 调试 Node.js

TODO

VSCode Node Debugger 配置

TODO

调试 npm scripts

TODO

调试 ESLint、Babel、TypeScript 的源码,Nest.js 源码。

TODO

Chrome DevTools

如何调试移动端网页

移动端网页调试离不开代理,所以我们还会学习 Charles 的使用。

调试工具的原理

Chrome DevTools 的实现原理

实现 mini puppeteer