iOS開發祕笈:如何經過WebView監控提高WebAPP性能

相對於須要專業移動開發人員的原生應用(Native APP),基於HTML5/CSS/JavaScript的WebAPP憑藉開發者門檻低、迭代迅速、支持跨平臺發佈等特色,成爲電商、銀行等網絡服務、瀏覽類應用的首選,然而因爲頁面渲染致使的性能差距是WebAPP與原生應用沒法抗衡的最大緣由,所以針對WebView組件的性能優化就顯得相當重要。
圖片描述
爲何是WebViewphp

WebAPP所顯示的Web頁面都是由一個叫作WebView的組件渲染出來的,每一個網頁都有一個連接即URL,首先將URL轉換成NSURLRequest,而後用加載網頁的類WebView加載Request,使用 - (void)loadRequest:(NSURLRequest *)request這個方法,就能將網頁加載顯示出來。css

目前iOS中有兩個加載網頁的類,分別是UIWebView和WKWebView,UIWebView是UIKit框架中的一個類,而WKWebView是WebKit框架中的類,從性能上來講WKWebView的性能高、穩定性好、佔用內存小,徹底優於UIWebView。但因爲WKWebView是iOS8提供的組件,所以系統版本低於iOS 8.0的iPhone/iPad用戶就沒法正常使用WKWebView組件開發出來的APP。因此目前大部分開發人員還在使用性能、穩定性並不理想的UIWebView進行WebAPP開發,而本文所說的雲智慧透視寶WebView性能監控也是以UIWebView爲主要優化目標。html

要進行性能監控必須得到WebAPP頁面加載全過程的性能數據,透視寶是經過向當前加載連接的html五、jsp、php網頁代碼中注入獲取數據的JS代碼,而後經過OC與JS交互,將數據傳遞給OC,而後再將數據整理髮送到透視寶後端。前端

監控哪些WebView性能數據
透視寶能監控四大類數據:html5

♦ 行爲數據:抓取用戶在移動端網頁點的行爲操做,也就是點擊網頁的內容,分析用戶的行爲ajax

♦時間相應數據:分解一個連接從加載開始到完成這段時間內,每一個階段的耗時後端

♦ Ajax請求數據:抓取終端用戶響應時間,響應數據下載時間,數據響應成功的callback執行時間和ajax錯誤數據性能優化

♦ JS錯誤數據:抓取加載連接的代碼錯誤信息網絡

① 時間響應數據及數據計算公式框架

圖片描述

(圖片來源:51cto技術博客)

參見上圖,JS傳給透視寶的時間響應數據就是這些字段,其中navigationStart是起點,全部的計算都須要依賴於它。分析移動端H5性能數據,其實就是測算HTML五、JSP、PHP等網頁元素在iOS上加載的時間長短,經過這些性能數據前段開發人員可以準確發現性能問題並及時解決,下表是透視寶定義的響應時間分解數據及計算方案:

圖片描述
② 資源時序數據

每個網頁都是有不少資源組成的,包括.js、.png、.jpg、.css、script等,每個元素的加載都須要加載時間,資源時序數據就是準確記錄每個元素的加載時間及類型,並把這些數據經過JS的performance接口直接得到並傳給OC,不須要計算。

③ JS錯誤及ajax請求數據

JS錯誤指的是抓取網頁代碼的錯誤,包括錯誤類型及堆棧信息,直接定位錯誤。ajax請求的數據有請求的連接、uri、 終端用戶響應時間,響應數據下載時間,數據響應成功的callback執行時間和ajax錯誤數據。JS錯誤和ajax請求數據都是有JS代碼直接獲取到,不須要處理。

JS代碼注入
想要準確監測網頁性能就須要進行代碼注入,而只有拿到網頁的代碼才能注入, UIWebView這個類裏面除了三個加載連接的方法和4個代理方法,就沒有其餘內容了,而這些方法並不能獲取到內容,因此咱們就須要考慮其餘方法。UIWebView在加載攔截的時候會進入NSURLProtocol這個類,而剛好這個類能拿到當前加載連接NSURLRequest,並且會走進這個類的 - (void)startLoading方法,這個方法在頁面load完成以前,頁面剛加載以後,因此就是咱們所須要的。

建立一個類,繼承NSURLProtocol這個類,重寫startLoading方法,因爲能拿到連接的request,因此咱們就對這個連接發送請求,用原生態的NSURLConnection或者NSURLSession均可以,咱們用的NSURLConnection這個類發送請求並設置代理,方法是這個 - (nullableinstancetype)initWithRequest:(NSURLRequest*)request delegate:(nullableid)delegate startImmediately:(BOOL)startImmediately,

NSURLConnection的代理方法中有一個能接受請求連接數據的方法, - (void)connection:(NSURLConnection )connection didReceiveData:(NSData )data,獲得的NSData是16進制的字節流數據,經過utf8轉碼將字節流轉換成字符串,而後發現這個字符串正好是這個當前加載網頁的代碼,

網頁代碼都是由標籤組成,都會有<head>這個標籤,咱們就把JS代碼注入到<head>標籤之下,放在本身添加的<script>標籤中;代碼實現就是獲取字符串中<head>這個字符的位置,而後在其下面插入用<script>包裝的js代碼,而後轉回成新的NSData的字節流數據。

因爲頁面尚未加載,咱們已經改動代碼了,就須要把注入JS代碼的從新記載一次,須要用NSURLProtocol的代理屬性NSURLProtocolClient,用NSURLProtocolClient這個中的這個方法- (void)URLProtocol:(NSURLProtocol)protocol didLoadData:(NSData)data,將新的NSData加載一次,轉回成NSData是由於這個方法須要的是NSData數據。

固然上面只是介紹主要實現的一些方法,還須要用到NSURLConnection的其餘代理方法,只是這些方法不須要添加什麼,按照常規處理就好了,就不一一介紹了。

性能數據獲取
加載連接過程當中JS代碼就會經過performance接口獲取數據,而後獲取的這些數據須要傳給移動端,如何傳遞數據呢,傳遞數據的過程也叫OC與JS交互的過程。

獲取數據的時機:

因爲不清楚何時JS能拿到數據,因此從最開始就須要進行交互的監控,也就是加載連接的時候,由於透視寶SDK用來監控的因此咱們不能直接使用這個方法,須要用到OC的運行時,動態加載機制,又叫hook。首先經過添加UIWebView的類目,添加類目是將UIWebView類的實現分散出來,每一個類都是由NSbject繼承下去,因此每一個類都有 + (void)load方法,並且這個方法的執行是最先的,咱們就在這個方法中使用OC的運行時runtime,使用一個方法交換UIWebView加載連接的三個方法的指針,這樣就會在執行加載方法以前執行咱們交換出來的方法,在這個方法裏面咱們傳遞一個與JS匹配的標識,經過標識相同來獲取數據,這樣作的目的就是能從最開始就監控數據的傳遞。
圖片描述
頁面加載資源時序圖

經過上述方法,透視寶可以準確獲取用戶訪問APP時的前端用戶體驗,分析網頁元素的響應時間和對用戶的影響,包括平均耗時、是否超過容忍時間、總用戶數和受影響用戶數以及在此事件上產生錯誤和崩潰的用戶數,判斷關鍵事件的性能影響嚴重程度,提供給APP開發人員進行進行鍼對性的性能優化。

相關文章
相關標籤/搜索