close

大廠技術堅持周更精選好文

本文為來自 西瓜視頻前端技術團隊 的文章,已授權 ELab 發布。

作者:鄭家興

前言

前端程序員最容易搞出 P0 事故的就是白屏,PC 上的白屏我們比較好調,打開 Chrome Devtools 就能看見。

但是手機上的白屏怎麼調?以及遠程用戶手機上的白屏又該怎麼調?這時候就需要使用遠程調試的技術了。

本文將對遠程調試這個話題進行探討,並給出最佳實踐。

誰適合閱讀本文檔

有移動端 Web 開發背景,或者對移動端 Web 開發感興趣的前端同學

預期收穫
了解遠程調試的發展歷程
掌握遠程調試的基本原理
掌握不同場景的調試決策
分享思路
介紹調試與遠程調試的概念
介紹 hybrid 遠程調試的發展歷程以及相關技術
對調試方案進行對比,並提供最佳實踐
對遠程調試未來的一個暢想
特殊說明

hybrid:前端和客戶端的混合開發,一般是指在客戶端應用上啟動 Webview 渲染 Web 頁面,兼顧原生 App 和 Web 的優點。在本文中,為方便理解,hybrid 泛指移動設備上的前端技術,包含原來的 hybrid 應用、以及移動瀏覽器 Web。

調試與遠程調試調試
使用 Chrome Devtools 調試網頁,是調試
使用 VSCode Debugger 調試 Node 應用,也是調試

他們的共同點在於:

有一個調試界面(client),比如 Chrome Devtools 、VSCode Debugger
有一個目標調試服務(server),比如 網頁、Node 應用
調試界面和目標服務之間約定了一個調試協議(protocol),比如 Chrome Devtools 的Chrome Devtools Protocol (CDP),VSCode Debugger 的Debug Adapter Protocol
需要一個傳輸通道(transport channel)來傳遞協議 ,比如使用內部函數調用,或者基於網絡傳輸的websocket方案,usb 傳輸等等

因此,我們粗淺的定義調試由四部分組成

調試四要素調試界面(client)調試協議(protocol)目標調試服務(server)傳輸通道(transport channel)
遠程調試

相比調試,遠程調試的調試界面(client)和目標調試服務(server)一定在不同的機器上;

此外,遠程調試在傳輸通道上做了限定,需要藉助一些物理介質(比如 WIFI、藍牙、USB)來配合傳輸通道(transport channel)傳遞協議

對於 hybrid 這個場景,遠程調試的四要素分別是:

調試界面(client)Chrome Devtools 、Safari Inspector 等調試工具,目前 Chrome Devtools 使用率占比最高目標調試服務(server)手機 web 頁面調試協議(protocol)Chrome Devtools Protocol ,Safari 的 Webkit Devtools Protocol傳輸通道(transport channel)可以是基於 USB 的請求轉發、或者基於網絡的 websocket 轉發,根據不同場景來決定使用的技術
發展歷程階段 0:WAP 時代的原始調試 - 2000

早期的移動端網頁稱之為 WAP ,支持展示少量頁面標籤以及頁面腳本。

當時存在着各種類型的操作系統,比如諾基亞的 Symbian、黑莓等等,大部分手機都會支持 WAP 。

以諾基亞為例,2005 年諾基亞手機內置 S60 瀏覽器,其內核用的 Webkit,支持 WAP 頁面展示。

當前的頁面形態還比較簡單,加之混合應用還沒起來,大部分情況下本地調試即可解決,因此遠程調試還不是痛點。

一般還是採用 alert 這樣的本地調試方案。

時間快進到 2009 年,Opera Mobile 10 發布,Symbian 系統可安裝下載。

該瀏覽器牛逼之處在哪?其**支持局域網內遠程調試,無需 USB ,領先同行數年!甚至如今(2022)Android Chrome 默認都不提供 WIFI 調試**,只能通過一些工具解決(下文會提到)

當前該方案的不足之處在於生態,如果統一市場的是 Opera 而不是 Chrome 的話...

手機和電腦處於同一局域網
電腦打開 Opera 瀏覽器,啟用遠程調試功能(默認開啟端口 7001)
手機打開 Opera 瀏覽器,進入調試頁面,輸入電腦 ip 和調試端口
電腦展示手機 Opera 瀏覽器畫面,此時可進行調試
階段 1:Webkit 初期 - 2007

