前端遠端除錯

lucifer210發表於2018-02-25

原文刊登在我的github

除錯是開發過程很重要的過程,而隨著移動端的普及,移動開發也越來越多,並且由於移動端的諸多限制,使得除錯相對PC複雜很多。因此遠端除錯就顯得非常重要了。 近幾年,瀏覽器廠商也紛紛推出自己的遠端除錯工具,比如Opera Mobile 推出的Opera Dragonfly,iOS Safari 可以開啟Web檢查器在 Mac OS X系統中實現遠端除錯。Android 4.0+系統的 Chrome for Android可以配合 ADB(Android Debug Bridge)實現桌面遠端除錯,桌面版Chrome 32+已經支援免安裝ADB即可實現遠端除錯移動裝置頁面/WebView 。國內的UC瀏覽器開發者版也推出了自己的遠端除錯工具RemoteInspector。除了瀏覽器廠商之外,也湧現出許多第三方開發的遠端除錯工具,諸如支援全平臺除錯的Weinre等。

本文主要介紹遠端除錯是什麼,基本原理是什麼,有哪些情況,以及如何根據不同的情況選擇恰當優雅的除錯方式。

本地除錯

遠端除錯是相對於本地除錯來講的,那麼理解本地除錯對於理解遠端除錯是很重要的。 本地除錯指的是直接除錯執行在本地的APP。常見的就是除錯本地PC(很簡單)。 比如我在本地執行了一個webpack-dev-server,埠號為8080. 那麼訪問8080,並且開啟瀏覽器的開發者工具,就可以在本地進行除錯了。再比如我要除錯google的官網,那麼我只需要 訪問www.google.com, 同樣開啟開發者工具就可以進行本地除錯了。

遠端除錯

那麼遠端除錯就是除錯執行在遠端的APP。比如手機上訪問google,我需要在PC上除錯手機上執行的google APP。 這個就叫做遠端除錯。

遠端除錯大概有三種型別:

  • 除錯遠端PC(本質上是一個debug server 和 一個debug target,其實下面兩種也是這種模型,ios中間會多一個協議轉化而已) 這種型別下的debug target就是pc, debug server 也是pc。

  • 除錯android webpage/webview(很多方式,但安卓4.4以後本質都是Chrome DevTools Protocol的擴充套件) 這種型別下的debug target就是android webview,debug server 是pc。

  • 除錯ios webpag/webview(可以使用iOS WebKit Debug Proxy代理,然後問題便退化成上述兩種場景) 這種型別下的debug target就是ios webview, debug server 是pc。

chrome遠端除錯

提到chrome的遠端除錯,就不得不提chrome remote debug protocol。 它採用websocket來與頁面建立通訊通道,由傳送給頁面的command和data組成。chrome的開發者工具是這個協議主要的使用者,第三方開發者也可以呼叫這個協議來與頁面互動除錯。簡而言之,有了它我們就可以和chrome中的頁面進行雙向通訊。

chrome 啟動的時候,預設是關閉了除錯埠的,如果要對一個chrome PC 瀏覽器進行除錯,那麼啟動的時候,可以通過傳遞引數來開啟 Chrome 的除錯開關:

sudo /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
複製程式碼

這個時候就可以通過http://127.0.0.1:9222 檢視所有遠端除錯目標

http://127.0.0.1:9222/json 可以檢視特定的遠端除錯目標資訊,型別為json陣列。

[
  {
    "description": "",
    "devtoolsFrontendUrl": "/devtools/inspector.html?ws=127.0.0.1:9222/devtools/page/fefa.....-ffa",
    "id": "fefa.....-ffa",
    "title": "test",
    "type": "page",
    "url": "http://127.0.0.1:51004/view/:id",
    "webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/page/fefa.....-ffa"
  }
]
複製程式碼

其中id是一個唯一的標示,chrome dev protocol基本都依賴這個id。

比如關閉一個頁面:

http://localhost:9222/json/close/477810FF-323E-44C5-997C-89B7FAC7B158
複製程式碼

再比如啟用一個頁面:

http://localhost:9222/json/activate/477810FF-323E-44C5-997C-89B7FAC7B158
複製程式碼

具體可以檢視官方資訊。

webSocketDebuggerUrl是除錯頁面需要用到的WebSocket連線的地址。

比如我需要清空瀏覽器快取,就用websocket連線到該頁面之後呼叫send方法

const ws = new WebSocket('ws://127.0.0.1:9222/devtools/page/fefa.....-ffa')
ws.send('{"id": 1, "method": "Network.clearBrowserCache", "params": {}}')
複製程式碼

還有很多類似的api,因此就可以構造複雜的擴充套件

常見的遠端除錯框架對比

明白了遠端除錯的型別,那麼對於不同的型別應該採取什麼樣的手段是我們最為關心的問題。 在回答這個問題之前,我們先來看下市面上的遠端除錯框架,他們做了什麼事情,解決了什麼問題。

如下是我對比較常見的遠端除錯框架的簡單對比。

remote-debug

後面虛線裡面的是除了抓包功能之外除錯框架,可以看出灰色部分是他們不支援的。 這時候就需要專門的抓包工具來代替。通常來說專門的抓包工具功能包括但不限於請求攔截和修改,https支援,重放和構造請求,(web)socket。

