Stories

Detail Return Return

vscode調試技巧 - Stories Detail

由於圖片和格式解析問題,可前往 閲讀原文

在現代前端與全棧開發的日常工作中,代碼調試是不可或缺的一環,而一款優秀的調試工具能夠顯著提升開發效率,減少問題定位的時間成本。Visual Studio Code(簡稱 VSCode)作為一款備受開發者喜愛的輕量化編輯器,不僅提供了豐富的插件生態和高效的代碼編輯體驗,更以其強大的調試功能成為開發者工作流中不可或缺的一部分

無論是調試 Node.js 後端代碼、前端瀏覽器代碼,還是更復雜的容器化微服務系統,VSCode 都提供了靈活的調試支持。而這種強大的調試能力,並不僅限於簡單地設置斷點或查看變量,更體現在其對多種語言、運行時環境的無縫支持以及對調試配置的高度自定義能力上。通過掌握 VSCode 調試工具,開發者不僅能夠輕鬆解決代碼問題,還可以培養更系統化的調試思維,提升整體開發質量

在接下來的內容中,我們將圍繞 VSCode 的調試功能展開深入剖析,從基本的斷點設置到複雜的調試場景,帶您全面解鎖 VSCode 調試的潛能,助力高效開發

調試界面

和大多數調試器的功能模塊界面基本上一致,包含:執行器、變量、執行棧、調試終端等等,比較簡單這裏就不多做介紹了;如果你對調試面板的操作步驟還不是很熟悉,可以看我的往期文章或者「vscode調試基本介紹」

調試分類

vscode支持多種形式的調試,從調試配置的複雜度來劃分,可以分兩大類:簡單、複雜;

簡單的調試可以快速的進入調試,無需關心過多的外在因素,通常這類的調試偏向於簡單、無需相關工具輔助之類的項目,如:簡單的原生js工程、NodeJS工程等等。簡單的調試這裏會介紹:auto attachJavascript Debug Terminal

而相對複雜的工程就不能使用這種模式了,當然也要具體的場景。面對複雜的場景,vscode提供了launch.json配置文件來定製化debug的功能,可以很方便的適配到不同的應用場景

Auto attach

auto attach顧名思義就是自動鏈接的意思,也就是當程序啓動debug模式時,vscode就會自動連接到目標debug,然後根據vscode提供的調試UI進行調試

若要使用此功能需要在vscode中開啓配置,cmd+shift+p 輸入 >Debug: Toggle Auto Attach 後回車,支持多種形式的選項,大體分為:

  • always:當程序啓動debug時總是自動連接上
  • flag:當監聽到 --inspect--inspect-brk 時才自動連接
  • disabled:禁止
注意:當選擇相關配置後,可能需要重啓IDE

下圖中小編啓動的是flag模式,在IDE底部欄會有對應的顯示,然後在終端輸入 node --inspect script 啓動程序,此時IDE就會自動連接上目標debug

可能心細得同學就已經發現了,當使用調試模式運行程序後,調試器會啓動一個ws服務,為什麼會有這個東西❓也有同學會疑問為啥vscode就能自動鏈接上目標debugger呢❓並且可以調試程序呢❓

現在讓我們打開chrome瀏覽器並輸入 chrome://inspect/#devices 打開調試TAB,會發現我們的目標程序,當點擊 inspect 後會打開一個 Dev Tool 並且也可以調試目標程序

通過Chrome鏈接基本上可以肯定的是,調試UI會通過ws進行調試數據的傳輸,而vscode之所以會自動鏈接一定做了相關事件監聽或者觸發。後面部分我們會揭曉調試UI和目標Debugger之間的數據傳輸原理

如果沒看到目標程序,需要將啓動node程序後的ws服務ip和端口配置到 Discover network targets 即可

Javascript Debug Terminal

如果説上面的auto attach調試方式已經足夠簡單,那麼Javascript Debug Terminal可以説是更加傻瓜式調試,簡直有手都會系列‼️讓我們來看看怎麼個簡單法

只需要打開Javascript Debug Terminal終端,然後像往常一樣啓動程序一樣:

  1. 打開對應的終端
  2. 啓動程序
vscode對於調試的友好性已經考慮到非常周全了

