网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網

小程序白屏問題和內存研究

發布時間:2018-12-14 08:59 所屬欄目:小程序開發教程

在開發小程序應用中,QA發現過幾次頁面白屏的情況,苦于難易復現和調試,故想對小程序白屏問題進行一番探究。

從小程序官方開發者文檔得知,微信小程序運行在三端:iOS(iPhone/iPad)、Android和用于調試的開發者工具。三端的腳本執行環境以及用于渲染非原生組件的環境是各不相同的[1]:

  1. 在 iOS 上,小程序邏輯層的 javascript 代碼運行在 JavaScriptCore 中,視圖層是由 WKWebView 來渲染的,環境有 iOS8、iOS9、iOS10;
  2. 在 Android 上,舊版本,小程序邏輯層的 javascript 代碼運行中 X5 JSCore 中,視圖層是由 X5 基于 Mobile Chrome 53/57 內核來渲染的;
  3. 新版本,小程序邏輯層的 javascript 代碼運行在 V8 中,視圖層是由自研 XWeb 引擎基于 Mobile Chrome 53 內核來渲染的;
  4. 在 開發工具上,小程序邏輯層的 javascript 代碼是運行在 NW.js 中,視圖層是由 Chromium 60 Webview 來渲染的。

下面說說WKWebView、Mobile Chrome 53/57、Mobile Chrome 53是什么。

在Apple公司的開發者文檔網站上,有對WKWebView進行介紹,簡單來說,WKWebView是一個為app內置瀏覽器渲染交互式網頁內容的組件,用于替換老版本的UIWebView組件[2]。不管是UIWebView,還是WKWebView,它們都屬于IOS WebView。我們可以把WebView理解為手機操作系統的一個系統級的組件。不管是手機內置的瀏覽器,還是其他app,比如微信等,只要你想呈現交互式的網頁內容,都可以調用WebView去完成這件事情。Android WebView亦是如此[3]。

現在我們可以把WKWebView稱為IOS端的WebView,那么Android端的Mobile Chrome 53/57,或者Mobile Chrome 53又是什么,這兩個跟WebView又是什么關系呢? 我們可以把Mobile Chrome 53/57理解為Chrome for Android 537版本,這里的537是指Chrome的排版引擎(layout engine)采用的WebKit內核版本,具體參考Google Chrome version history[4]。需要指出的是,53/57是不是就是537,這里存疑,沒有查到有效的參考資料,但是這個對我們的研究應該沒有什么影響,可以不予考慮。到這里,又引入了兩個概念:layout engine、WebKit內核。接下來簡單介紹一下layout engine和WebKit內核。

我們都知道瀏覽器有兩個重要的引擎:渲染引擎(rendering engine,也稱layout engine,即上面提到的排版引擎,后續為了方便,統一描述為渲染引擎)和JS引擎。其中渲染引擎負責解析網頁內容,計算顯示方式,輸出至顯示設備。JS引擎則負責解析JavaScript語言,實現網頁的動態交互效果。最開始時渲染引擎和JS引擎并沒有區分的很明確,后來JS引擎越來越獨立,內核就傾向于只指渲染引擎,即瀏覽器內核就是該瀏覽器采用的渲染引擎,主要參考X5內核調研報告[5]。在后續的討論中,瀏覽器內核就單指渲染引擎。

那WebKit內核又是什么?這個不得不追溯WebKit的歷史了。1998,自由軟件社區KDE開發了HTML排版引擎KHTML和JavaScript解析引擎KJS,也就是現代瀏覽器兩個重要的引擎。Apple公司的開發者Don Melton于2001年在KDE的基礎之上開始了WebKit項目。剛開始時,WebKit僅為KDE的復刻,我們可以理解為WebKit是KDE基礎上fork出來的分支。后來,在WebKit項目中,KHTML被命名為WebCore,KJS被命名為JavaScriptCore,主要參考維基百科[6]。至此,我們可以回答,至少針對Apple的產品來說,瀏覽器內核就是WebKit,即渲染引擎采用的是WebKit內核。

webkit項目是Apple公司發展自家瀏覽器啟動的項目。Google公司在發展Chrome瀏覽器也成立了Chromium項目。在Chromium項目中,JavaScript解析引擎采用Google自己開發的大名鼎鼎的V8引擎,渲染引擎采用的是WebKit內核。到2013年7月份,Chromium項目將渲染引擎替換為Blink引擎,并在Chrome28及后續的版本上采用[4][7]。Blink引擎是Google在WebKit項目中的WebCore基礎上fork出來的一個分支[8][9]。我們可以用一幅圖把KDE、WebKit和Chromium串聯起來:

現在,我們再回過頭來看一下Mobile Chrome 53/57,或者Mobile Chrome 53,其實它的內核還是從WebKit上演化而來。繞了這么遠,只為一句話:小程序就是運行在WebView之上。那么我們的初衷,研究小程序白屏問題,其實就是在探究WebView白屏問題。如果要更詳細一點,那就是WKWebview、Android WebView白屏的原因。

關于WKWebview白屏,網上羅列的常見原因大致有以下幾種:

  1. 內存占用比較大時,WebContent Process 會 crash,從而出現白屏現象。
  2. URL網址無效或者含有中文字符。
  3. WKWebview剛推出時,在IOS8.0~8.2會偶爾出現白屏
  4. 由于滾動組件嵌套的結構,不刷新的問題。

