【前端】vue+vscode斷點調試詳解

前言

  • 非開箱即用,僅做好奇心知足、複雜項目中自定義斷點配置、下個項目中不求人不百度當即斷點調試
  • 涉及面較寬,須要必定經驗,且各處均不會太深刻(我也菜)
  • 若是你處處搜索但始終解決不了: vscode沒法鏈接上頁面、提示未驗證斷點(灰空心圓)、斷點漂移亂飛到其餘行、斷點實際中斷時所在位置不對、單步跳過執行時去到奇怪的位置,那麼這裏可能解決問題

js如何斷點

如圖↑,直接sources面板中打斷點。
若在第6行的空行打斷點,看到一個動畫顯示斷點從第六行溜到第七行。vscode的debugger擴展實質就是與這個通訊,並反饋結果到本身的ui上。所以若是你看到vscode中用鼠標打的斷點與顯示不一致,那麼實際上是瀏覽器就是這樣作的,只是vscode少了過渡動畫,並非vscode的bug,是設定。

SourceMap

阮一峯老師的講解:JavaScript Source Map 詳解
簡單來講,SourceMap可以讓壓縮/翻譯過的最終版的各類文件與原來未壓縮過的文件對應起來。那麼斷點邏輯容易理解:
1.給瀏覽器提供未壓縮的源碼和SourceMap文件
2.瀏覽器跑最終版本的js代碼時,經過SourceMap找到對應源碼的位置,若是該對應源碼處被用戶打上了斷點標記,那麼中斷
javascript

同時:
1.僅在你F12打開開發者工具後,瀏覽器纔會去加載最終版代碼指示的SourceMap文件(所以基本不影響普通用戶加載速度),再根據SourceMap文件指示去加載源碼。以下圖的文件↓ php

2.線上環境中,能把SourceMap文件也放上去,但不可能把源碼也放到服務器。即SourceMap指向源文件位置爲 /a.js時,瀏覽器會加載 協議://域名/a.js,顯然線上沒有此文件。但咱們能夠經過瀏覽器Sources->Filesystem添加文件夾映射,即映射到本地項目的源碼中進行斷點調試。固然瀏覽器窗口會給出相應的ui反饋↓
3.關於這個具體的映射規則,就是把Filesystem裏面添加的若干個文件夾視做網站根目錄,瀏覽器自動根據目錄結構和文件名尋找對應的文件。但這並不意味你能夠隨意對應,好比新建一個相似的目錄結構並放入空內容的App.vue文件,瀏覽器並不會將它和源文件關聯起來。另外視乎SourceMap的質量(如webpack中有多種生成方式,詳略程度不同),可能存在部分映射信息缺少、模塊合併後各處代碼指向同一個源碼位置等等,致使如文章前言提到的各類奇怪表現。
4.若是這裏服務器中和本地Filesystem中有一樣的源碼文件,那麼瀏覽器以本地Filesystem的爲準。即忽略從服務器中獲取的源碼文件,而使用本地Filesystem的文件做SourceMap映射的源文件

vue中配置SourceMap

其實是設置webpack配置中的devtool:'source-map'選項。這裏具體位置出入較大,你多是@vue/cli初始化的項目、使用webpack的vue模板構建的項目、項目負責人自行從新組織過的項目等,這裏就請自行了解到哪配置webpack了。html

注意:這個devtool:'source-map'能夠說是必須的,其餘生成SourceMap的方式都不太適合斷點而適合分析,不然因爲上述緣由出現各類奇怪表現。vue

webpack提供的本地服務器

在最完整的SourceMap設置下你應該能看到這個結構(a.js是我額外加進去的,不用管)↓ java

