摘要:而渲染帶來的性能問題主要是由于數據接口請求返回以及前端資源獲取所帶來的網絡問題。本地化實現由于我們的這面是純渲染的,所以我們一個最終的詳情頁主要是由新聞數據和靜態頁面兩者構成的。
開篇之前先介紹一下場景。信息流是一個基于用戶興趣使用算法將用戶感興趣的新聞內容推薦給用戶的一種業務。這種業務帶有非常特色的場景就是用戶有一個“永遠”都刷不完的推薦流列表,點擊列表中的新聞之后可以跳轉到其詳情頁中查看新聞的正文內容。列表一般都是由客戶端原生去實現的,而詳情頁這塊由于新聞內容結構的復雜性,一般還是會使用 h5 來實現。這樣就對我們 h5 的性能提出了要求,我們必須在用戶切換的時候將切換的白屏時間盡量減少,這樣才能提高用戶的閱讀體驗。
本文就將為大家講述一下我們是如何實現性能優化達到“閃開”的效果的。我們可以先看看效果
https://v.qq.com/x/page/j0900...,下圖左邊是正常版本,而右邊的是優化后的版本。對比之下可以發現即使我已經悄咪咪的先點擊左邊的手機,同一篇新聞右邊的打開速度明顯比左邊的要快很多。接下來就讓我們看看這個是如何做到的吧!
眾所周知,網頁中內容渲染往往根據渲染方式可以分為后渲染和前端渲染兩種方式,最近幾年由前端渲染又演化出了同構渲染,也就是大家經常說的 SSR。這幾種渲染方式的主要優缺點大概整理了主要有如下幾個方面。
后端渲染:
優勢:服務端直出首屏性能好,SEO好
劣勢:交互邏輯復雜需要兩端維護結構
前端渲染:
優勢:前端交互易維護,數據渲染分離
劣勢:首屏性能問題以及 SEO 問題
同構渲染:
優勢:首屏性能好,SEO 好,一份代碼多端運行
劣勢:代碼維護成本,服務器性能和維護成本增加
當然本篇文章不是來講各種渲染方式的優缺點的,主要是說因為種種原因我們的項目最后使用了前端 JS 渲染的方式。而 JS 渲染帶來的性能問題主要是由于數據接口請求返回以及前端 JS 資源獲取所帶來的網絡問題。為了解決這兩個問題,一方面我們采用了服務端將數據注入到頁面全局變量中的方式避免了數據請求,另一方面我們使用了 localStorage 緩存的方式將前端資源做了 LS 緩存避免了二次打開之后的前端資源請求,從而提高了前端渲染的首屏性能。
思考優化方案雖然我們避免了前端渲染的一些問題對首屏的性能做了優化,但還遠遠不夠。那目前還有哪些點可以進行優化呢?簡單的整理了下可以有如下兩個方面:
首次進入以及線上代碼有更新之后還是需要下載前端資源
服務端頁面的 ttfb 相應還有優化的空間
客戶端 WebView 打開的速度和性能還有優化的空間
從上面兩個優化點我們可以看到所有的優化還是網絡的優化,主要還是在移動端網絡對性能的影響是遠遠大于其他方面的。那么是否有什么方案能夠讓我們免去這些網絡請求呢,最終我們給的答案就是詳情頁本地化。通過本地化方案,我們將平均 820ms 的首屏渲染時間優化到了 260ms,整整提高了三倍多!
詳情頁本地化就是客戶端不走網絡請求打開新聞的方案,解決上文中列舉的所有網絡請求相關的優化點。它除了能為我們帶來首屏性能的進一步提升之外,由于它不走網絡請求的特性,也為我們解決了復雜網絡環境下頁面劫持導致的詳情頁白頁打不開的問題。同時還為我們帶來了無網絡環境下的離線閱讀新聞的能力。
本地化實現由于我們的這面是純 JS 渲染的,所以我們一個最終的詳情頁主要是由新聞數據和靜態頁面兩者構成的。
鑒于對服務端的依賴非常的少,和大部分的 SPA 頁面一樣,本質上只要在客戶端將我們的前端頁面提前下載下來就能正常打開了。
詳情頁 = 靜態頁面 + 新聞數據數據預下發
而如何在用戶還沒有打開新聞之前客戶端就能把我們的頁面資源下載下來呢?這里就不得不提一下我們的場景,因為在我們的信息流場景中,用戶永遠是通過流點擊進入到詳情頁中。而在客戶端的流中是需要加載服務端數據的,所以在這個時候其實我們就可以告知客戶端讓其提前下載好模板。當然大家不要忘記,除了頁面之外我們還要有新聞數據,為了實現純離線化同時也避免新聞數據接口的請求,在列表中還會將每條新聞的詳細數據下發下去,保證必備要素的本地化。
如圖所示,在列表請求的接口中,服務端會將需要緩存的靜態頁面地址以及每條新聞對應的新聞數據全部下發給客戶端,客戶端接收到請求之后會進行模板的下載。
客戶端行為需要的東西下發下去之后剩下的就是客戶端進行渲染了。正常來說除了模板頁面之外,服務端還需要下載其他相關的靜態資源,然后啟動一個 HTTP 服務將頁面和資源文件進行關聯,關聯之后將數據注入到頁面之后打開頁面。但這對客戶端的要求就非常多了,為了將客戶端的工作量降低,我們將所有需要使用的靜態資源通過編譯內聯到 HTML 文件內,客戶端通過字符串拼接的形式將數據注入到頁面的全局變量中。
如圖所示所有靜態資源都被標記了 inline 屬性,我們的編譯工具在讀取到這個屬性后會將當前資源給內聯到 HTML 中。同時大家注意到該模板不是以 開頭的,而是有一些截斷。這是為了給客戶端提供注入數據空間,客戶端通過模板字符串拼接的形式將新聞數據注入到全局變量中最終完成整個新聞頁面的獲取。前端代碼中則直接使用 __INJECT_DATA_FROM_CLIENT_DONT_MODIFY__ 全局變量獲取注入的數據。
頁面的更新上面就是一套完整的本地化下發并打開的流程了,總的來講就分為四步:
前端將頁面處理成真·單頁應用
服務端在列表時將數據和本地化模板下載地址通過接口下發給客戶端
客戶端獲取到模板下載地址后進行下載
當用戶打開新聞的時候客戶端將數據和模板進行拼接打開即可
但是只要有資源的分發就會涉及到資源的同步更新問題,我們的本地化模板也是一樣。在我們的線上更新的時候如何讓客戶端知曉并觸發更新行為,也是我們需要去考慮的問題。實際上大家在前兩張截圖中可以看到,為了解決這個問題,我們是在服務端下發的接口中還增加了一個 version 字段,用來標記當前 HTML 的版本。而當前端進行代碼發布的時候,我們的發布系統會有一個類似 npm 的 postpublish 的鉤子,利用這個鉤子我們告訴服務端發布成功更新版本號。最后,當客戶端接收到新的版本號的時候則會重新下載新的模板,完成一次本地模板的更新。
跨域問題在前端頁面中,Cookie 和 LocalStorage 等大量的特性是和域名相關的,而不巧的是我們的頁面中都有使用,所以跨域也是我們需要考慮到的問題。我們知道,本質上此種方案下客戶端相當于使用 WebView 打開了一個本地頁面,而在 Android 系統中 WebView 打開本地頁面的話有三種方法:
loadUrl:本質上使用 file:///temp.html 的形式打開一個本地文件 URL
loadData:和 loadUrl 類型,好的地方在于不需要寫成文件,可以直接加載頁面字符串,不過此時加載完之后頁面的 URL 是 about:blank
loadDataWithBaseURL:和 loadData 類似,好的地方在于提供了參數能夠設置當前 URL 地址
從描述中可以看到,很明顯最后一種 loadDataWithBaseURL 才是我們需要的。客戶端通過這個方法加載,設置當前頁面的 URL 為真實線上 URL,對于前端來說基本上就和線上環境無異了,本地化和線上 Cookie 和 LocalStorage 的共享都沒有問題。不過這里需要注意,第一個參數 baseUrl 僅能管住當前頁面,如果頁面做了 history.pushState() 等前進后退操作的話當前頁面地址又會變成 about:blank,此時需要再設置最后一個參數 historyUrl 才行。
后記本文給大家講述了實現本地化離線閱讀的方案。除了以上列舉的問題,我們還碰到了一些細微的問題。例如我們發現在網絡不好的情況下客戶端可能會下載模板失敗緩存了不完整的代碼,所以我們增加了模板的 md5 值一并下發給客戶端用來校驗模板是否下載完全。又如上文說了模板的更新,實際上內容也會有更新,特別是一些新聞的實時性會有比較高的要求,為了解決這個問題,我們會在頁面打開后再次去檢查一下文章的狀態,如果發生變量會切換至線上版本用來規避這個問題。除了這些之外我們還做了完備的云控后退方案,能在方案出問題的時候完美回退到普通版本。
其實大家可以看到,本地化只是我們在特定場景下決絕性能問題的一種特定思路。它并不是使用于所有的場景,所以我在文章開頭也特別強調了一下我們的應用場景方便大家去理解。但是我們只要理解這種方案的精髓,我相信在其它的一些特定場合總能發揮它的威力。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106126.html
摘要:回顧上一次參加還是年。年的還是真正的,年的會議早已經把英文全稱去掉,改稱全球大前端技術大會。同時與產品協作從產品設計方面突出關注點,做產品設計方面的優化,如站新版改造減少頁面元素,將播放器窗口直接顯示在第一屏。 回顧 上一次參加 GMTC 還是 2017 年。那時的我還是剛剛參加工作并在試用期辭職的菜鳥。 2017 年的 GMTC 還是真正的 Global Mobile Tech Co...
摘要:由于密鑰被暴露了,所以必須換新的密鑰,元首這會兒只能走途徑告訴古德里安新的密鑰,這會兒逗逼的事情來了,如何對密鑰進行加密。但是,有一點是值得說明,那就是無論是對稱加密還是非對稱加密,都頂不住用機器是強行暴力猜解私鑰。 懶漢 入門 這兩點就足以說明這篇文章不想要著有什么高端大氣的技術內容,我跟你講,全是水。不可能有什么質數素數、橢圓曲線加密、迪菲-赫爾曼什么的,不可能有的。 首先我不...
摘要:但如果數據可視化做的較弱,反而會帶來負面效果錯誤的表達往往會損害數據的傳播,完全曲解和誤導用戶,所以更需要我們多維的展現數據,就不僅僅是單一層面,目前有多種第三方庫來實現數據的可視化等。數據可視化的具體實現這里基于兩種實現方式,一種一種。 數據可視化的目的其實就是直觀地展現數據,例如讓花費數小時甚至更久才能歸納的數據量,轉化成一眼就能讀懂的指標;通過加減乘除、各類公式權衡計算得到的兩組...
摘要:性能訪問字面量和局部變量的速度是最快的,訪問數組和對象成員相對較慢變量標識符解析過程搜索執行環境的作用域鏈,查找同名標識符。建議將全局變量存儲到局部變量,加快讀寫速度。優化建議將常用的跨作用域變量存儲到局部變量,然后直接訪問局部變量。 缺陷 這本書是2010年出版的,這本書談性能是有時效性的,現在馬上就2018年了,這幾年前端發展的速度是飛快的,書里面還有一些內容考慮IE6、7、8的東...
閱讀 2716·2021-09-24 09:47
閱讀 4366·2021-08-27 13:10
閱讀 2981·2019-08-30 15:44
閱讀 1281·2019-08-29 12:56
閱讀 2594·2019-08-28 18:07
閱讀 2614·2019-08-26 14:05
閱讀 2551·2019-08-26 13:41
閱讀 1265·2019-08-26 13:33