到這裏就將簡單形式的調試已經介紹完畢了,確實很簡單,很時候一些需要快速、簡單的調試場景,當然,實際場景中往往程序都是以複雜的工程出現的,那麼這種簡單的調試模式可能就不適用了,接下來看看vscode是如何支持複雜性工程的調試的

Debug Configuration

在 Visual Studio Code(VSCode)中,Debug Configuration(調試配置)是調試功能的核心。它允許開發者根據項目需求自定義調試環境、參數和行為。調試配置通常存儲在項目的 .vscode/launch.json 文件中,通過 JSON 格式定義調試任務

創建launch.json文件有多種方式,支持手動、可視化等等,你可以打開Debug擴展,然後根據提示創建對應的文件:

在選擇debugger時選擇我們熟悉的node、chrome都行,最終都是可以通過配置文件調整

一個典型的 launch.json 文件由以下部分組成:

{
  "version": "0.2.0", // 配置文件的版本號,固定為 0.2.0
  "configurations": [
    // 調試任務列表
    {
      "type": "node", // 調試類型,例如 "node", "python", "chrome"
      "request": "launch", // 調試請求類型:"launch"(啓動程序)或 "attach"(附加到運行的進程)
      "name": "測試NodeJS", // 調試任務的名稱,顯示在調試面板中
      "program": "${workspaceFolder}/index.js", // 主程序文件路徑
      "cwd": "${workspaceFolder}", // 當前工作目錄
      "env": {
        // 環境變量
        "NODE_ENV": "development"
      },
      "args": ["--verbose"], // 啓動參數
      "port": 9229 // 調試所需的端口(僅部分配置需要)
    }
  ]
}

配置文件模式最大的區別就是type,總體來説它把調試劃分成兩大分類:

  • launch:以調試模式啓動程序
  • attach:附加到正在運行的Debuger進程

創建配置

launch.json中可以快速創建對應類型的配置,vscode給了對應的配置

輸入花括號後會有對應的提示

也點擊右下角的Add COnfiguration按鈕

Task

在正式介紹調試配置文件前,先來介紹下Task;這又是什麼❓在 VSCode 中,Task 是一個功能強大的任務管理工具,用於執行各種自動化操作,例如運行構建工具、執行腳本、啓動開發服務器、或調用外部命令。通過配置 Task,可以將常用的命令集成到 VSCode 中,大幅提升開發效率

説明了就是可以幫助我們執行一些自動化的任務,如:腳本、npm等等,結合調試就可以做一些自動化的東西。比如,我們需要調試一個目標程序前,可能需要將其編譯才行,那麼就可以將編譯的任務交給Task,調試配置文件也確實提供了對應的屬性:postLaunchTaskpreLaunchTask

{
  // postLaunchTask ...
  "preLaunchTask": "tsc: build" // 定義的 task 的 label 值
}

那麼如何配置task呢,可以通過輸入對應命令生成:.vscode/tasks.json

可以根據具體的場景調試配置:

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "typescript",
            "tsconfig": "ts-examples/tsconfig.json",
            "problemMatcher": [
                "$tsc"
            ],
            "group": "build",
            "label": "tsc: build"
        }
    ]
}

接下來我們來看兩大調試方式吧

attach

attach調試比較簡單,就是鏈接到對應的目標Debugger調試程序進程上,以下是一個attach例子,通過attach方式鏈接到9229端口目標調試器上

{
  "name": "Attach NodeJS Break Debugger",
  "port": 9229,
  "address": "localhost",
  "request": "attach",
  "skipFiles": [
    "<node_internals>/**"
  ],
  "type": "node"
}

當我們在終端以調試的方式啓動程序後,在調試插件界面,啓動這個調試後就會自動鏈接上目標調試器:

這個其實和前面介紹的auto attach 以及用 Chrome 進行調試道理是一樣的

此模式下也包含很多相關的屬性配置,這裏簡單列舉幾個:

  • outFiles:源文件輸出的目標文件,一般對於編譯文件,vscode會自動匹配來做sourcemap映射
  • resolveSourceMapLocations:用於指定調試器在解析源映射(Source Maps)時可以加載的文件路徑或 URL
  • continueOnAttach:用於控制調試器在附加到正在運行的進程時,是否自動繼續執行程序,如:--inspect-brk模式調試時的場景

launch

如果説到這裏還覺得配置文件方式的調試也比較的話,那麼launch模式調試就會多樣化了,我覺得它可以代表配置文件調試的核心,此種模式功能有很多

