一、安裝VSCode和Node.js
記錄環境配置:本文配置的環境主要針對單獨JS文件的斷點調試,主要是為了調試LeetCode里面的代碼。
首先在官網下載對應的版本:https://nodejs.org/en/
開始安裝,可以自定義選擇安裝路徑。
這里選擇Add Path,系統變量會自動設置,但是用戶變量并沒有自動設置,需要的話可以自己手動加一下。
測試是否安裝成功,在命令行輸入node -v和npm -v,如果能顯示出版本號說明安裝成功,且已經有了正確的環境變量。
? ? ? ?用戶變量最好也手動自己添加一個比較穩妥,因為我之前沒有加,有時候在VSCode中會出現node.js找不到路徑的情況,雖然重啟會解決問題,但是彈了兩次我總覺得還有些不對勁,所以就還是加了一下,大家在安裝的時候最好提前加一下。
到這里,Node.js安裝完成
二、VSCode配置
先在VSCode里面安裝兩個插件,一個是負責運行的Code Runner,一個是JS的語法提示JavaScript(ES6) code snippets。
原文鏈接:Luminary_aurora https://blog.csdn.net/qq_40197828/article/details/123930432
創建json file
Debug with VSCode
描述了在VS Code中怎樣充分利用其強大的debug功能來調試web項目和源碼調試(TypeScript)
原文:Debug with VSCode - 知乎
背景
之前在看一些github源碼的時候看調試數據是非常非常吃力,不知道多少時間消耗在了console,rebuild,switch tab的這幾個頻率最高的步驟中,著實煩躁。首先回顧一下我自己之前在看一些庫源碼的過程,以rollup這個打包庫為例,首先git clone
下來,npm install
后發現它也自動執行了打包過程,看了下package.json
文件中的scripts字段,其中有prepare腳本命令,npm在執行npm install
后就會自動執行這個script,這個命令又指向了npm run build
,進而進行了自動打包過程。通常我都會在這個project下執行npm link
然后重新重建個文件夾寫自己的一些例子項目link到前面的project,這樣看project下的源碼或者console之后重新build,就能在例子項目實時能夠調試到,其中執行npm run watch
可以不用重新build。
這樣真的很累!...需要開兩個項目頻繁切換,消耗時間,還一點都不靈活!下面就研究了下VSCode中強大的Debug功能,讓我猶如坐上了火箭 ,并在此做個總結。
初識Debug Panel(牛刀小試)
下面是vscode中的debug panel
最左邊一列的第四個tab,之前的我看到過無數遍這個小蜘蛛,卻從來沒有打開過...,相信我,它會讓你打開新世界的大門。(command+shife+D
快捷打開此面板)
方便這節后面的演示,用VSCode打開一個空目錄取名Hello,下面新建一個app.js,寫個最簡單的代碼如下:
var hello = "Hello World"
console.log(hello)
然后點擊小蜘蛛進入到debug面板,點擊 下面的小齒輪圖標
如果你的項目根目錄下有.vscode目錄且下面有launch.json配置文件,則點擊上面的小齒輪按鈕會直接打開此 launch.json配置文件
這時會出現如下,讓你選擇調試環境,VSCode內置了Node.js環境,可以在插件tab安裝其他語言的擴展,VSCode支持各種語言的調試,eg:PHP,Python,go,C/C++...我們直接選擇Node.js環境
選擇后會直接打開一個launch.json文件并有如下配置:
{"version": "0.2.0","configurations": [{"type": "node","request": "launch","name": "Launch Program","program": "${file}"}]
}
按command+shift+E
回到目錄列表會看到多了一個.vscode目錄,下面就是該launch.json文件,可以點擊右下角的Add Configuration按鈕,會彈出如下配置供選擇,在這個配置文件里可以充分利用它的智能感知功能,我們選擇Node.js: Launch Program
它會自動幫我們生成該配置的常用項,我們將其中的"program": "${file}"
改為"program": "${workspaceRoot}/app.js"
,在這個配置有挺多的內置變量可以直接使用,${file}
就是當前所活躍的文件,${workspaceRoot}
表示當前項目的工作根目錄,完整的替換變量的列表可參考這里
在上面的配置字段中有個request
字段,有兩個值可以選擇:"launch"
和?"attach"
,它表示VS Code中核心的兩種調試模式。當時搞清這兩種模式區別的時候也是有點暈,這也是取決與你項目中的工作流是怎樣的,假如你調試的是web項目,通常你會在瀏覽器中已經直接打開項目了,這個時候我們可以使用attach模式,正如字面的意思,將debugger附加到你已經運行到的web項目,而launch就像字面意思是直接由編輯器啟動這個程序,比如啟動一個服務端項目或者上面我們的小例子,這個啟動模式編輯器會自動把debugger附加到這個程序中。launch config 就像是作為一種debug模式直接啟動app,而attach config 就像是debugger連接到正在運行的app。下面我們在web項目調試一節會有這兩種模式的直觀印象
在開始debug之前,我們先在app.js的第二行最左邊打一個斷點
configurations
里面的name字段會顯示在左邊Debug一欄最上面的下拉列表里,點擊小齒輪左邊的框就可以選擇剛才添加的配置,對應與configurations
里面的name字段,選擇Launch Program,然后點擊左邊的小綠色三角啟動debug(F5),然后就可以看到程序暫停在剛才打的斷點這行了
可以看到最上面的工具欄就是所有的調試操作:
- 繼續/暫停 F5
- 單步跳過 F10
- 單步調試 F11
- 單步跳出 ?F11
- 重啟 ??F5
- 停止 ?F5
左邊的調試欄也顯示出了程序里運行的所有變量,可以看到commonjs的模塊變量也顯示出來了__dirname,__filename,module,require...
global下面也有所有的全局變量,調用堆棧也顯示了程序中函數的調用順序,這樣你就可以在任何你想調試的地方打個斷點,這個地方的所有信息就全部暴露出來了。下面我們可以看看怎樣來調試web項目
調試web項目
我們用create-react-app官方腳手架創建一個簡單app項目,在終端運行如下命令:
npx create-react-app debug-react # npm 版本5.2以上
cd debug-react
npm start
可以看到瀏覽器自動打開并運行了這個簡單web項目,為了方便調試看到效果,我們將App.js代碼稍加改動如下:
// App.js
// ...
function App(props) {const {link,text,} = props // 這行打個斷點return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href={link}target="_blank"rel="noopener noreferrer">{text}</a></header></div>);
}
// ...
相應的index.js改動如下:
// index.js
// ...
ReactDOM.render(<Applink="https://reactjs.org"text="hello world"/>,document.getElementById('root')
);
// ...
保存后瀏覽器自動刷新了,可以看到只是將渲染數據提取出來以props形式從父組件傳入,接下來我們進行debug的配置
調試web項目需要安裝一個利器,打開VS Code左邊的擴展欄 ??X ,然后輸入chrome,選擇并點安裝?Debugger for Chrome
?擴展,安裝完后進入左邊debug欄點擊小齒輪 F5 在彈出的選擇環境的下拉列表框中選擇 chrome ,然后會自動打開Launch.json配置文件并有如下配置:
{"version": "0.2.0","configurations": [{"type": "chrome","request": "launch","name": "Launch Chrome against localhost","url": "http://localhost:3000","webRoot": "${workspaceFolder}"}]
}
你必須指定一個 url 或者 file 配置項啟動瀏覽器,以上配置的url就是指向我們最上面的debug-react項目的本地服務url。如果指定了url,就要設置webRoot字段,其表示一個絕對路徑指示本地服務的文件來自哪里,比如以上的webRoot配置會解析http://localhost:3000/index.js
成為類似/Users/me/debug-react/app.js
所以確保它設置正確
在啟動調試之前確保之前的本地服務是跑著的,然后按 F5 啟動debug調試,可以看到VS Code啟動了個新的瀏覽器窗口,如果程序并沒有停在之前的斷點處,可以在刷新一下調試 ??F5 ,可以看到如下效果了:
相應的props和相關變量都可以在debug欄清晰的看到,都不用去看瀏覽器的調試了。
注意到上面的chrome調試配置的 request 類型是 launch,我們還可以嘗試另一種調試方式,也就是"request": "attach"
的調試方式,打開Launch.json配置文件,點擊右下角的Add Cogfiguration選擇Chrome: attach
, VS Code自動生成了系列配置如下:
{"type": "chrome","request": "attach","name": "Attach to Chrome","port": 9222,"webRoot": "${workspaceFolder}"
}
要進行遠程調試必須的打開chrome的遠程調試功能,并設置以上默認配置的遠程調試端口,如下:
- Mac:
在終端運行/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
, 會直接運行一個新的瀏覽器的窗口,然后將之前的debug-react項目重啟一下npm start
- Windows:
右擊桌面的chrome的快捷方式,點屬性=>目標框的后面添加--remote-debugging-port=9222
,或者在命令行下執行<path to chrome>/chrome.exe --remote-debugging-port=9222
,重啟一下debug-react項目
啟動調試 F5 ,可能會讓你選一個本地服務,選擇debug-react即可,可以看到已經開始了debug調試:
點擊以上綠色按鈕重啟一下,程序停在了斷點的位置上了。注意attach并沒有啟動一個新的瀏覽器窗口,而是在你原有啟動的窗口下開始了調試。將鼠標移到上圖橙色正方圖標上,顯示的是斷開連接,這也和之前我們所說的attach模式是把debugger連接到了已經啟動的app上的說法一致,它沒有像launch模式那樣每次啟動都會啟一個新的瀏覽器窗口。
在調試react項目的時候會經常遇到render階段數據還沒出來,這跟react的生命周期有關,往往我們會多點幾下單步調試或者單步跳過,其實打斷點的時候支持多種斷點,比如打條件斷點,日志斷點,函數斷點等等...可以自行研究下~至此,調試web項目就到這了,下面我們來看一下怎樣用此debugger科學的看那些庫源碼
源碼調試
正如背景里面所提到的,在未接觸VS Code的debugger之前,我看源碼的過程真的很苦逼...而且時常搞不清源碼中各個函數的調用棧順序,效率著實慢的著急,由此往往沒耐心往下看,也體會不到源碼里的思想精髓...
廢話不多說,這節我們以rollup源碼為例。建議花半分鐘可以去官網看看這是個什么,不過看不看無所謂也不是這節的重點。建議把此項目clone下來跟著步驟一起走。
打開項目,發現整塊源碼都是用TypeScript寫的(實踐你會發現在VS Code中用debugger配合TypeScript看源碼有多爽),VS Code可以調試任何可以編譯成javascript的語言,更不用說親兒子TS了。
看到項目目錄中是有自己的.vscode目錄中,打開看下launch.json是有關于debug test的配置的,我們先點右下角添加一個Node.js: Launch配置,先放在這。然后看下package.json文件的scripts字段下的命令,在背景里面也說了在install完成后會執行build腳本,我們可以看看build中有一段rollup -c
命令,這個命令就是典型的rollup打包命令,也就是說它以上一版本已經打包后的自已為依賴把自己的源碼進行了打包,那我們就去看下rollup.config.js文件(-c 是指根據根目錄下的rollup.config.js文件進行配置打包)。
打開rollup.config.js文件,主要是這三項配置:
/* Rollup core node builds */
{input: 'src/node-entry.ts',...,output: [{ file: 'dist/rollup.js', format: 'cjs', sourcemap: true, banner },{ file: 'dist/rollup.es.js', format: 'esm', banner }]
},
/* Rollup CLI */
{input: 'bin/src/index.ts',...,output: {file: 'bin/rollup',format: 'cjs',banner: '#!/usr/bin/env node',paths: {rollup: '../dist/rollup.js'}}
}
/* Rollup core browser builds */
{input: 'src/browser-entry.ts',...,output: [{ file: 'dist/rollup.browser.js', format: 'umd', name: 'rollup', banner },{ file: 'dist/rollup.browser.es.js', format: 'esm', banner }]
}
這是根據input文件打包到output的輸出路徑,可以看看package.json里面的files字段就對應與這里的output的輸出路徑,也就是最終發布到npm包里的所有代碼。我們先從Rollup CLI打包過程看起,它的input輸入文件是 bin/src/index.ts,這里的入口文件應該就是rollup -c
對應的執行源文件了,我們先在const command = minimist(...)
這行打個斷點。
既然bin/src/index.ts是最開始的rollup -c
開始的執行源文件,那我們將此添加至剛剛在launch.json新添加的配置里
{"type": "node","request": "launch","name": "Launch Program","program": "${workspaceFolder}/bin/src/index.ts", // 更換這里的路徑"args": ["-c"] // 傳給program的參數
}
注意我們加?了個args字段,這樣就模擬了rollup -c
命令,這時候若是按F5啟動debug,會報個錯無法啟動程序.../src/index.ts,提示設置"outFiles"屬性
。
就是說我們是以ts文件為入口的文件,VS Code需要編譯后的js文件對源ts文件的映射,也就是需要sourcemap文件的路徑,這樣才能對應與源碼的位置,可是我們看到只有dist目錄下的rollup.js文件有對應的sourcemap文件,這從上面的三項配置就可以看到只有Rollup core node builds
下的output下的file: 'dist/rollup.js',設置了sourcemap: true
,那我們給Rollup CLI
也設置一下:
/* Rollup CLI */
{input: 'bin/src/index.ts',...,output: {file: 'bin/rollup',format: 'cjs',banner: '#!/usr/bin/env node',paths: {rollup: '../dist/rollup.js'},sourcemap: true // 設置sourcemap}
}
這樣給launch.json也要設置對應的 outFiles 屬性outFiles: ["${workspaceFolder}/bin/*"]
, 這樣就能找到源文件的映射了。
我們改了rollup.config.js文件,那就意味著需要重新 run build 一下,在命令行執行npm run build
,可以看到bin目錄下有了新的rollup.map文件
然后F5啟動debug,你會發現程序停在最開始打的command斷點那個地方了,這樣你就可以尋著debug的腳步 探尋源碼之旅了,大功告成!
彩蛋
上面的源碼調試雖然成功了,可是它調試的是原有的npm run build
命令,也就是倉庫自己的一些rollup配置,我想調試自己寫的一些rollup配置該咋辦勒。。。?
其實前面的背景已經提到了這個問題,在clone的rollup目錄下執行npm link
,然后你在你自己寫的rollup配置目錄里執行npm link rollup
,這樣你在node_modules(先安裝好rollup依賴的其他依賴,可以先npm install rollup
,然后刪除node_modules里的rollup倉庫,link你clone的rollup)里就可以看到整個rollup的鏈接倉庫,在鏈接倉庫里打斷點,然后在按上面的步驟在你的例子項目里配置launch.json,這樣啟動你的debug,你會發現打的斷點沒用... ,程序沒有暫停過,這也是因為node_modules里的是symlinks,要使斷點起作用的話,得給launch.json加上運行參數:
{"runtimeArgs": ["--preserve-symlinks",// "--preserve-symlinks-main"]
}
如果你的program指向的也是個鏈接文件就也要加上"--preserve-symlinks-main"
參數,這樣就能正常調試你自己寫的配置了。(需要Node.js 10+)
在你調試的過程中進行單步調試的時候時常會進入一些node_modules里不想看的庫,或者會進入到node的內置模塊里,這些其實有時候沒必要看,我們就可以跳過這些文件,例如:
{"skipFiles": ["${workspaceFolder}/node_modules/**/*.js","${workspaceFolder}/lib/**/*.js","<node_internals>/**/*.js" // node內部核心模塊 設置的話在正常調試的時候可能有些問題。。。]
}
在前面調試源碼一節中我們修改了rollup源碼的配置文件并重新手動 run build 了一下,其實我們可以直接在launch.json配置文件中配置一個"preLaunchTask": "rollup"
,它表示在啟動debug調試之前運行一個任務,可以在.vscode文件夾下新建一個task.json,針對源碼調試那節我們可以寫如下配置:
{// See https://go.microsoft.com/fwlink/?LinkId=733558// for the documentation about the tasks.json format"version": "2.0.0","tasks": [{"label": "rollup","type": "shell","command": "npm run build"}]
}
然后在launch.json中配置"preLaunchTask": "rollup"
,這樣,我們就不用在debug之前手動去執行build,直接F5啟動debug就行。相應的還有postDebugTask
鉤子在debug結束后執行一些任務,關于任務的具體設置信息可以看這里
end
作者 @cslove
本文版權屬于再惠研發團隊,歡迎轉載,轉載請保留出處。
目錄
斷點調試
1. 簡介
2. 打斷點
3. 開始調試
4. 單步前進 - Step Into
5. 繼續單步前進-研究循環
6. continue, while
7. Step Out, Step Over
1. 簡介
在程序有BUG/缺陷,需要修復時,斷點調試是發現缺陷的重要方法。對于初學者而言,斷點調試還有另外一個用途:幫助理解程序背后的邏輯。
本文以下述程序為例,講述在Visual Studio Code中的斷點調試方法。
names = ['Peter Anderson', 'Frank Bush', 'Tom Henry','Jack Lee', 'Dorothy Henry']sName = "NOTFOUND"
for x in names:if x.endswith("Henry"):sName = xbreakprint(x, "not ends with 'Henry'.")print("I found a Henry:", sName)
2. 打斷點
在Visual Studio Code中打開相關代碼文件,用鼠標在行號3的左方空白處單擊(下圖紅點處),便會出現紅色的斷點-breakpoint。如果在相同位置再次單擊,斷點便會消失。在同一個程序中,斷點可以打很多個。
3. 開始調試
選擇Debug->Start Debugging菜單項,或者直接按下F5快捷鍵(使用筆記本的讀者注意:F5鍵可能同時復用了其它功能,需要配合Fn鍵使用);
然后在彈出的菜單里選擇Python File / Debug the currently active Python file;
調試過程啟動,程序開始運行,然后遇到了第3行的斷點,停了下來。請讀者注意,當前第3行是黃色高亮的,這說明程序執行完了1-2行,第3行處于等待執行狀態。
上圖的左方,VARIABLES/變量欄則列出了全部的LOCAL/局部變量。可以看到,作為第1行代碼的執行結果,名字為names的變量存在,其值為一個列表。因為第3行代碼尚未執行, 所以目前sName變量尚不存在。
4. 單步前進 - Step Into
在前圖的上方,有一個工具欄,其中,第三個按鈕(方向向下的鍵頭)的彈出標簽為Step Into(F11)。這個按鍵的作用為單步前行。按一下這個按鍵,或者直接按F11,會發現程序向前執行了一行,第4行變為高亮待執行。作為第3行代碼的執行結果,sName變量出現在左方VARIABLES欄中。如果把鼠標移至代碼中的sName上方,Visual Studio Code還會顯示sName變量的當前值為NOTFOUND。如下圖:
5. 繼續單步前進-研究循環
再次點擊Step Into, 第4行被執行,第5行變為高亮待執行。請讀者注意,根據for循環, x變量取值names列表的第1個元素,其值為'Peter Anderson'。
顯然,第5行的邏輯判斷不成立,第6,7行不會被執行。再次按下Step Into后,第8行高亮待執行:
Step Into執行第8行,下方控制臺會輸出相應的print結果,然后程序執行點回到了第4行,準備開始下一輪循環:
再次Step Into后,第5行高亮待執行。此時,x取值names列表的第2個元素,其值為'Frank Bush':
同樣,Frank Bush也不是Henry,第5行的邏輯判斷不成立,6,7不執行,第8行執行 ... 按Step Into兩次,程序重新回到第4行,準備開始第三輪循環:
再次按下Step Into, 第5行高亮待執行。此時,x取值names列表的第3個元素,其值為'Tom Henry'。請注意,VARIABLES欄中x變量的值。
這一次不一樣了,x以"Henry"結尾,所以第5行的邏輯判斷成立,再次按下Step Into,程序來到了第6行:
Step Into執行完第6行后,sName的值從'NOTFOUND'變成了'Tom Henry',程序停在了第7行:
按照語義,break語句執行將導致循環直接結束,第8行不會執行,剩下的names列表中的'Jack Lee', 'Dorothy Henry'會被忽略,程序直接來到第9行。由于第9行是空行, Visual Studio Code直接來到第10行。請讀者注意,根據縮進規則,第10行與第4行的for循環屬于同一層級,不屬于循環體內部代碼。
再次Step Into, 第10行執行結束,下方控制臺打印了“I found a Henry: Tom Henry。程序調試自動結束:
6. continue, while
希望上述調試過程可以幫助讀者理解for循環及break語句。
如果讀者對continue, while循環等感到疑惑,也可以對相關代碼進行調試研究。
7. Step Out, Step Over
Visual Studio Code的調試工具欄內,還有Step Out, Step Over等按鈕。不同于Step Into(單步前進), Step Out, Step Over用于在調試過程中避免過分深入函數或者循環內部。
本文節選自作者的B站MOOC及同名教材:
Python編程基礎及應用 — 重慶大學 高等教育出版社,作者親授_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com/video/BV1kt411R7uW
作者:海洋餅干叔叔并包含指向本頁面的鏈接。 Visual Studio Code中的Python程序斷點調試 - 知乎