2007 年首款 iPhone 和 Android 設備分別發布,自帶 Webview 功能(採用的 Webkit 引擎)

那一開始如何進行 Webview 頁面調試的呢?

Android:默認不提供調試功能,但提供了一些 Android API ,可以控制頁面(注入腳本,獲取console 信息)
iOS:默認提供 Debug Console 功能,可以在頁面某個區域上直接展示調試彈窗

引自Step By Step: Turn On The iPhone/iPad’s Web Debugging Console · MaisonBisson

首先 iOS 的調試方案不通用,還壓縮了頁面布局;Android 上調試需要懂 Android 的同學配合。

此時的調試如此麻煩,不如繼續使用 alert 。

但 alert 本身就難用,此時有追求的前端同學就誕生了一個想法:

畫一個調試框,支持打印輸出(重寫 consoleapi),執行輸入腳本(eval)

這也是後面介紹的 vconsole 等解決方案的雛形,但當時大家各做各的,貌似也沒有較出名的開源方案。

階段 2:Weinre(WebInspectorRemote)前端方案 - 2010

聰明的程序員大多是偷懶的

如果能在電腦上直接調試移動端頁面,那效率就大大提高。可是客戶端不支持,作為一個前端開發,怎麼用前端技術來解決這個問題?

2010.12,Patrick Mueller 推出了 weinre 工具,意為WebInspectorRemote(見 weinre - ChangeLog)

weinre 由三部分組成

本地調試器(Debug Client): 用的是 Webkit 的 Web Inspector
服務端(Debug Server):本地起的 http 服務(weinre 採用的 node 技術),用來與 Debug Client 和 Debug Target 進行通信
目標頁面(Debug Target):移動端上的目標調試頁面,需要在頁面上注入一段 weinre 腳本,該腳本會與 Debug Server 進行通信,將當前頁面的調試信息發往 Debug Server ,或收取 Debug Server 的信息來控制 Debug Target

weinre 的原理如下:

Debug Target 和 Debug Client 使用同一套調試協議(Webkit Devtools Protocol)
Debug Target 收到 Debug Client 的操作請求,將其解析為具體的 JS 操作,作用到當前頁面並返回結果響應
Debug Target 內部也會監聽一些事件,比較網絡請求、日誌輸出,並將結果主動推到 Debug Client
Debug Target 和 Debug Client 使用 Debug Server 進行中轉,支持多頁調試。(經典的發布訂閱模式)

以最常用的「Console 面板執行代碼」為例:

重寫頁面全局 API ,包括 console 等
收到「執行代碼」請求,使用 eval 執行代碼,並將結果作為響應返回
如果直接過程中出現輸出,則主動發起「輸出日誌」的請求

weinre使用純前端能力,沒有用到任何 native 能力。

因此其功能有限,比如無法調試源碼、監控所有請求(可以想一下為什麼)。

但weinre提供了一個思路,即純前端可以實現基礎能力的任意遠程調試

階段 3:USB 連接調試 - 2012

weinre 方案故好,但還是缺少諸如完整的元素麵板、完整的請求列表面板。

於是,輪到操作系統開始卷了。

2012.9 蘋果發布了 iOS 6 ,其支持遠程調試
2013.11 谷歌發布了 Android 4.4 ,使用 chromium 作為 webview,可以配合桌面 Chrome Devtools 實現遠程調試

此時的遠程調試四要素如下:

iOSAndroid調試界面(client)Safari Web InspectorChrome Devtools目標調試服務(server)iOS WebviewAndroid Webview調試協議(protocol)Webkit Devtools ProtocolChrome Devtools Protocol傳輸通道(transport channel)USB 請求轉發USB 請求轉發

該階段能夠實現完整的調試能力,但引入了 USB 作為調試通道,增加了遠程調試成本,且不適用於跨地遠程調試

階段 4:前端模擬 CDP - 2016

CDP,即 Chrome Devtools Protocol 。隨着 Chrome 的優化,Safari 、Firefox 和 IE 等瀏覽器的沒落,社區上使用 Chrome Devtools 調試的占比越來越大。