launch顧名思義就是啓動的意思,的確它通過配置文件告訴vscode以debug形式啓動目標程序,然後自動鏈接到調試UI上,這種模式自動化完成了啓動與連接的過程

launch支持多種啓動程序的方式,下面是常用形式:

  • url:通常是啓動瀏覽器打開對應的地址
  • program:指定啓動的應用程序文件
  • runtimeExecutable:通過執行器執行,如:npm、yarn、pnpm等等,這些執行器必須能正常使用

url

此種方式會直接打開設置的url,vscode內部會根據內置的策略將頁面通過sourcemap與源碼關聯起來,如果程序需要編譯但沒有提供對應的sourcemap,將無法進行調試,此時打的斷點都是灰色的

{
  "name": "Launch Chrome",
  "request": "launch",
  "type": "chrome",
  "url": "http://localhost:8082",
  "webRoot": "${workspaceFolder}"
}

請注意:以上url服務需要提前運,這裏使用 http-server 指定 8082 端口運行

program

program則指定vscode要運行的程序文件,比如運行node程序main.js

{
  "type": "node",
  "request": "launch",
  "name": "Test Launch Debugger",
  "args": ["author=ihengshuai"],
  "program": "${workspaceFolder}/node/index.js",
  "env": { "website": "https://blog.usword.cn" }
}

此種形式通常可以搭配argsenv提供相關的參數變量等等

同樣的如果程序也需要轉義,請提供相關的sourcemap

runtimeExecutable

runtimeExecutable 用於指定調試程序的運行時可執行文件,該字段通常用於指定運行調試目標所需的特定運行環境,例如 Node.js 的可執行文件、Python 解釋器或其他自定義的可執行程序

{
  "type": "node",
  "request": "launch",
  "name": "Test Launch Debugger",
  "skipFiles": [
    "<node_internals>/**"
  ],
  "cwd": "${workspaceFolder}/node",
  "args": ["author=ihengshuai"],
  "runtimeExecutable": "npm", // 使用npm啓動
  "runtimeArgs": ["run", "debug", "github=ihengshuai"], // npm 後面的參數, npm run debug
  "env": { "website": "https://blog.usword.cn" }
}

此種方式的效果圖和以上基本一致

重要的屬性

launch方式調試有多種屬性可以選擇,這裏我們列舉幾個

  1. args:用來給目標程序傳遞對應的變量
  2. cwd:指定啓動目標程序的基本路徑,一般都會在項目的根目錄,如果對於多倉庫項目,可以你可以指定對應的文件路徑
  3. runtimeArgs:傳給runtimeExecutable 的參數,比如對應的執行腳本命令:build、lint等等
  4. env和envFile:環境變量,和.env配置文件定義類似
  5. console:啓動程序的終端,默認是debug終端,如果對於程序執行過程中一些特殊要求,你可以選擇vscode終端或者外部的終端,有internalConsoleintegratedTerminalexternalTerminal幾個配置
除了這些屬性配置外,可以很多其他的屬性選項,請結合不同的type提示選擇使用對應的屬性

設置sourcemap

對於大多數的真實場景來説,都會是基於各種打包器的比較複雜的大型工程,那麼生成的文件都會是經過壓縮或者含義後的內容,而調試則需要對應sourcemap的支持,這樣才能和源碼映射起來

配置文件提供了sourcemap相關的配置:

  • sourceMaps:默認為true,啓用sourcemap
  • outFiles:用於指定編譯後的文件路徑的位置,調試器會使用這些文件來加載 Source Map
  • webRoot:用於指定 Web 應用的根目錄
  • sourceMapPathOverrides:用於覆蓋和重映射源代碼路徑,當 Source Map 文件中記錄的路徑與實際文件路徑不一致時,通過此字段解決路徑匹配問題
  • resolveSourceMapLocations:控制調試器加載 Source Map 文件的路徑範圍

比如我們基於webpack進行路徑映射的調整:

{
  "sourceMapPathOverrides": {
    "webpack:///./*": "${webRoot}/src"
  },
}
注意:以上只是簡單的一個例子,請根據具體的項目場景設置

分組調試

