Electron啟動出現(xiàn)白屏問題的解決方案
對于 Web 開發(fā)者使用 Electron 構(gòu)建桌面應(yīng)用程序時,經(jīng)常會遇到如上圖所示的一個問題 —— 窗口加載過程中長時間白屏。在應(yīng)用窗口創(chuàng)建完成到頁面加載出來的這段時間里,出現(xiàn)了長時間的白屏,這個問題對于前端開發(fā)來說是一個老生常談的問題,純 Web 端可能就是異步加載、靜態(tài)資源壓縮、CDN 以及骨架屏等等優(yōu)化方案,但是如果是開發(fā) Electron 應(yīng)用,場景又有些許不同,因此我們也不能完全按照通用的前端解決白屏的方案進行處理,本文就來探索基于 Electron 場景下啟動白屏的解決方案。
問題原因分析
1. Electron 主進程加載時間過長
Electron 應(yīng)用在啟動時,需要先加載主進程,然后由主進程去創(chuàng)建瀏覽器窗口和加載頁面。如果主進程加載時間過長,就會導致應(yīng)用一直停留在空白窗口,出現(xiàn)白屏。
主進程加載時間長的原因可以有:
- 初始化邏輯復(fù)雜,比如加載大量數(shù)據(jù)、執(zhí)行計算任務(wù)等
- 主進程依賴的模塊加載時間長,例如 Native 模塊編譯耗時
- 主進程代碼進行了大量同步 I/O 操作,阻塞了事件循環(huán)
2. Web 部分性能優(yōu)化不足
瀏覽器窗口加載 HTML、JavaScript、CSS 等靜態(tài)資源是一個漸進的過程,如果資源體積過大,加載時間過長,在加載過程中就會短暫出現(xiàn)白屏,這一點其實就是我們常說的前端首屏加載時間過長的問題。導致 Web 加載時間過長的原因可以是:
- 頁面體積大,如加載過多圖片、視頻等大資源
- 沒有代碼拆分,一次加載全部 Bundles
- 缺乏緩存機制,資源無法命中緩存
- 主線程運算量大,頻繁阻塞渲染
解決方案
1. 常規(guī) Web 端性能優(yōu)化
Web 端加載渲染過程中的白屏,可以采用常規(guī)前端的性能優(yōu)化手段:
- 代碼拆分,異步加載,避免大包導致的加載時間過長
- 靜態(tài)資源壓縮合并、CDN 加速,減少資源加載時間
- 使用骨架屏技術(shù),先提供頁面骨架,優(yōu)化用戶體驗
- 減少主線程工作量,比如使用 Web Worker 進行復(fù)雜計算
- 避免頻繁布局重排,優(yōu)化 DOM 操作
以上優(yōu)化可以明顯減少 HTML 和資源加載渲染的時,縮短白屏現(xiàn)象。還是那句話,純 Web 端的性能優(yōu)化對于前端開發(fā)來說老生常談,我這邊不做詳細的贅述,不提供實際代碼,開發(fā)者可以參考其他大佬寫的性能優(yōu)化文章,本文主要針對的是 Electron 啟動白屏過長的問題,因為體驗下來 Electron 白屏的本質(zhì)問題還是要通過 Electron 自身來解決~
2. 控制 Electron 主進程加載時機
Electron 啟動長時間白屏的本質(zhì)原因,前面特意強調(diào)了,解決方案還是得看 Electron 自身的加載時機,因為我這邊將 Web 部分的代碼打包啟動,白屏時間是非常短的,與上面動圖里肉眼可見的白屏時間形成了鮮明的對比。所以為了解決這個問題,我們還是要探尋 Electron 的加載時機,通過對 Electron 的啟動流程分析,我們發(fā)現(xiàn):
- 如果在主進程準備就緒之前就創(chuàng)建并顯示瀏覽器窗口,由于此時渲染進程和頁面還未開始加載,窗口內(nèi)自然就是空白,因此需要確保在合適的時機創(chuàng)建窗口。
- 反之如果創(chuàng)建窗口后,又長時間不調(diào)用
window.show()
顯示窗口,那么窗口會一直在后臺加載頁面,用戶也會看不到,從而出現(xiàn)白屏的效果。
因此我們可以通過控制主進程的 Ready 事件時機以及 Window 窗口的加載時機來對這個問題進行優(yōu)化,同樣的關(guān)于加載時機我們也可以有兩種方案進行優(yōu)化:
- 通過監(jiān)聽
BrowserWindow
上面的ready-to-show
事件控制窗口顯示
// 解決白屏問題 app.whenReady().then(() => { // 將創(chuàng)建窗口的代碼放在 `app.whenReady` 事件回調(diào)中,確保主進程啟動完成后再創(chuàng)建窗口 const mainWindow = new BrowserWindow({ show:false }); // 加載頁面 mainWindow.loadURL('index.html'); // 在 ready-to-show 事件中顯示窗口 mainWindow..once("ready-to-show", () => { mainWindow.show(); }); });
上述代碼通過操作 app.whenReady()
和 BrowserWindow
的 mainWindow.once('ready-to-show')
這幾個 Electron 核心啟動 API,優(yōu)雅地處理了窗口隱藏 + 頁面加載 + 窗口顯示等問題,詳細流程如下:
將創(chuàng)建窗口的代碼放在
app.whenReady
事件回調(diào)中,確保主進程啟動完成后再創(chuàng)建窗口創(chuàng)建窗口的時候讓窗口隱藏不顯示
{ show: false }
,避免頁面沒加載完成導致的白屏窗口加載頁面
win.loadURL
,也就是說窗口雖然隱藏了,但是不耽誤加載頁面通過
ready-to-show
事件來判斷窗口是否已經(jīng)準備好,這個事件其實就代表頁面已經(jīng)加載完成了,因此此時調(diào)用mainWidnow.show()
讓窗口顯示就解決了白屏的問題
- 通過監(jiān)聽
BrowserWindow.webContents
上面的did-finish-load
或者dom-ready
事件來控制窗口顯示
app.whenReady().then(() => { // 將創(chuàng)建窗口的代碼放在 `app.whenReady` 事件回調(diào)中,確保主進程啟動完成后再創(chuàng)建窗口 const mainWindow = new BrowserWindow({ show:false }); // 加載頁面 mainWindow.loadURL(indexPage); // 通過 webContents 對應(yīng)事件來處理窗口顯示 mainWindow.webContents.on("did-finish-load", () => { mainWindow.show(); }); });
此方案與上述方案的唯一區(qū)別就是,第一個使用的是 BrowserWindow
的事件來處理,而此方案通過判斷 BrowserWindow.webContents
這個對象,這個對象是 Electron 中用來渲染以及控制 Web 頁面的,因此我們可以更直接的使用 did-finish-load
或者直接 dom-ready
這兩個事件來判斷頁面是否加載完成,這兩個 API 的含義相信前端開發(fā)者都不陌生,頁面加載完成以及 DOM Ready 都是前端的概念,通過這種方式也是可以解決啟動白屏的。
最后解決完成的效果如下:
總結(jié)
從上圖來看最終的效果還是不錯的,當窗口出現(xiàn)的一瞬間頁面就直接加載完成了,不過細心的小伙伴應(yīng)該會發(fā)現(xiàn),這個方案屬于偷梁換柱,給用戶的感覺是窗口出現(xiàn)的時候頁面就有內(nèi)容了,但是其實窗口沒出現(xiàn)的時間是有空檔期的,大概就是下面這個意思:
從上圖以及實際效果來看,其實我們的啟動時間是沒有發(fā)生改變的,但是因為端上應(yīng)用和我們純 Web 應(yīng)用的使用場景不同,它自身就是有應(yīng)用的啟動時間,所以空檔期如果不長,這個方案的體驗還是可以的。但是如果前面的空檔期過長,那么可能就是 Electron 啟動的時候加載資源過多造成的了,就需要其他優(yōu)化方案了。由此也可以見得其實對于用戶體驗來說,可能我們的產(chǎn)品性能并不一定有提升,只要從場景出發(fā)從用戶角度去考慮問題,其實就能提升整個應(yīng)用的體驗。
以上就是Electron啟動出現(xiàn)白屏問題的解決方案的詳細內(nèi)容,更多關(guān)于Electron啟動白屏的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript中常見的數(shù)據(jù)格式化方式詳解
這篇文章主要為大家詳細介紹了JavaScript中常見的數(shù)據(jù)格式化方式,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解一下2023-12-12Javascript 生成指定范圍數(shù)值隨機數(shù)
查手冊后才知道, 介紹的信息少得可憐吶, 沒有介紹生成 m-n 范圍的隨機數(shù)..., 就只是給你一個 Math.random() 了事.2009-01-01javascript 實現(xiàn)簡單的table排序及table操作練習
在這個列子中,練習了table的操作,主要有:tBodies、rows、cells,還有有關(guān)數(shù)組的排序方法:sort,按興趣的朋友可以研究下2012-12-12怎么理解wx.navigateTo的events參數(shù)使用詳情
這篇文章主要介紹了怎么理解wx.navigateTo的events參數(shù)使用詳情,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05javascript 在firebug調(diào)試時用console.log的方法
當你使用console.log()函數(shù)時,下面的firebug一定要打開,不然這函數(shù)在用firefox運行時無效且影響正常程序,如果用IE打開,將會出錯2012-05-05layer.msg()去掉默認時間,實現(xiàn)手動關(guān)閉的方法
今天小編就為大家分享一篇layer.msg()去掉默認時間,實現(xiàn)手動關(guān)閉的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09