1.先說下這個 webpack://,這個就是webpack自定義的網絡應用層協議,跟 http://https://同樣道理。
2.在這個自定義應用層協議中,能夠省略域名(相似於ftp)即 webpack:///路徑。另外 .真的就是一個文件夾 ,不表明當前目錄(http協議中 https://juejin.im/timelinehttps://juejin.im/./timeline一回事)
3.如圖, webpack:///src中通常是咱們的原始vue文件, webpack:///./src是部分處理事後的vue和png等資源
4.webpack本地服務器把編譯後資源直接放在內存中,你看不到有編譯後的本地文件。所以你可能須要先build一下看看咱們的最終打包出來的 app.js和他的 app.js.map有些什麼↓
(1) app.js文件中最後一行會是 //# sourceMappingURL=app.js.map,當咱們打開開發者工具,瀏覽器就會去加載這個map文件。
(2) app.js.map裏面應該有這樣幾行:

"version":3,
  "sources":[
    "webpack:///src/app.js",
    "webpack:///./src/app.js",
    ...
  ]
複製代碼

也就是這個SourceMap可以把編譯後的代碼映射到sources中指示的若干個js源文件的對應位置。
(3)瀏覽器能夠看做一個強大的IDE,此時咱們能夠在開發者工具的source面板找到這些文件,並打上斷點進行調試node

vscode中調試

實質上vscode調試,就是經過調試擴展鏈接瀏覽器以獲取調試信息,同時經過本身的ui和交互讓咱們感受不到在使用上述瀏覽器功能。所以若是你發現vscode中調試很奇怪,那麼按前面步驟去看看瀏覽器中能不能正常斷點調試,若是瀏覽器中表現也是這麼奇怪,那麼無論你vscode怎麼配置基本都是徒勞的。理清思路後,進入核心主題(須要安裝Debugger for Chrome 這個擴展)webpack

chrome須要的準備功夫

本身命令行啓動或者快捷方式,追加啓動參數--remote-debugging-port=9222,這個是讓chrome打開9222調試端口,咱們的vscode擴展會經過這個端口獲取瀏覽器提供的調試信息。下面vscode會以attach方式鏈接,所以請先啓動瀏覽器,本地跑你的vue項目,並打開目標頁面。ios

Normally, if Chrome is already running when you start debugging with a launch config, then the new instance won't start in remote debugging mode.git