這個階段其實沒有什麼創新性的突破,而是將原來的調試體系往 CDP 靠攏,社區出了如下方案:

ios-webkit-debug-proxy :基於 USB 連接,使用 Chrome Devtools 調試 iOS Safari ,隨着 Chrome Devtools Protocol 越發不兼容 webkit protocol,現在已無法單獨使用,需要配合如下工具
remotedebug-ios-webkit-adapter :協議適配器,將 webkit protocol 轉換為 Chrome Devtools Protocol

而在基於 WIFI 通道的調試方案上,weinre 已不再兼容 Chrome Devtools Protocol ,於是社區又出了一款代替 weinre 的方案 -- chii

於 2020.4 推出,對標 weinre 的能力,只是將 webkit protocol 改為 Chrome Devtools Protocol ,weinre 無法獲取到的,chii 也無法獲取,比如網絡只能捕獲 xhr

於此同時,原先的「頁面展示一個調試窗口」也出了幾種較為好用的方案:

vConsole :目標是更輕量的 console 控制器,由 Tencent 前端團隊於2016.4開源
eruda:2017.3 推出,和 chii 是同一個作者

簡單總結下這個階段:工具不斷優化,並往 Chrome Devtools 調試靠攏

階段 5:WIFI + CDP

前面提到,社區調試方案逐步遷移到 Chrome Devtools 的調試體系,包括:

USB 連接調試,支持 Chrome Devtools 調試 iOS 和 Android (完整的調試能力)
前端模擬CDP:基於純前端能力,支持 Chrome Devtools 調試 iOS 和 Android(部分調試能力)

現在還有一個問題沒有解決:如何基於 WIFI 通道完整的調試Hybrid頁面?

解決了這個問題,我們就能拋開物理限制,實現跨地區的完整的遠程調試

在分析這個問題之前,我們需要先解決如下問題:

USB 調試的原理是什麼?
怎麼將 USB 通道替換為 WIFI 通道?
Android USB 調試

Android 和 iOS 的 USB 調試過程不太一樣,這裡先講 Android 的

Android USB 調試原理

Android Chrome 在開啟調試模式後,會啟動 Unix Domain Socket Server(固定端口 9229) ,對其發送/json/list請求可以獲得可調試的頁面列表;創建 socket client 並連上該 Server ,找到目標調試頁面,對其收發 cdp 數據包,即可控制相應頁面或者收到該頁面的調試信息。

使用 usb 調試,實際是使用 ****adb****做了一層端口轉發

adbforwardtcp:9229tcp:9229

本地訪問 9229 端口實際訪問的是 Android 內部的 9229 端口

PC 啟動調試工具時,會創建一個socket client,接着再通過 adb 連上了Unix Domain Socket Server,此後即可就進行 cdp 進行通信。

Android 繞過 USB

解決方案其實很簡單,加一層websocket進行中轉

在 Android App 內部啟動 2 個 socket client :

一個連接Unix Domain Socket Server收發數據,
另外一個連接 PC 的socket server用來中轉數據

然後 PC 的 socket server 再轉發 CDP 數據給Chrome Devtools

iOS USB 調試iOS USB 調試原理

iOS 和 Mac 之間進行 USB 通信,採用的是 USB 協議稱之為usbmux,其本身是私有協議,用於自身應用使用,但是都被破解得差不多了...

usbmuxd是 usbmux 協議的實現,是一個守護進程,隨 iOS 設備和 Mac 設備的系統啟動而啟動,當 iOS 設備連接上 Mac ,之間的 usb 通信將通過 usbmuxd 這個中間服務進行

於是如果我們知道了 Web 遠程調試對應的 USB 協議,那麼就可以取代 Safari Inspector ,實現自己的調試終端。

相關的調試協議可以通過這個倉庫找到 GitHub - google/ios-webkit-debug-proxy: A DevTools proxy (Chrome Remote Debugging Protocol) for iOS ,感興趣的自行查閱

iOS 繞過 USB

同 Android ,要想取消 USB ,我們也需要啟動了一個 websocket 來做指令中轉。

要做指令中轉,我們首先需要找到遠程調試服務的端口。那麼問題來了:iOS 的遠程調試服務端口是多少?