抓包工具的原理非常簡單,本質上它就是一個正向代理,所有的請求經過它,就可以將其記錄下來,甚至可以重放構造請求等。

對於抓包工具,步驟基本就是三部曲。

第一步:手機和PC保持在同一網路下(比如同時連到一個Wi-Fi下)

第二步:設定手機的HTTP代理,代理IP地址設定為PC的IP地址,埠為代理的啟動埠。

Android設定代理步驟:設定 - WLAN - 長按選中網路 - 修改網路 - 高階 - 代理設定 - 手動 iOS設定代理步驟:設定 - 無線區域網 - 選中網路 - HTTP代理手動

對於https請求需要多一步:

第三步:手機安裝證書。

對於第二步,我們可以通過連線USB的方式,然後設定埠轉發和虛擬主機對映,建立tcp連線,這樣就ip就可以設定為localhost,以後ip變動,代理設定也不必變動,但是卻需要連線USB,可謂各有千秋。

遠端除錯服務

通過使用上面提到的框架(或者是自己寫的擁有上面基本功能的框架), 我們已經可以很方便地進行除錯了。 但是事實上大多數公司都是開發者在本地進行除錯。這就造成了很多問題,比如

  • 如果手機在不同的開發者電腦除錯,就需要在一個手機安裝多個證書。
  • 開發者需要自己配置代理配置檔案,共享需要手動匯出匯入相對麻煩。
  • 如果開發者本地的ip發生變動,那麼就需要修改手機的代理ip(不使用usb走虛擬主機對映的情況) ......

針對以上等問題,如果搭建一個遠端的除錯服務(產品),那麼問題就可以很好的解決。

理想的狀況是,手機僅僅需要配置一次(安裝證書,設定代理等),以後除錯的時候就可以直接檢視該手機的請求以及控制檯,元素等等,並且直接指定對映到任何電腦 進行pc端除錯。不同開發者之間可以方便的共享配置(比如有一個集團或公司的共有配置)。

拿搭建一個whistle的服務為例。

下載專案並啟動:

npm install whistle -g --registry=https://registry.npm.taobao.org

w2 start
複製程式碼

設定代理:

比如設定手機的代理為x.x.x.x:8899

> x.x.x.x 為部署服務的ip地址,8899為預設埠,若修改了,則對應修改為修改後的埠號

dashboard

訪問http://x.x.x.x:8899/,會看到如下的頁面:    

whistle dashboard
   我們可以在network檢視遠端的網路請求,可以通過其內建的weinre檢視元素,控制檯等    可以看到我們配置了三套配置,分別為預設配置,專案一和專案二。

簡單介紹下配置做了什麼。    前兩個就是簡單地將請求對映到本地。    第三條配置會攔截www.duiba.com.cn 的請求,並在html中注入一端weinre指令碼。攔截成功就可以通過訪問http://x.x.x.x:8899/weinre/client/#sword 訪問對應的開發者工具進行除錯。  

weinre-client
  其他功能:

Network:主要用來檢視請求資訊,構造請求,頁面 console 列印的日誌及丟擲的js錯誤等

Rules:配置操作規則

Plugins:安裝的外掛資訊,及啟用或禁用外掛

Weinre:設定的weinre列表

HTTPS:設定是否攔截HTTPS請求,及下載whistle根證書

我們可以進一步安裝證書支援https攔截,配置賬號系統,日誌對映等等, 部署一個其他的遠端除錯框架的基本思想和步驟基本是一樣的。

經過上面的步驟我們已經得到了一個集中式的除錯伺服器,我們不需要在本地配置複雜的環境和配置了, 並且足夠靈活,我們可以檢視所有請求,隨意更改請求,並且直接代理到本地盡心除錯。

實際情況我們還會遇到很多其他問題,通過擴充套件框架的功能豐富功能是非常有必要的,這個時候框架的擴充套件性就很重要了。

除錯的輔助手段

通過上面的方式我們已經建立了除錯的準備環境。但是真正除錯應用,發現問題,解決問題。還需要 其他資訊來輔助。下面來講解一些除錯的輔助手段。

使用者軌跡

有時候我們需要知道使用者的瀏覽軌跡,從而方便定位問題。 瀏覽軌跡的粒度可以自己決定,可以是元件級,也可以是頁面級。

應用資料

獲取足夠的資訊對於除錯是非常重要的。尤其是資料驅動(data driven)的應用, 知道了資料,基本上就可以還原現場,定位問題。

比如我們使用vuex或者redux這樣的狀態管理框架,一種方式是將中央的store掛載到window上。 這樣我們就可以通過訪問window的屬性獲取到全域性的store。 如果使用其他的狀態管理框架或者自制的狀態管理,也可以採取類似的方式。

然而我們也可以使用現成的工具,比如使用react-dev-tools除錯react應用。 比如使用redux-dev-tools除錯使用redux的應用等等。

其他除錯資訊

比如使用者的id,客戶端資料,登陸的session資訊等等對於除錯有所幫助的,都可以將其收集起來。

參考

https://www.jianshu.com/p/19c18c924f91

https://aotu.io/notes/2017/02/24/Mobile-debug/index.html

歡迎關注我的公眾號,不定時更新。

公眾號

相關文章