B站PC客戶端-架構設計
眾所周知,B站是個學習的網站,網頁端和粉版移動端都非常的好用,不過,相對其它平臺來說B站的PC客戶端也算是大器晚成了。在有些場景PC客戶端的優勢也是顯而易見的,比如,跓留電腦桌面的快捷、獨立的應用窗口、特有的交互方式等,因此就有了很多喜歡B站的技術大佬整出了不少體驗不錯的第三方PC應用,比如云之幻版、逍遙橙子版等。
當然我站也有一個源自三方的UWP客戶端,但是由于歷史原因一直沒有得到很好的維護,在21年底,一個需要在電腦端預裝的需求讓我們有了開發一個全新的PC客戶端的想法。
一、PC客戶端的技術選型
選擇一個什么樣的技術,可以在降本增效的大背景下實現一個體驗相對較好、易維護、跨平臺且能快速推進的PC應用呢?
圖2 PC端開發技術對比
調研了一些PC端應用開發的技術方案之后,基于開發效率、跨平臺和成熟度等因素考慮,最終我們選擇了使用WEB技術棧的Electron做為新PC客戶端的開發框架。
圖3 Electron框架的優勢
在確定了開發框架后,我們先來看看Electron到底是什么。我們知道Electron是背靠微軟基于WEB技術的開源項目,最初源自GitHub團隊的Atom Shell項目,結合NodeJs和Chromium實現,并對系統API做了封裝,比如系統對話框、系統托盤、系統菜單、剪切板等,開發者可以直接通過js訪問這些API。
圖4 Electron的構成
圖5 一般Electron應用的運行時
我們知道Electron程序主要分為主進程(Main Process)和渲染進程(Render Process),主進程主要為NodeJs和原生API,渲染進程主要為前端技術,主進程和渲染進程之間通過IPC進行通信。
為了易維護、好拓展、可復用等目的,我們選擇了NodeJs+NestJs+Esbuild的方案來開發主進程,選擇了和WEB首頁Laputa項目相同的技術棧Vue3+Vite2+TypeScript開發渲染進程。
圖6 PC客戶端技術選型
主進程的NestJs是一個受Angular啟發的NodeJS后端框架,風格有點像SpringBoot,結合OOP (Object Oriented Programming)、FP (Functional Programming)和 FRP (Functional Reactive Programming)等編程范式,能夠開發出高可測、好拓展、松耦合、易維護的應用。Esbuild是使用go語言實現的js極速打包工具,可以助力更高效的開發主進程。
圖7 Esbuild官網展示的構建性能對比
渲染進程使用和WEB相同的技術棧,除了方便復用WEB現成的很多組件之外,同時WEB業務線的開發人力也可以無障礙的投入到PC客戶端的業務開發中來,因此可以最大限度的降低開發成本、提高開發效率。另外,我們還在項目中實踐和應用了我們自研的Vue3組件庫vivid-ui、函數庫@bilibili/b-utils和樣式庫@bilibili/b-style等工具庫。
圖8 PC客戶端自研工具庫
二、PC客戶端的整體架構
PC客戶端是B站的一個全新的端,除了推薦、直播、熱門、OGV、動態、空間、搜索等常規功能之外,還需具備電腦端本地軟件的其它能力,包括安裝升級、托盤隱藏、本地存儲、專有窗口、離線緩存、自定義配置、喚端拉活等等。
圖9 下載中心
(其中Windows版、MacOS版、微軟商店版都是PC客戶端)
我們先來看看PC客戶端的業務功能設計,在1.0的版本我們其實就已經實現了安裝卸載、開屏頁、首頁、動態、搜索、我的和空間、播放頁、登錄、主題和設置等功能,隨著版本迭代,我們陸續完成了一鍵三連安裝界面、離線緩存、播單、消息等功能。
圖10 PC客戶端業務功能設計
在明確業務功能后,結合框架和技術棧,我們設計了PC客戶端的整體架構:由渲染進程實現業務功能的UI和交互,由主進程實現本地日志、存儲、下載、上報、升級等服務和支持的功能,渲染進程和主進程之間封裝IPC為統一的JSB接口進行通信。
圖11 PC客戶端整體架構設計
在渲染進程中,賬號登錄、大會員充值、直播間和開播頁都是使用webview嵌WEB頁的方式接入的,其它業務模塊均為本地應用頁面;在主進程中,本地日志、本地存儲和下載SDK都是引入的模塊,其它各個模塊和服務之間通過依賴注入和rxjs主題訂閱的方式實現相互調用;JSB則由主進程通過preload的方式注入到渲染進程各頁面的window對象中,渲染進程不論是外嵌還是本地頁面都能訪問到JSB對象實現和主進程通信。
由于客戶端基于Electron和WEB技術開發,一個窗口頁面其實本質上就是一個HTML頁面。當然,我們的主頁面都是從由主進程創建的本地服務器上拉取的Local頁面,因此斷網的情況也能響應,像首頁、動態網絡強相關的頁面,在斷網時會顯示失敗提示,而離線緩存、設置等功能都能正常使用。
由于我們渲染層是基于Vue開發的SPA應用,主窗口和播放窗口在打開時會有一個比較耗時的加載過程,為了提升用戶體驗我們專門針對窗口創建和打開過程做了優化。
在啟動時(首次打開主窗口),會先創建一個隱藏的主窗口,加載一個相對簡單的開屏頁。
當開屏頁渲染完成后,調用主進程splashPageReady接口,主進程控制顯示主窗口。(防止開屏頁白屏)
主窗口和開屏頁顯示之后,在主窗口開屏頁下方加載和渲染比較大的主頁面。
主頁面渲染完成時,調用主進程mainWindowReady接口,并關閉蓋在主頁面上面的開屏頁。
主進程收到mainWindowReady后,創建一個隱藏的播放窗口。
當用戶點擊播放視頻時,顯示已渲染好的播放窗口,并加載和播放視頻。
關閉主窗口和播放窗口時,只將窗口隱藏并不真實銷毀窗口實例,當再次打開或播放視頻時,就可以快速打開窗口,提升用戶體驗。
圖12 PC客戶端執行過程
圖13 窗口創建和打開流程
事實上,采用隱藏的窗口進程做預渲染和并行處理是提升Electron應用體驗的常用方法,在Electron中可以用ChildProcess、BrowserWindow、BrowserView、webview等方式開啟子進程,突破進程限制,充分利用機器的性能。
可以通過主進程app.getAppMetrics()方法獲取APP各進程的CPU和內存數據統計,PC客戶端主要包含7個常跓進程:1個瀏覽器(Browser)進程、1個GPU進程、1個網絡服務(Network Service)進程、1個音頻服務(Audio Service)進程和3個頁面(Tab)進程。
圖14 PC客戶端的進程
由于渲染進程占用資源比較大,如果用戶長時間未使用又沒有關閉的話就會造成資源浪費,因此我們還為APP設計了“節能模式”,當APP隱藏到托盤超過一定時間未點開后會進入到此模式,這時程序會殺掉主窗口和播放窗口對應的渲染進程,釋放資源占用。進入節能模式之后,如果用戶再打開APP則會進入前面提到的窗口創建和打開流程,不過這個過程沒有APP初始化的任務,速度會比冷啟動時要快很多。
圖15 PC客戶端節能模式
PC客戶端使用Fawkes平臺打包構建、使用北極星進行數據上報并在觀遠建立數據報表、使用魔鏡平臺進行自動化巡檢測試、在info上建有專門的產品和開發文檔,開發方面也有明確的代碼規范要求
圖16 項目設計開發平臺工具
三、PC客戶端工程化構建
PC客戶端渲染進程和主進程都是基于TypeScript進行開發的,Ts提供的類型定義和規范可以大幅度提高代碼的可讀性,在主進程和渲染進程的中間,我們還設計了一個common共享層,用來實現Ts類型和常量的共享。
PC客戶端項目結構:
PC客戶端項目運行和構建都基于NPM Script,構建release包只需要運行: yarn build:prod。構建代碼位于app目錄下,由于構建產物也是js代碼,很容易被人拿去套殼、植入或篡改。為了防范這些所知的風險,增加被篡改和攻擊的難度,我們需要對構建包進行加密處理。經過不斷的迭代優化,我們實現了一套使用結合代碼混淆、對稱加密、字節碼處理、WASM解密和啥希校驗的組合式客戶端加密防破解方案。
在打Release包時,會把構建生成的代碼先進行混淆、壓縮處理,再將主進程主程序代碼使用AES-256對稱加密生成/app/main/.biliapp文件,將解密和執行入口使用字節碼處理,最后計算出APP的哈希值。
圖17 PC客戶端主程序加密
當PC客戶端啟動時,會先根據操作系統和系統架構找到對應字節碼入口、解密并運行主程序、主程序中校驗APP的哈希值,在確定運行環境安全后再正常啟動程序。
圖18 pc客戶端運行流程
PC客戶端基于electron-builder進行打包,Mac的安裝窗口通過electron-builder配置可以直接生成,Windows的專屬一鍵三連安裝程序則是使用NSIS + QT獨立開發的。
圖19 PC客戶端安裝引導界面
圖20 基于NSIS+QT的專屬一鍵三連界面
PC客戶端前期版本基于electron-updater進行升級更新,每次進行版本升級后,都需要用戶重新下載完整的安裝包進行覆蓋安裝,由于安裝包體積比較大在網絡比較差的情況下,升級過程會比較耗時影響用戶體驗。
在1.9.x版本之后,我們已集成增量更新的功能,只需對app.asar代碼包進行更新而不是包含框架的完整安裝包,因此可以提高了升級更新效率和體驗。
圖21 PC客戶端升級更新流程
四、PC客戶端的播放體驗
類似愛奇藝和騰訊視頻,我們的PC客戶端也是雙窗口模式,即主窗口和播放窗口是獨立的,可以讓用戶一邊播放視頻一邊刷動態、逛空間、看消息。
得益于PC客戶端渲染進程使用WEB技術開發,稍加適配,PC客戶端的播放器直接用上了WEB強大的Nano播放器,這使得PC客戶端也擁有了高級彈幕、播放設置、播放器快捷鍵等功能。PC客戶端還將UGC和OGV播放器集成在同一個播放窗口,讓視頻類型切換更加順暢,還可以通過前進后退播放歷史紀錄。
PC客戶端的播放質量對比WEB播放頁來說,首幀和VV卡頓率會優于WEB,主要原因為能更多預載,單實例,編碼支持統一;而百分鐘卡頓率和錯誤率相對WEB來說要略高一些,新平臺有更多case需要處理,此項會略高但重試機制盡量不影響體驗。
圖22 PC客戶端和WEB播放頁質量對比
對比B站其它端來說,PC客戶端的人均播放時長是最高的,目前均值已超80分鐘,峰值可達100分鐘。
另外,PC客戶端還實現了貼心的“小窗”播放模式,當點擊播放窗口右上角的小窗模式按鈕時或拖動改變播放窗口到小尺寸時便會進入小窗模式。
在小窗模式下:
- 播放窗口可以適配視頻大小比例,實現無黑邊播放。
- 搭配固定窗口在最前端的功能,可以讓用戶一邊看教程學習,一邊實際動手操作。
- 相對網頁的畫中畫,PC客戶端的小窗不僅可以顯示彈幕,而且還沒有原畫頁面的各種限制。
- 這里小窗其實指的是一種簡潔播放模式,因為小窗也可以拖動邊緣調整大小,變成比“大窗”還大。
圖23 極致的小窗播放體驗
圖24 固定小窗在最前端
五、PC客戶端的質量保證
PC客戶端在每次上線之前都需要經過嚴格的測試流程,一般在官網上線前4個工作日需要進行集成測試,前2個工作日出總包并進行總包回歸測試。
除了功能測試之外,構建也需要保證準確性,PC客戶端使用Fawkes打包構建,但是人工構建每次都需要根據不同的渠道選擇不同的環境變量,渠道也比較多構建容易出錯,因此我們開發了CLI打包工具。
命令行打包工具打通了Fawkes構建平臺和魔鏡測試平臺,通過命令行選擇渠道、類型和其它參數,并使用配置列表發起構建。
- 快速發起Fawkes構建,提高打包配置效率。
- 多種模式可選,快速發起debug/release、簽名、推CD的包。
- 可以避免渠道包打了debug或未簽名的情況。
- 可以避免環境變量配錯、渠道號和渠道名對不上的問題。
- 接入魔鏡自動化測試平臺,保證構建包可靠性,不用人力挨個校驗,提高構建效率。
圖25 通過命令行工具發起構建
圖26 魔鏡PC客戶端自動化測試
六、PC客戶端發布和上線
PC客戶端于22年5月10日在官網正式上線,在B站WEB首頁頂導、B站下載中心和常用的PC的軟件平臺如:微軟商店、聯想商店、華為應用市場、騰訊管家等搜索“嗶哩嗶哩”都能下載到最新版本。
PC客戶端的發布渠道較多,不同的渠道也有不同的要求,新版本會根據渠道ID來構建并分別投放上架。
圖27 PC客戶端渠道匯總
上線以來,PC客戶端DAU穩步增長,目前已達300萬+。
圖28 PC客戶端DAU數據穩步增長
各渠道安裝量穩步上長,對比官網包占比已達40%。
圖29 微軟商店~入選精選娛樂應用
圖30 華為應用市場~閑暇時光首選
圖31 聯想應用商店~搜索“嗶哩嗶哩”
?本期作者
沈濤
嗶哩嗶哩資深開發工程師