1.業(yè)務(wù)背景
隨著公司業(yè)務(wù)的快速發(fā)展谈喳,商家客服也納入了我們的服務(wù)范圍婿禽,商家客服工作臺(tái)的定位是通過(guò)工具和數(shù)據(jù)服務(wù)商家谈宛,一站式解決用戶購(gòu)買咨詢?cè)V求吆录。通過(guò)工具和運(yùn)營(yíng)策略協(xié)助商家提升服務(wù)品質(zhì)恢筝,讓品牌商家有動(dòng)力運(yùn)營(yíng)好潛在的客戶,從而達(dá)到提升用戶服務(wù)的目標(biāo)侄柔。桌面應(yīng)用的轉(zhuǎn)化在未來(lái)是客服產(chǎn)品的方向暂题。
- 已有web端聊天系統(tǒng)的前提下薪者,商家客服為什么要遷移桌面應(yīng)用言津?
首先我們收到部分商家客服反饋:
- 用戶是上帝怀吻,我們是很重視用戶的反饋的烙博,所以首先我們想的是如何在web端解決這些問(wèn)題渣窜,下面我們逐一分析下以上問(wèn)題我們能不能在網(wǎng)頁(yè)端解決呢乔宿?
針對(duì)客服A同學(xué)問(wèn)題:大多數(shù)客服職場(chǎng)的臺(tái)式機(jī)是不會(huì)安裝音頻設(shè)備,如果人家沒(méi)音頻鲁沥,沒(méi)外音,我們能強(qiáng)迫他買個(gè)播放器嗎,那肯定是不能的番宁,如果是自營(yíng)客服還有點(diǎn)處理方案蝶押,真需要棋电,公司可以統(tǒng)一采購(gòu)赶盔,但是ToC的顯然不能強(qiáng)制做什么事情霎俩,所以此問(wèn)題無(wú)解打却。
針對(duì)客服B同學(xué)問(wèn)題:這句話怎么理解呢柳击,是這樣的捌肴,在一屏既有web瀏覽器,又有其他應(yīng)用如飛書之類的PC應(yīng)用疊著放饥悴,web notification通知由于是瀏覽器級(jí)別的西设,提醒不到最上層贷揽,瀏覽器的提醒確實(shí)有點(diǎn)弱(看不到提醒會(huì)影響到客服的首響禽绪,首響會(huì)影響客服的績(jī)效藻糖,咱公司對(duì)于用戶的服務(wù)效率是比較嚴(yán)格的)巨柒,所以此問(wèn)題無(wú)解晶乔。
針對(duì)客服C同學(xué)問(wèn)題:em正罢。。翻具。好的履怯,您說(shuō)的對(duì),web網(wǎng)頁(yè)給商家客服的感覺(jué)就是我們平臺(tái)有點(diǎn)趕不上形勢(shì)裆泳。叹洲。。
基于上面的一些場(chǎng)景运提,想必大家已經(jīng)對(duì)為何做桌面應(yīng)用有個(gè)初步的了解,下面以一張圖來(lái)看下web應(yīng)用跟桌面應(yīng)用的區(qū)別闻葵。
2.技術(shù)選型
- 為什么會(huì)選擇Electron而不是其他應(yīng)用開發(fā)框架民泵?
2.1 Electron架構(gòu)簡(jiǎn)介
Electron的構(gòu)成主要是上面的3個(gè)大模塊,每個(gè)模塊各司其職槽畔,讓Electron有了桌面應(yīng)用的能力洪灯。
Chromium:可以為Electron提供UI渲染能力,再加上Chromium本身就是跨平臺(tái)的竟痰,所以也不用考慮代碼的兼容性签钩。只要有Chromium,就能用JavaScript坏快,HTML铅檩,CSS這些前端開發(fā)工程師所熟知的三劍客來(lái)開發(fā)頁(yè)面。
Node.js:Chromium并不具備原生GUI操作的能力莽鸿,所以Node.js正好補(bǔ)足了這個(gè)能力昧旨,能夠調(diào)用操作系統(tǒng)的底層 API,比如path祥得、fs兔沃、crypto 這些模塊,甚至能集成C++级及。
Native APIs:Native API讓Electron有了跨平臺(tái)和桌面端的原生能力乒疏,比如說(shuō)它有統(tǒng)一的原生界面,窗口饮焦、托盤這些怕吴。
2.2 Electron與其他框架的區(qū)別
下面是Electron與Native窍侧、QT、NW應(yīng)用的對(duì)比圖:
Native(C++/C#/Objective-C)不管從原生體驗(yàn)转绷、包的體積伟件、性能方面來(lái)說(shuō)都是最佳的選擇,但是開發(fā)門檻高议经,迭代速度慢斧账。
QT是基于C++的跨平臺(tái)開發(fā)框架,跨平臺(tái)應(yīng)用十分廣泛(Mac煞肾、Windows其骄、ios、Android扯旷、Linux拯爽、嵌入式),眾所周知的WPS就是用QT開發(fā)的钧忽。性能很好毯炮,甚至于可以媲美原生的體驗(yàn),但是整體門檻還是比較高的耸黑。
Web技術(shù)的代表Electron 和 NW.js 桃煎,相比之前選擇Electron,Electron有非炒罂活躍的社區(qū)为迈,有102k star,有Atom缺菌、vscode這樣的大型應(yīng)用都是基于Electron開發(fā)的葫辐,性能相比于natvie是肯定要差一些,但綜合來(lái)看伴郁,Electron是作為開發(fā)桌面應(yīng)用的目前首選耿战。
值得一提的是Flutter desktop,從渲染原理看flutter是skia自繪性能優(yōu)于Electron焊傅,但問(wèn)題還是穩(wěn)定性和生態(tài)剂陡。Electron由于是nodejs+chromium,前端的生態(tài)可以直接用狐胎,所以Flutter desktop就不納入考慮范圍的鸭栖,但值得關(guān)注。
除了以上這些握巢,最主要的一點(diǎn):Electron能快速交付晕鹊,業(yè)務(wù)層復(fù)用web系統(tǒng)的代碼,只需要關(guān)注主進(jìn)程就好了,并且也能滿足業(yè)務(wù)需要的系統(tǒng)級(jí)別的一些功能捏题。
3.技術(shù)實(shí)現(xiàn)
3.1 項(xiàng)目架構(gòu)
首先介紹下Electron框架里面兩個(gè)重要的概念主進(jìn)程和渲染進(jìn)程。
主進(jìn)程:主要負(fù)責(zé)創(chuàng)建和管理BrowserWindow實(shí)例以及應(yīng)用程序事件肉渴。它可以執(zhí)行注冊(cè)全局快捷方式公荧,創(chuàng)建系統(tǒng)菜單和對(duì)話框,響應(yīng)自動(dòng)更新事件等操作同规。主進(jìn)程以及所有Node.js模塊中都提供了一部分Electron API循狰。
渲染進(jìn)程:渲染過(guò)程負(fù)責(zé)運(yùn)行應(yīng)用程序的用戶界面,渲染進(jìn)程中提供了所有DOM API券勺,Node.js API和Electron API的子集绪钥。
如上面截圖,打開Electron項(xiàng)目之后會(huì)有多個(gè)進(jìn)程关炼,一個(gè)項(xiàng)目有且只有一個(gè)主進(jìn)程程腹,創(chuàng)建窗口等有關(guān)系統(tǒng)事件寫在主進(jìn)程中進(jìn)行,但是渲染進(jìn)程可能有多個(gè)儒拂。
那為什么會(huì)有多個(gè)渲染進(jìn)程呢寸潦?
Electron應(yīng)用是Chromium內(nèi)核,所以多進(jìn)程的架構(gòu)也來(lái)源于Chromium社痛,Chromium會(huì)單獨(dú)運(yùn)行每個(gè)標(biāo)簽见转,任何一個(gè)標(biāo)簽頁(yè)崩潰了都不會(huì)影響到其他標(biāo)簽。因此蒜哀,每個(gè)進(jìn)程在自己的空間中運(yùn)行斩箫,由操作系統(tǒng)調(diào)度。如果某個(gè)進(jìn)程觸發(fā)了無(wú)限循環(huán)撵儿,也不會(huì)導(dǎo)致整個(gè)應(yīng)用down掉乘客。
在上文說(shuō)到兩個(gè)字“遷移”,是的淀歇,我們?cè)陂_發(fā)桌面應(yīng)用之前有非常成熟的web端商家客服聊天系統(tǒng)了寨典,所以我們?cè)陂_發(fā)桌面應(yīng)用的時(shí)候大多數(shù)時(shí)候是關(guān)心主進(jìn)程的,渲染進(jìn)程并不太需要關(guān)心房匆。
3.2 主進(jìn)程功能模塊
3.2.1 通信模塊
主要是調(diào)用Electron框架本身的API以及通用方法的封裝耸成。
主進(jìn)程到渲染進(jìn)程的通信:
渲染進(jìn)程到主進(jìn)程的通信:
有兩種方案,一種是在主進(jìn)程開啟了nodeIntegration: true之后在渲染進(jìn)程里面可以使用window.require('Electron')來(lái)引入寫通信相關(guān)代碼
一種是需要在主進(jìn)程編寫preload.js浴鸿,在初始化窗口的時(shí)候引入
通信的同步和異步問(wèn)題
- 【異步】渲染進(jìn)程->發(fā)送->主進(jìn)程
- 【同步】渲染進(jìn)程->發(fā)送->主進(jìn)程
3.2.2 菜單模塊
主要是調(diào)用Electron框架本身的API井氢,滿足快速擴(kuò)展菜單功能以及自定義菜單功能。
但是商家客服項(xiàng)目沒(méi)用到原生菜單岳链,而是用了自定義的菜單花竞。
沒(méi)有使用原生菜單的主要原因是:
原生菜單樣式較死板,不能調(diào)整;
自定義編寫菜單能有各種自己想要的功能约急,可控制其展示零远。
3.2.3 托盤模塊
托盤屬于系統(tǒng)級(jí)的操作,所以是在主進(jìn)程中設(shè)置的厌蔽。在開始之前需要注意的地方牵辣,設(shè)置托盤必須在程序ready之后。實(shí)現(xiàn)較簡(jiǎn)單奴饮,代碼如下:
3.2.4 異常處理模塊
主要調(diào)用Electron框架本身API纬向,結(jié)合Node.js API,檢測(cè)系統(tǒng)異常后自動(dòng)刷新并上報(bào)戴卜,渲染進(jìn)程的異常已經(jīng)使用sls&arms處理逾条,主進(jìn)程的異常主要是通過(guò)Electron的crashReporter API來(lái)記錄日志。
上面提交參數(shù)有幾個(gè)需要注意的點(diǎn):
submitURL 是以post方式上傳
extra 一個(gè)你可以定義的對(duì)象投剥,附帶在崩潰報(bào)告上一起發(fā)送 . 只有字符串屬性可以被正確發(fā)送师脂,不支持嵌套對(duì)象
3.3 渲染進(jìn)程功能模塊
渲染進(jìn)程的代碼大部分跟商家客服web端一致,很多只是遷移即可江锨。
3.3.1 登錄改造
登錄信息本地化危彩,在登錄成功的時(shí)候,把賬號(hào)信息緩存泳桦,下次打開應(yīng)用的時(shí)候客服無(wú)需再重新輸入汤徽,直接從緩存獲取即可。
3.3.2 靜態(tài)資源
傳統(tǒng)Web應(yīng)用灸撰,將項(xiàng)目代碼部署服務(wù)器谒府,項(xiàng)目運(yùn)行時(shí),訪問(wèn)的是服務(wù)器靜態(tài)資源浮毯,現(xiàn)在版本發(fā)布流程完疫,走的是cdn資源,總而言之都是通過(guò)網(wǎng)絡(luò)獲取债蓝。
Electron提供將靜態(tài)資源打包到安裝程序壳鹤,在安裝時(shí),將項(xiàng)目文件同步安裝到用戶電腦饰迹,使其具備訪問(wèn)本地文件芳誓,減少了請(qǐng)求占用資源,一定程度上也能改善因網(wǎng)速問(wèn)題導(dǎo)致的靜態(tài)資源不能實(shí)時(shí)獲取啊鸭,頁(yè)面白屏問(wèn)題锹淌。
3.3.3 數(shù)據(jù)存儲(chǔ)
Electron應(yīng)用里面的數(shù)據(jù)存儲(chǔ)是通過(guò)Electron-store第三方庫(kù)來(lái)實(shí)現(xiàn)的,實(shí)現(xiàn)比較簡(jiǎn)單赠制,如下:
3.3.4 渲染進(jìn)程打包
這塊為什么要單拎出來(lái)講渲染進(jìn)程打包呢赂摆,是因?yàn)閣eb項(xiàng)目遷移變成應(yīng)用渲染進(jìn)程的時(shí)候不能像web應(yīng)用一樣直接打包,需要調(diào)整請(qǐng)求API代碼,API前綴需要區(qū)分本地調(diào)試和應(yīng)用環(huán)境:
使用Electron, 將項(xiàng)目打包成離線應(yīng)用烟号。使用file協(xié)議绊谭,在本地讀取靜態(tài)資源。但是ajax請(qǐng)求如果用相對(duì)路徑汪拥,打包之后达传,會(huì)直接找到根目錄,如下截圖:
所以打包的時(shí)候需要給ajax提供完整的url路徑喷楣。
4.技術(shù)挑戰(zhàn)
在從0到1搭建商家客服桌面端的過(guò)程中趟大,遇到了很多的問(wèn)題鹤树,Electron社區(qū)雖然很活躍铣焊,但是不一樣場(chǎng)景遇到的問(wèn)題,幾乎找不到對(duì)應(yīng)的解決方案罕伯,所以很多都是在探索過(guò)程中不斷的去完善曲伊。這里主要圍繞發(fā)布構(gòu)建流程和安全性來(lái)講下,我們是怎么解決的追他。
4.1 安全性問(wèn)題
Electron客戶端的安全問(wèn)題也是非常重要的坟募,那都遇到了哪些安全問(wèn)題以及我們又是如何解決的呢,具體如下:
渲染進(jìn)程XSS:Electron實(shí)現(xiàn)的桌面端軟件渲染層的原理實(shí)際是通過(guò)chrome內(nèi)核渲染的邑狸,同樣存在XSS注入的風(fēng)險(xiǎn)懈糯。舉個(gè)例子:在html頁(yè)面中可以執(zhí)行命令:<img/src=x οnerrοr="require('child_process').exec('gnome-calculator')"> ,就可以打開當(dāng)前操作系統(tǒng)的計(jì)算器单雾。接入了公司統(tǒng)一的XSS治理方案赚哗,該問(wèn)題即得到解決。
用戶認(rèn)證信息泄漏問(wèn)題:商家客服桌面端登錄調(diào)用商家的授權(quán)接口硅堆,APP網(wǎng)關(guān)有校驗(yàn)屿储,可以確保登陸沒(méi)有問(wèn)題;
本地緩存明文讀取問(wèn)題:本地?cái)?shù)據(jù)泄漏渐逃,例如:indexDB够掠、localStorage、sessionStorage等茄菊,我們主要用加密和解密算法對(duì)本地緩存信息進(jìn)行處理疯潭。
沒(méi)有絕對(duì)的安全,我們能做的就是盡可能的提高安全門檻面殖,過(guò)程中我們也積極同公司的安全部門進(jìn)行溝通袁勺,讓他們排查桌面端發(fā)布之后的安全漏洞,最終驗(yàn)證都是滿足安全標(biāo)準(zhǔn)畜普,符合發(fā)布的條件期丰。
4.2 發(fā)布構(gòu)建流程
應(yīng)用發(fā)布涉及到渲染進(jìn)程和主進(jìn)程,渲染進(jìn)程主要是負(fù)責(zé)給主進(jìn)程提供渲染包,主進(jìn)程使用Electron-builder庫(kù)來(lái)打包部署所發(fā)布的包钝荡。
前面已經(jīng)說(shuō)過(guò)街立,Electron的好處是可以無(wú)縫集成web端的業(yè)務(wù)邏輯代碼,這里上圖左邊紅色的是web端構(gòu)建出的產(chǎn)物埠通,我們會(huì)把這部分構(gòu)建產(chǎn)物同步到主進(jìn)程的app/render目錄下赎离,即渲染進(jìn)程目錄,這樣在打包應(yīng)用包的時(shí)候端辱,就能集成渲染進(jìn)程的業(yè)務(wù)邏輯梁剔,而不需要維護(hù)兩份web端的代碼。
此方案還存在不少的缺陷舞蔽,由于生產(chǎn)構(gòu)建環(huán)境需要window環(huán)境荣病,所以暫時(shí)不支持在遠(yuǎn)程打包,目前都是在本地window機(jī)器上打出完整的包之后再上傳到CDN渗柿,商家客服通過(guò)加載CDN的更新包來(lái)替換本地安裝文件个盆,實(shí)現(xiàn)軟件的本地安裝。
4.3 應(yīng)用更新問(wèn)題
應(yīng)用開發(fā)離不開“更新”這個(gè)話題朵栖,比如飛書應(yīng)用會(huì)時(shí)不時(shí)彈出一個(gè)更新窗口颊亮,讓你選擇是否更新,商家客服在推廣桌面應(yīng)用之后陨溅,也存在更新這個(gè)問(wèn)題终惑。在業(yè)務(wù)快速發(fā)展的同時(shí),如何將業(yè)務(wù)需求更好的同步給商家使用门扇,這是商家客服桌面應(yīng)用面臨的最大的挑戰(zhàn)雹有。
4.3.1 全量更新
4.3.1.1 手動(dòng)下載安裝
最基礎(chǔ)的更新模式,主要思路是在打開app(其他時(shí)候也行悯嗓,我們業(yè)務(wù)主要是打開app的時(shí)候)的時(shí)候訪問(wèn)遠(yuǎn)程的json文件件舵,文件內(nèi)容包含版本號(hào),更新內(nèi)容等等最新版本的信息脯厨,拿到遠(yuǎn)程版本號(hào)會(huì)跟本地應(yīng)用版本號(hào)做比較铅祸,如果版本號(hào)不一致,就詢問(wèn)用戶是否更新合武,需要更新的話會(huì)下載到本地临梗,用戶手動(dòng)點(diǎn)擊安裝即可。這個(gè)更新方式不推薦使用稼跳,如果你的應(yīng)用一年更新一次盟庞,ok,是可以這么做的汤善。
4.3.2 增量更新
在網(wǎng)速快的情況下什猖,全量更新跟增量更新幾乎是沒(méi)有區(qū)別的票彪。但是網(wǎng)速慢的情況下它倆之間的差距會(huì)被放大,用戶體驗(yàn)不是很好不狮。我們不能想當(dāng)然的以為所有用戶網(wǎng)速都很好降铸,這是不現(xiàn)實(shí)的,所以不管是PC應(yīng)用還是移動(dòng)端應(yīng)用摇零,大多數(shù)情況下是需要做增量更新推掸。下面表格是網(wǎng)速不一樣情況下的下載耗時(shí)對(duì)比:
4.3.2.1 electron-updater
現(xiàn)在就開始介紹在商家客服應(yīng)用(windows應(yīng)用)中是怎么實(shí)現(xiàn)增量更新功能的。
更新在大的分類上區(qū)分全量以及增量更新驻仅,在每個(gè)小分類里面也區(qū)分強(qiáng)更新谅畅,弱更新(業(yè)務(wù)上的區(qū)分,底層實(shí)現(xiàn)沒(méi)區(qū)別)噪服。簡(jiǎn)單來(lái)說(shuō)毡泻,強(qiáng)更新指的是用戶必須更新,不更新將無(wú)法使用系統(tǒng)功能芯咧,弱更新指的是用戶想要的時(shí)候再去觸發(fā)應(yīng)用的更新牙捉,完全由用戶自主選擇竹揍。
更新流程
其中electron-updater作用于“更新應(yīng)用”這個(gè)節(jié)點(diǎn)敬飒,主要是依賴新舊版本blockmap文件的對(duì)比來(lái)實(shí)現(xiàn)增量更新。下面截圖為electron-builder打包出來(lái)的release包芬位,每次打包都會(huì)有對(duì)應(yīng)的blockmap文件无拗。
electron-updater更新實(shí)現(xiàn)主要流程:
- 生產(chǎn)的blockmap文件:
1.使用7z壓縮安裝包
2.讀取安裝包的header
3.計(jì)算出每個(gè)file的offset和end得到相應(yīng)的hash生產(chǎn)blockmap
- 使用blockmap文件:
1.下載云上的blockmap文件跟本地blockmap文件對(duì)比,從上面截圖可以看出blockmap文件很小昧碉,所以下載并不會(huì)對(duì)應(yīng)用性能產(chǎn)生影響
2.使用range英染,request(范圍請(qǐng)求)請(qǐng)求更新內(nèi)容的部分
4.3.2.2 文件替換
還有一種增量更新方式就是文件替換,只更新需要更新的模塊被饿,這種方式只更新需要渲染進(jìn)程的資源四康,大部分情況下主進(jìn)程的資源不用更改,所以下載的資源會(huì)比較小狭握,更新較快闪金,因?yàn)槭窃诰€熱更新,更新完成后不用重新啟動(dòng)軟件论颅,只需要刷新頁(yè)面重新加載資源即可哎垦。其實(shí)之前我覺(jué)的這樣的思路挺好的,看下面的流程圖也是可以實(shí)現(xiàn)的恃疯,也很符合商家客服桌面應(yīng)用產(chǎn)品需求漏设。
可是后來(lái)發(fā)現(xiàn)其實(shí)忽略了以下兩個(gè)點(diǎn):
替換用戶本地文件這個(gè)本身有權(quán)限問(wèn)題,比如windows用戶安裝到了C盤今妄,寫入文件是有管理員權(quán)限限制的郑口;
文件被占用問(wèn)題鸳碧,眾所周知,當(dāng)文件夾中存在正在被占用的文件時(shí)犬性,刪除會(huì)失敗杆兵。所以在覆蓋原文件同時(shí)需要退出應(yīng)用避免占用,所以這個(gè)方式也不是很可靠仔夺。
5.遇到的問(wèn)題
Electron 的硬件加速功能琐脏,在 win7 或者 Linux 系統(tǒng)上,容易出現(xiàn)黑屏或者卡死缸兔。
解決方案:判斷是不是win7及以下系統(tǒng)日裙,如果是app.disableHardwareAcceleration (),禁用當(dāng)前應(yīng)用程序的硬件加速惰蜜。
- Uncaught ReferenceError: require is not defined昂拂,這個(gè)報(bào)錯(cuò)是試圖在渲染進(jìn)程使用node的時(shí)候出現(xiàn)的,不是不能用抛猖,只要開啟 主進(jìn)程的nodeIntegration: true就好了格侯, 但不建議,有安全問(wèn)題财著。
解決方案:
- Note:you may have one or two (large) stale temporary file(s) left in your temporary directory (Generally this only happens on Windows 9x)這個(gè)是打包了半天都打不出來(lái)一個(gè)完整的包的情況下出現(xiàn)的联四。
解決方案:當(dāng)時(shí)是因?yàn)槲覜](méi)刪除原來(lái)的包導(dǎo)致我放打包文件的C盤滿了。撑教。朝墩。所以刪除一些緩存就好了,nsis打包大概率都是跟磁盤有關(guān)伟姐。
- 下載npm包特別慢
解決方案:yarn安裝收苏;Electron相關(guān)的包優(yōu)先使用淘寶鏡像安裝;使用公司鏡像安裝公司內(nèi)部包愤兵。
6.總結(jié)
一路開發(fā)下來(lái)鹿霸,感慨很多,作為公司第一個(gè)Electron應(yīng)用秆乳,不管是在開發(fā)上懦鼠,打包上,或者說(shuō)在部署上矫夷,都遇到了一些挑戰(zhàn)葛闷,在網(wǎng)上也沒(méi)有比較詳細(xì)的文檔,外面做的好的也不會(huì)把詳細(xì)方案分享出來(lái)双藕,但是即使遇到了這些問(wèn)題淑趾,也不能否認(rèn)Electron是目前最適配于我們業(yè)務(wù)目標(biāo)以及適配于開發(fā)資源的一個(gè)框架。目前已有線上穩(wěn)定版本忧陪,逐步在推廣到全部商家客服扣泊。接下來(lái)需要完善的開發(fā)流程近范,克服的技術(shù)難點(diǎn)有很多,商家客服工作臺(tái)應(yīng)用也會(huì)越來(lái)越完善延蟹。
文/Uni