注意,若是你已常常規啓動chrome,那麼再啓動一個chrome通常狀況下他不會以遠程調試模式啓動。所以attach方式請關掉全部chrome實例,而且從新以遠程調試模式啓動一次(如上面參數,能夠直接訪問http://localhost:9222看看有沒有迴應)github

強制配置的參數

  • type - the type of debugger to use for this launch configuration. Every installed debug extension introduces a type: node for the built-in Node debugger, for example, or php and go for the PHP and Go extensions.(大意是說每一個調試擴展都向vscode註冊了一個type,vscode根據你設置的type的值去通知不一樣擴展進行工做)
  • request - the request type of this launch configuration. Currently, launch and attach are supported.(目前只有兩個容許值。在咱們這個狀況下,launch表示啓動瀏覽器打開目標頁面並attach;attach即直接鏈接到當前瀏覽器的目標頁面)
  • name - the reader-friendly name to appear in the Debug launch configuration drop-down.(這個配置的名字。實際就是用來切換多種不一樣配置的調試)

來源:Debugging

經常使用的可選參數

可選參數並不統一,需查看各個擴展說明。一些絕大部分擴展都支持的參數官網有說明,不重複了。下面是attach方式中這個擴展經常使用的參數:

  • url: On a 'launch' config, it will launch Chrome at this URL.(目標url。若是是launch模式,會直接啓動瀏覽器打開這個頁面。而後attach這個頁面,即至關於在這個頁面啓動開發者工具)
  • urlFilter: On an 'attach' config, or a 'launch' config with no 'url' set, search for a page with this url and attach to it. It can also contain wildcards, for example, "localhost:*/app" will match either "http://localhost:123/app" or "http://localhost:456/app", but not "stackoverflow.com".(上面那個url只能精確匹配,這個則容許使用通配符,看它的例子)
  • sourceMaps: By default, the adapter will use sourcemaps and your original sources whenever possible. You can disable this by setting sourceMaps to false.(默認爲true。可看成上面提到的把目錄加入Filesystem)
  • webRoot: 設置${webRoot}變量。${webRoot}是下面兩個參數的默認設置用到的變量,從而使得該參數具備意義
  • pathMapping: This property takes a mapping of URL paths to local paths, to give you more flexibility in how URLs are resolved to local files. "webRoot": "${workspaceFolder}" is just shorthand for a pathMapping like { "/": "${workspaceFolder}" }(實際上做用基本同下面,區別主要是人類「語義」上的區別和默認的設置不一樣。常規文件映射用這個,map文件映射用下面那個,但沒有嚴格區分)
  • sourceMapPathOverrides: 下面會詳細說。可簡單理解爲如何設置當前目錄到Filesystem進行映射

來源:vscode-chrome-debug

變量

  • ${workspaceFolder} - the path of the folder opened in VS Code
  • ${workspaceFolderBasename} - the name of the folder opened in VS Code without any slashes (/)
  • ${file} - the current opened file
  • ${relativeFile} - the current opened file relative to workspaceFolder
  • ${fileBasename} - the current opened file's basename
  • ${fileBasenameNoExtension} - the current opened file's basename with no file extension
  • ${fileDirname} - the current opened file's dirname
  • ${fileExtname} - the current opened file's extension
  • ${cwd} - the task runner's current working directory on startup
  • ${lineNumber} - the current selected line number in the active file
  • ${selectedText} - the current selected text in the active file
  • ${execPath} - the path to the running VS Code executable

來源:Variables Reference 這個點進去看他舉例就能理解了,不翻譯了。

sourceMapPathOverrides

設置如何映射。下面是它的默認設置

// Note: These are the mappings that are included by default out of the box, with examples of how they could be resolved in different scenarios. These are not mappings that would make sense together in one project.
// webRoot = /Users/me/project
"sourceMapPathOverrides": {
    "webpack:///./~/*": "${webRoot}/node_modules/*",       // Example: "webpack:///./~/querystring/index.js" -> "/Users/me/project/node_modules/querystring/index.js"
    "webpack:///./*":   "${webRoot}/*",                    // Example: "webpack:///./src/app.js" -> "/Users/me/project/src/app.js",
    "webpack:///*":     "*",                               // Example: "webpack:///project/app.ts" -> "/project/app.ts"
    "webpack:///src/*": "${webRoot}/*",                    // Example: "webpack:///src/app.js" -> "/Users/me/project/app.js"
    "meteor://💻app/*": "${webRoot}/*"                    // Example: "meteor://💻app/main.ts" -> "/Users/me/project/main.ts"
}
複製代碼

其中的${webRoot}是咱們自定義值的一個變量。你須要作的,就是保證webpack:///下的各類文件能被正確映射到咱們的開發目錄文件。實際就是設置Filesystem(這個某些狀況下可右鍵自定義如何映射到網絡資源,不展開了)
注意:sourceMapPathOverrides一旦被自定義設置,那麼原來的默認設置無效(就是被從新賦值的意思);存在多個匹配時,後面出現匹配的覆蓋前面存在的匹配。

總結

搞了一大堆,其實就是這麼幾個意思:
1.chrome遠程調試模式啓動,先確保你知道是哪一個端口可被vscode鏈接、確保你能在F12裏面斷點不會有奇奇怪怪的現象
2.vscode建立調試,在launch.json中,點擊右下角的添加配置,更改端口port爲上面你啓動的端口
3.設置url或者urlFilter參數(attach要求你已經打開了這個url對應的頁面。launch方式就是多了自動幫你打開這個頁面,沒多大區別)
4.設置webRoot參數,由於默認的sourceMapPathOverrides中用到了${webRoot} 這個變量
5.等一會,attach上目標頁面後,vscode底部欄會變色,能夠了。熱更新後有問題請刷新頁面
6.理解爲重,最多見錯誤是webRoot與sourceMapPathOverrides胡亂設置沒有對應上。通常而言,只要你的vue項目是工做目錄下有個src文件夾,裏面有main.js、App.vue這樣結構的話,那麼最小化的配置只要6個參數:

{
    "type": "chrome",
    "request": "attach",
    "name": "hello world",
    "port": 9222,
    "webRoot": "${workspaceFolder}/src",
    "url": "http://localhost:8080"
}
複製代碼
相關文章
相關標籤/搜索