vscode支持將多個調試分組,可以按組運行調試器

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Chrome Browser",
      "request": "launch",
      // ...
    },
    {
      "name": "Launch Node Server",
      "type": "node",
      // ...
    },
  ],
  "compounds": [ // 定義組
    {
      "name": "Run Debugger",
      "configurations": ["Launch Chrome Browser", "Launch Node Server"]
    }
  ]
}

到這裏基本上將vscode的調試功能講完了,接下來我們來幾個真實的調試案例

調試案例

調試Vue源碼

配置好調試,終端啓動對應的服務腳本:

啓動debug會打開對應的瀏覽器,這裏我們點進對應的文件目錄和文件:

在對應的源碼文件中打斷點:

調試NodeJS

{
  "name": "Test Express App",
  "request": "launch",
  "runtimeArgs": [
    "run-script",
    "express-app"
  ],
  "runtimeExecutable": "npm",
  "skipFiles": [
    "<node_internals>/**"
  ],
  "type": "node"
}

調試NestJS

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Test NestJS",
      "request": "launch",
      "runtimeArgs": [
        "run-script",
        "start:dev"
      ],
      "runtimeExecutable": "pnpm",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "type": "node"
    }
  ]
}

調試Typescript

由於目標程序是ts,所以需要sourcemap的支持,上面我們講了幾種方式配置

{
  "name": "Launch Typescript",
  "type": "node",
  "request": "launch",
  "skipFiles": [
    "<node_internals>/**"
  ],
  "program": "${workspaceFolder}/ts-examples/demo1.ts",
  "outFiles": [
    "${workspaceFolder}/ts-examples/dist/*.(m|c|)js",
    "!**/node_modules/**"
  ],
}

調試SSR

ssr有服務端和前端,我們可以使用組合方式進行調試,頁面通過啓動瀏覽器的方式進行調試,node端通過腳本形式啓動服務,這樣就可以調試了

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Chrome Browser",
      "request": "launch",
      "type": "chrome",
      "url": "http://localhost:10011",
      "webRoot": "${workspaceFolder}/client",
      "sourceMaps": true,
    },
    {
      "name": "Launch Node Server",
      "type": "node",
      "request": "launch",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["dev"],
      "sourceMapPathOverrides": {
        "webpack:///./*": "${webRoot}/src"
      },
    },
  ],
  "compounds": [
    {
      "name": "Run Debugger",
      "configurations": ["Launch Chrome Browser", "Launch Node Server"]
    }
  ]
}
切記soucemap支持

調試其他語言

vscode不光支持js語言的調試,同時它也支持其他語言的調試,如:Java、C#、Python等等,如果你需要調試其他語言,可以下載對應的語言的調試插件 Debug Extensions Marketplace

核心原理

從上面的attach模式我們就知道目標程序啓動debug模式後,可以和不同的調試UI進行連接通信,然後完成一系列的調試,而調試的核心就是debugger和UI進行數據通信的形式,只要兩端根據協商好的協議進行數據的傳輸,就可以完成一系列操作

Chrome DevTools Protocol(CDP)

Chrome DevTools Protocol (CDP) 是由 Google 提供的一套調試協議,用於調試、診斷、分析和操作運行中的 Chrome 瀏覽器或其他基於 Chromium 的環境。它允許開發者通過遠程調用控制瀏覽器的行為,比如攔截網絡請求、調試 JavaScript、操作 DOM、性能分析等

開啓Protocol Monitor

查看Protocol Monitor

Debug Adapter Protocol (DAP)

VSCode 使用 Debug Adapter Protocol (DAP) 作為調試的標準協議。由於vscode支持多種語言的調試,因此中間使用適配協議,不同語言的調試器是要對接了對應的適配器數據定義,就可以完成數據通信

你也可以直接閲讀官方的「Debugging Architecture of VSCode」

參考文檔

  • debugging
  • typescript-debugging
  • nodejs-debugging
  • vscode-js-debug options
  • vscode debug recipes
  • vue webpack5 debuggers

由於圖片和格式解析問題,可前往 閲讀原文
user avatar cyzf Avatar freeman_tian Avatar sunplay Avatar chongdianqishi Avatar woniuseo Avatar licin Avatar yuhuashi_584a46acea21f Avatar nzbin Avatar yuxl01 Avatar jinl9s27 Avatar tangzhiyuan Avatar baidujiagoushi Avatar
Favorites 50 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.