最近做了安卓app前端資源本地化的工作,下面說明一下具體實現(xiàn)的一些點。
概覽
最近做了安卓app前端資源本地化的工作,下面說明一下具體實現(xiàn)的一些點珊拼。
概覽
如圖所示,原本我們的app基本上是一個純套殼的app流炕,單webview嵌入了一個線上的h5頁面澎现,App提供視圖渲染和功能拓展(拍照,定位等)每辟,只要去更新線上的前端代碼就可以更新當前app了剑辫,但是這樣會有一個弊端,殺掉程序后渠欺,每次進入app都會重新向server發(fā)送請求來加載資源妹蔽,盡管目前我們的前端包不算大,在網(wǎng)速一般的時候不可避免的會出現(xiàn)白屏的情況挠将。如果內(nèi)嵌的前端資源有大量圖片胳岂,這種情況會更加糟糕。
改造后舔稀,前端資源會緩存在本地乳丰,webview的地址也指向了本地的server,這樣就可以解決上面說的痛點内贮,但與此同時又帶來了新的問題产园。下面梳理一下這次優(yōu)化所碰到的坑。
坑點
我們所使用的跨平臺框架是capacitorjs夜郁,官方文檔在這里什燕。
- 網(wǎng)絡請求,之前前端資源和服務器上的接口屬于同域竞端,所以不會出現(xiàn)跨域問題屎即,可是現(xiàn)在頁面實際運行的地址是localhost,那么要么后端去做一下跨域處理事富,這顯然不合理剑勾。所以最好的方式是走安卓端請求接口的方式,安卓請求接口是比http更底層的tcp赵颅,不存在跨域虽另。
在api的http部分,給了一些示例饺谬,所以我們要做的就是把目前的訪問接口方式批量改成這種嗎捂刺?早先我也是這么認為的谣拣,我們用的ajax請求庫是axios,那么動手將兩種風格統(tǒng)一族展,手動去實現(xiàn)攔截器等功能也是一個不小的工作森缠。
后面發(fā)現(xiàn),只要引入這個庫仪缸,請求似乎都走了native贵涵,不難想象出有針對xhr做全局攔截處理的代碼。示例是這樣寫的
import { CapacitorHttp } from '@capacitor/core';
然而如果想當然以為這一部分的代碼就在這里恰画,那就錯了宾茂,翻看源碼后得知這一部分的邏輯在native-bridge.js里
所以如果想讓網(wǎng)絡請求正常工作,需要安卓判斷是否有CapacitorHttp相關的處理(低版本的capacitor并沒有這些插件)拴还,有了插件也要檢查native-bridge是否有全局劫持xhr的代碼跨晴。
即使做了這些,有些特殊的請求還是要手動兼容片林,目前發(fā)現(xiàn)上傳文件接口就會出現(xiàn)(本質是multipart和json兩種數(shù)據(jù)類型的原因)端盆。
熱更新,之前說了直接使用線上地址的好處是隨時發(fā)版费封,內(nèi)容可變焕妙,那如果做本地化也想要這樣的效果需要怎么做呢,這個capacitor實在是過于小眾弓摘,比較麻煩焚鹊。最終我找到的方案就是cap-go的插件,具體使用的方法文檔說明的還算清晰衣盾,不再贅述寺旺。需要注意的是壓縮包不能包括根目錄(選取多文件壓縮多項)
自動化腳本問題爷抓,我們沒有一個完整的CI工具势决,所以之前上傳前端資源使用的是我基于nodejs寫的腳本,根據(jù)不同環(huán)境打包蓝撇,然后通過sftp協(xié)議傳到服務端果复,實際寫過nodejs腳本的人應該知道,設計之初的nodejs包含大量的回調(diào)語法渤昌,和現(xiàn)在promise風格的API是格格不入的虽抄。所以這次我基于zxjs進行了優(yōu)化,整體流程更加直觀易懂独柑。
腳本上傳文件的時候迈窟,又發(fā)現(xiàn)了新的問題,swagger和postman都能通忌栅,包括本地起的server模擬文件服務也能成功车酣,但是在線上環(huán)境就是無法直接后臺訪問接口上傳,關鍵時候使用了一下apiFox,明白了其中缺失的部分湖员。
axios({
url:`${baseUrlMap[env]}/management/web/uploadSource`,
method:'post',
data:formData,
headers:formData.getHeaders() // 關鍵語句
})
結論
事實上hybrid App在我們?nèi)粘I钪写嬖诤芏嗥肚模弥Ц秾毰e例,有時需要從應用市場重新下載娘摔,有時只需要在頁面上點擊一下更新資源窄坦,這個就是app熱更新。只要知道原理凳寺,調(diào)試的時候就不會毫無頭緒鸭津。