不像 Android 的調試端口是固定的,iOS 設備的內部服務是啟動時動態註冊的。

對於這個問題,iOS 提供了一種類似「門衛」的解決方案:內部運行一個守護進程(lockdown),運行在固定端口(62078),支持系統服務訪問能力。

暫時無法在飛書文檔外展示此內容

於是可以先通過該服務找到 Web 調試服務(com.apple.webinspector)的端口,之後的過程和 Android 一樣了。

方案缺陷

首先是使用成本,本地需要另外啟動一個 socket server 服務。

那麼把 socket server 服務部署在線上呢?的確可以降低用戶的使用成本,但是相應的,網絡鏈路變長了,容易出現時延問題,如果是居家辦公不在同一個辦公網的話就更嚴重了。

方案對比

打分規則:

不支持為 ❌
支持,結合可用性和易用性打分,1~3 顆 ⭐
最佳實踐
如果需要遠程調試其他用戶的頁面
頁面類型最佳方案公司內測 App 頁面推動公司基建部門建設 「WIFI 調試」方案,否則使用「其他 web 頁面」方案公司線上 App web 頁面若需要完整的調試能力,下載對應版本 app 的內測包,然後同「公司內測 App web 頁面」- 若僅僅是簡單調試 console,同 「其他 web 頁面」其他 web 頁面(如微信頁、瀏覽器 Web)自行搭建 chii;如果僅查看輸出,直接用 vConsole 、 eruda
如果是本地調試自己的手機頁面
頁面類型最佳方案公司內測 App 頁面推動公司基建部門建設 「WIFI 調試」方案,否則使用「其他 web 頁面」方案公司線上 App web 頁面若需要完整的調試能力,下載對應版本 app 的內測包,然後同「公司內測 App web 頁面」- 若僅僅是簡單調試 console,同 「其他 web 頁面」原生瀏覽器頁面打開手機調試設置,連接 USB 調試頁面。如果不想用 Safari 調試 iOS 頁面,需要自行部署 ios-webkit-debug-proxy。其他 App 頁面自行搭建 chii;如果僅查看輸出,直接用 vConsole 、 eruda,否則可用採用「前端模擬 CDP 遠程調試」方案:chii
未來暢想

上面講了這麼多,我們會發現調試方案非常的零碎,或者落地成本較高。

我們希望未來的遠程調試是這樣的:

統一的調試協議CDP統一的調試終端Chrome Devtools統一的調試地址配置允許手機配置本地調試的 Socket Server 地址,開啟開發者模式後,所有瀏覽器 Web 頁和內測 App Web 頁將自動連上該 Socket Server ,PC 調試工具再與該 Server 通信(參考 Opera ,兼顧安全和效率)復用 Chrome Extension 能力支持 React Devtools、Vue Devtools 等高效、安全、穩定的通信通道自動選擇最優,通道包括 wifi、藍牙、usb

第三點需要操作系統支持,其他的屬於上層方案,總是可以實現。

參考資料

usbmux協議分析 - Lazy Eval

揭秘瀏覽器遠程調試技術 Webkit 遠程調試協議初探

乾貨|一定要知道的抖音小程序/小遊戲調試原理!

iOS自動化測試驅動工具探索 - 掘金

Web應用調試:現在是Weinre和JSConsole,最終會是WebKit的遠程調試協議_Java_Werner Schuster_InfoQ精選文章

在越獄設備調試任意 iOS App 的 WebView - 字節時代

wap是什麼渠道的簡稱(wap的另一層意思)

跨終端Web之Hybrid App_移動_徐凱_InfoQ精選文章

關於我們

我們來自字節跳動,是旗下西瓜視頻前端部門,負責西瓜視頻的產品研發工作。

我們致力於分享產品內的業務實踐,為業界提供經驗價值。包括但不限於營銷搭建、互動玩法、工程能力、穩定性、Nodejs、中後台等方向。

歡迎關注我們的公眾號:xiguafe,閱讀更多精品文章。

我們在招的崗位:https://job.toutiao.com/s/rhjPVXT。招聘的城市:北京/上海/廈門。

歡迎大家加入我們,一起做有挑戰的事情!

謝謝你的閱讀,希望能對你有所幫助,歡迎關注、點讚~

- END -

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()