針對原因3,解決的方案是判斷IOS系統版本,小于8.2的使用UIWebView。如果站在小程序開發者的角度,這個跟我們好像沒有關系。小程序是個平臺,我們在這個平臺上開發我們的小程序應用,如果小程序也有這個問題,那只能由小程序團隊去解決這件事情。還有,比如原因4,我們該嵌套還是得嵌套,有問題也是小程序團隊去解決。至于原因2,如果是小程序原生開發的話,頁面間的跳轉URL包含中文也是能正常跳轉的,這個應該是小程序內部兼容了。但是原因1,這個跟我們就有很大的關系了,比如我們定義了大量的變量,使用完了卻沒有釋放,那么這部分內存在小程序銷毀之前會被一直占用。再比如我們在某一刻操作了某個比較大的變量,可能在短時間內,內存使用量也會飆升。同樣的,對于導致Android WebView白屏的問題,絕大部分也只能由小程序團隊去解決。

這樣一來,從開發小程序應用的前端角度來說,我們能夠把握的是盡量避免由于內存使用緊張導致的部分WebView被回收而出現的白屏問題。至此,我們研究的小程序白屏問題,可以轉向對小程序內存優化的研究。

下面總結一下平時開發過程中可能會導致內存警告的操作:

  1. 使用大圖片和長列表圖片。根據小程序團隊分析過的大部分案例,大圖片和長列表圖片的使用,都會引起WKWebview被回收[10]。其中長列表頁圖片是指頁面包含數目較大的列表,每個列表里面又引用了圖片。

  2. 隨意定義變量,由于小程序的機制而又沒有得到釋放。以下四種場景下定義的變量,即使離開當前頁面,變量也不會被回收:

    • 定義在Page構造器外層的全局變量。

    • 定義在data內部的數據。

    • 定義在Page內部,類data數據。

    • 掛載到getApp().globalData上的數據。

    假如我們在testvar頁面定義了上述變量,由testvar通過navigateTo跳轉到下一個頁面otherpage,在頁面otherpage里面我們可以通過getCurrentPages()獲取頁面testvar的引用,進而獲取里面的變量。通過navigateTo打開新頁面,上一個頁面進入頁面棧,并且該頁面只是hide,并不是unload[11]。小程序框架的頁面棧最多可支持10層頁面。設想一下,那些具有復雜交互的頁面,每層頁面都附帶了眾多的數據,甚至包含很多圖片,再考慮多層頁面并存的問題,那內存使用量將是很可觀的。在頁面棧里面的頁面unload之前,都會造成持續的內存占用。

  3. 短時間內大數據操作。假設在某個時間點,我們需要對接口返回的大量數據進行操作,可能會造成瞬時的內存占用。

  4. 列表數據的持續累加,導致某個數據異常大。設想一下,假如我們的列表頁有很多條數據,每經過一次分頁請求,我們就把新的數據concat到已有的數據之上,久而久之,這條數據可能會變成巨無霸,逐漸侵蝕我們的內存。

所幸的是,上述這些可能造成內存大量占用的操作,我們是可以避免或者優化的。

  1. 針對原因1中的大圖片,我們就可以適當壓縮壓縮。如果不能再壓了,或者圖片必須這么大,還有單個圖片本來都不大,但是列表太多造成引用的圖片太多怎么辦呢?好,這個可以暫時先放下,在后續的討論中再提對應的解決方案。
  2. 針對原因2,我們需要結合實際的業務場景,對那些用完就可以丟棄的,不需要伴隨頁面整個生存周期存在的變量,就不要用那四種方式去定義數據。
  3. 針對原因3,我們可以盡量和接口開發方協商,通過分頁或其他方式來避免接口一次返回大量的數據。
  4. 針對原因4,本質的原因是持續的分頁請求導致新的數據不斷追加到已有的數據之上,那么這種場景,我們就需要對已有的部分數據進行舍棄。舍棄哪些已有的數據,需要一個原則。設想一下有這樣一個場景,我們進入列表頁list,我們定義了listData用來存放每次分頁請求過來的數據。第一頁的數據過來了,listData僅僅包含第一頁數據。第二頁數據過來了,我們把新數據concat到第一頁上,此時,listData就包含了第一、第二兩個頁面的數據。第三頁的數據過來了,listData就包含前三個頁面的數據。現在我們不妨停下來想想,目前我們給用戶呈現的是第三頁的數據,第一頁的數據處于不可見的狀態,既然不可見,為何不把它丟棄?如果用戶往上滑動,需要呈現第一頁的數據時,我們可以再請求第一頁的數據。listData丟棄部分數據,會及時反饋到view層,view層部分節點也會隨之銷毀,這樣App Service層和view層占用的部分內存都會得到釋放。當然,我們提出的這種方案,就是為了解決持續的分頁請求導致新的數據不斷追加到已有的數據之上的問題,至于要不要采用,采用了什么場景下進行已有數據丟棄,丟棄哪些數據,這些都要結合實際的業務進行評估和權衡。

希望大家進行批評和指正!


易優小程序(企業版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/25019.html 復制鏈接 如需定制請聯系易優客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×