“秒开”浏览器实现起来有多难?
作者:billpchen,騰訊看點(diǎn)前端開發(fā)工程師
近兩年,信息流行業(yè)處于一個(gè)增長(zhǎng)緩慢甚至停滯的狀態(tài),騰訊看點(diǎn)一直在尋求自己的破局之路。研究發(fā)現(xiàn),近兩年實(shí)現(xiàn)爆發(fā)增長(zhǎng)的業(yè)務(wù)都具有用戶覆蓋面大、差異化小的普適特點(diǎn)。
什么內(nèi)容具備普適特點(diǎn)呢?有兩類,一類是打發(fā)時(shí)間、放松解壓的搞笑內(nèi)容,一類是明星八卦、話題談資的熱點(diǎn)內(nèi)容,這兩類內(nèi)容具有低門檻、 快消費(fèi)、易傳播的特點(diǎn)。為了進(jìn)一步降低內(nèi)容消費(fèi)的門檻,我們把消費(fèi)場(chǎng)景放在了信息流中,用戶無需進(jìn)入詳情頁(yè)就可以直接消費(fèi)完文字、圖片、動(dòng)圖、視頻等內(nèi)容,這種新的內(nèi)容形態(tài)被稱為“短內(nèi)容”,由短內(nèi)容構(gòu)成的信息流被稱為“短內(nèi)容頁(yè)面”。
QQ 瀏覽器中短內(nèi)容頁(yè)面的入口是在推薦流中的短內(nèi)容卡片,一般帶有分享、評(píng)論、點(diǎn)贊互動(dòng)欄的就是短內(nèi)容卡片,點(diǎn)擊短內(nèi)容即可以進(jìn)入短內(nèi)容頁(yè)面。
對(duì)于 C 端頁(yè)面,用戶體驗(yàn)尤為重要,尤其是首屏體驗(yàn),更是奠定了用戶的第一印象,所以“性能優(yōu)化/首屏優(yōu)化”常作為前端人的重要研究課題。那短內(nèi)容頁(yè)面的首屏體驗(yàn)是怎么樣的呢?
看完上面在手機(jī)性能相對(duì)較好的 iPhone X 上的演示動(dòng)圖,你一定會(huì)感覺到這真是個(gè)糟糕的體驗(yàn),那到底糟糕在哪里呢?具體有三點(diǎn):白屏?xí)r間長(zhǎng)、圖片加載慢、頁(yè)面過渡僵硬。本地的首屏優(yōu)化方案就集中在這三方面,本文也圍繞這三點(diǎn)詳細(xì)闡述。
1. 白屏?xí)r間長(zhǎng)
所謂白屏,指打開新頁(yè)面時(shí)屏幕中沒有任何有意義的內(nèi)容,只有無休無止令人窒息的空白。造成頁(yè)面白屏的原因有不少,比如頁(yè)面崩潰、網(wǎng)絡(luò)資源加載較慢、頁(yè)面啟動(dòng)卡頓等等,這里不討論頁(yè)面崩潰等程序出現(xiàn) bug 的場(chǎng)景,有 bug 就去解決嘛。
我們都討厭白屏,有時(shí)白屏?xí)r間比較短,在我們的容忍范圍內(nèi),但有時(shí)白屏?xí)r間很長(zhǎng),那就令人煩躁了。據(jù)統(tǒng)計(jì),大多數(shù)用戶可以忍受 1000ms 以內(nèi)的白屏?xí)r間,超過 1000ms 時(shí)隨時(shí)間的變長(zhǎng)越來越無法忍受。所以我們的首屏優(yōu)化目標(biāo)是 1000ms 以內(nèi),即“秒開”。
定好了目標(biāo),下面貌似就應(yīng)該行動(dòng)起來尋找解決方案了,但等等,我們一直在說“首屏”,那什么是首屏,我們得先嘮嘮。首屏的英文名是 “Above the Fold”,Fold?跟折疊有什么關(guān)系?“Above the Fold” 這個(gè)概念最早用于出版行業(yè),買過報(bào)紙的同學(xué)都知道,因?yàn)榉奖惆徇\(yùn),報(bào)紙的一般都是折疊起來的,即使是“頭版”,也分朝上和朝下的一面,如圖所示,朝上的那一半被稱為 “Above the Fold”,也是被報(bào)社認(rèn)為最重要的位置。延伸到互聯(lián)網(wǎng)產(chǎn)品,“Above the Fold” 用來指代頁(yè)面不用操作(比如點(diǎn)擊、滾動(dòng))就能看到的信息。
明白了“首屏”,那什么是“首屏?xí)r長(zhǎng)”?雖然“首屏”這個(gè)概念是從報(bào)紙那里借鑒過來的,但我們看到報(bào)紙的頭版也就看到了,不存在先看到一部分再看到完整的,所以“首屏?xí)r長(zhǎng)”是屬于互聯(lián)網(wǎng)產(chǎn)品特有的概念。為了衡量看到“首屏”內(nèi)容的效率,人們定義了很多標(biāo)準(zhǔn),比如 Google 就定了 FP、FCP、FMP 等很多指標(biāo)來衡量首屏的性能,久而久之,這些標(biāo)準(zhǔn)成了大家公認(rèn)的標(biāo)準(zhǔn)。短內(nèi)容頁(yè)面基于 Hippy,一種動(dòng)態(tài)化框架,本身沒有什么衡量標(biāo)準(zhǔn),所以我們就仿照 Chrome,定義了動(dòng)態(tài)化頁(yè)面的首屏打開性能指標(biāo):FCP 和 FMP。
在我們的定義中,短內(nèi)容頁(yè)面的 FCP 指的是從外層入口點(diǎn)擊的時(shí)間點(diǎn)到短內(nèi)容頁(yè)面根元素 didMount 的時(shí)間點(diǎn)的差值,FMP 指的是從外層入口點(diǎn)擊的時(shí)間點(diǎn)到短內(nèi)容第一條卡片根元素 didMount 的時(shí)間點(diǎn)的差值。這里的 FCP 和 FMP 可能跟 Chrome 中的定義有所偏差,不過無傷大雅,我們需要的只是有那么幾個(gè)指標(biāo)來衡量?jī)?yōu)化前后的效果。
明確了首屏?xí)r長(zhǎng)的衡量標(biāo)準(zhǔn)后,那下面我們就可以開始正式的優(yōu)化環(huán)節(jié)了。從哪里下手呢?既然要縮減白屏?xí)r長(zhǎng),那就要了解首屏加載有哪些環(huán)節(jié),辨別出關(guān)鍵的耗時(shí)環(huán)節(jié)才能有的放矢。
如圖所示,當(dāng)用戶點(diǎn)擊了短內(nèi)容頁(yè)面的入口時(shí),客戶端開始創(chuàng)建 Activity,然后開始創(chuàng)建 Hippy 引擎,引擎創(chuàng)建完成后加載 Bundle,而后向前端發(fā)送 loadInstance 事件開始啟動(dòng)業(yè)務(wù),接著便開始渲染 HippyRootView,下面的事前端就比較熟悉了,拉取數(shù)據(jù),渲染內(nèi)容。
整個(gè)過程可以分為兩個(gè)部分:頁(yè)面啟動(dòng)和數(shù)據(jù)加載,我們分別從這兩方面進(jìn)行優(yōu)化。
1.1 頁(yè)面啟動(dòng)
頁(yè)面啟動(dòng)階段主要有 initEngine、onInitialized、loadModule 和 loadInstance 4 個(gè)階段,逐個(gè)分析發(fā)現(xiàn),在“加載 bundle” 階段我們可以有所作為。加載 bundle 的時(shí)間跟 bundle 體積成正相關(guān),如果我們把 bundle 的體積減小,那么 bundle 自然加載地更快。如何減包呢?我們可以使用 Webpack Bundle Analyzer 對(duì) bundle 進(jìn)行分析。
從分析結(jié)果中,我們可以看到有近 10 個(gè)文件的體積超過了 100 KiB,還有很多的文件達(dá)到數(shù)十 KiB,那開始挨個(gè)分析每一個(gè)文件。雖然 CircleCommJce.js 體積最大,但項(xiàng)目處于新舊交替過程中,項(xiàng)目原先是通過 WUP 協(xié)議拉取數(shù)據(jù),而現(xiàn)在隨著騰訊看點(diǎn)三端(QQ 看點(diǎn)、QQ 瀏覽器、看點(diǎn)快報(bào))的統(tǒng)一,CGI 服務(wù)也統(tǒng)一成 HTTP,所以這里逐漸會(huì)將 WUP 協(xié)議換成 HTTP 協(xié)議,等項(xiàng)目協(xié)議切換完成,這些與 WUP 相關(guān)的文件都可以刪掉了。與 CircleCommJce.js 類似的還有 MTT4PageInfoJce.js 等等,這些文件我們暫時(shí)不作改動(dòng)。
接著,lodash.js 這個(gè)文件引起了我的注意。Lodash 是一個(gè)便捷的 JS 工具庫(kù),但便捷的代價(jià)就是項(xiàng)目體積的增加,這不,lodash.js 就有 466 KiB。那如何減少這個(gè)文件的體積呢?很簡(jiǎn)單,徹底不用。在項(xiàng)目中檢索 “l(fā)odash”,發(fā)現(xiàn)被引用了 19 次,共 45 次調(diào)用。乍一看還挺多,仔細(xì)梳理,發(fā)現(xiàn)一共就用到了 Lodash 的 5 個(gè)方法:_.get、_.chunk、_.pick、_.pickBy 和 _.mapValues。將這些方法用自己寫的 JS 函數(shù)替代,比如下面就是 _.get 的簡(jiǎn)單實(shí)現(xiàn)。
將 lodash.js 刪掉后,打包后的 bundle 體積減少了 2.4%,安卓的啟動(dòng)時(shí)長(zhǎng)減少了 5.2%,iOS 的啟動(dòng)時(shí)長(zhǎng)減少了 3.9%。
1.2 數(shù)據(jù)加載
數(shù)據(jù)加載階段主要包含 fetch 和 setContentView 兩個(gè)階段,逐個(gè)分析發(fā)現(xiàn),主要的耗時(shí)環(huán)節(jié)是獲取數(shù)據(jù)環(huán)節(jié),那如何優(yōu)化這部分的耗時(shí)呢?我們?cè)俅渭?xì)化獲取數(shù)據(jù)環(huán)節(jié),大概分為 DNS - 建立連接 - 后臺(tái)處理 - 個(gè)性化推薦 - 數(shù)據(jù)返回這幾個(gè)階段。網(wǎng)絡(luò)傳輸環(huán)節(jié)與運(yùn)營(yíng)商相關(guān),個(gè)性化推薦與算法、機(jī)器數(shù)量和性能相關(guān),即便優(yōu)化,耗時(shí)也很難有實(shí)質(zhì)性的縮減。總而言之,從減少獲取數(shù)據(jù)耗時(shí)這一環(huán)節(jié)本身出發(fā),我們做不了什么。那是否意味著這個(gè)環(huán)節(jié)我們不能優(yōu)化了呢?方法還是有的,我們可以提前獲取數(shù)據(jù),然后緩存到本地,等用戶打開頁(yè)面的時(shí)候直接從緩存獲取第一刷的數(shù)據(jù)。從緩存讀取數(shù)據(jù)會(huì)比從網(wǎng)絡(luò)讀取數(shù)據(jù)減少不少的耗時(shí),那具體怎么做呢?
短內(nèi)容頁(yè)面的入口是推薦流中的短內(nèi)容卡片,當(dāng)推薦流中有短內(nèi)容卡片曝光時(shí),QQ 瀏覽器將會(huì)去網(wǎng)絡(luò)拉取一刷數(shù)據(jù)緩存到本地。如果用戶真的點(diǎn)擊了短內(nèi)容卡片進(jìn)入了短內(nèi)容頁(yè)面,那么會(huì)直接從緩存中獲取數(shù)據(jù)。這個(gè)方案被稱為“數(shù)據(jù)預(yù)加載”。
道理我都懂,但感覺太簡(jiǎn)單,里面會(huì)不會(huì)有坑呢?有的,數(shù)據(jù)預(yù)加載可能存在四個(gè)方面的問題。
流量浪費(fèi)
如果用戶沒有進(jìn)入短內(nèi)容浮層,那這部分流量不是浪費(fèi)了嗎?這里要分兩方面看。一方面是公司的流量浪費(fèi),公司的流量費(fèi)用是與公司峰值帶寬相關(guān)的,數(shù)據(jù)預(yù)加載對(duì)公司的峰值帶寬影響不大,所以不會(huì)導(dǎo)致公司方面的流量浪費(fèi);另一方面是用戶的流量浪費(fèi),據(jù)統(tǒng)計(jì)有 44% 的短內(nèi)容用戶用流量瀏覽,對(duì)于這部分用戶來說,預(yù)加載方案是一種以空間換時(shí)間的方式,這部分的流量浪費(fèi)不可避免,并且為了減少流量浪費(fèi),我們選擇了預(yù)加載 3 條而不是更多,因?yàn)橐话闱闆r下 3 條恰好可以覆蓋一屏,包含 1 條主 TL 的帖子和 2 條推薦帖子。
推薦浪費(fèi)
用戶看到的帖子都是由推薦系統(tǒng)推薦的,已經(jīng)看過的帖子推薦系統(tǒng)就不會(huì)再給我們推送了,這叫“曝光去重”。在數(shù)據(jù)預(yù)加載場(chǎng)景下,很可能會(huì)出現(xiàn)推薦系統(tǒng)推薦了帖子,但用戶實(shí)際上沒有進(jìn)入短內(nèi)容頁(yè)面也就沒有消費(fèi)這些帖子的情況,這叫做“推薦物料浪費(fèi)”。針對(duì)這種情況,我們與推薦后臺(tái)約定,預(yù)加載出的推薦數(shù)據(jù)在下一次推薦時(shí)不會(huì)被曝光去重,只有用戶真正消費(fèi)的時(shí)候,前端回寫曝光數(shù)據(jù),告訴推薦后臺(tái)哪些帖子被真正消費(fèi)了,那么這些帖子才會(huì)被曝光去重,那么這樣也就避免了推薦物料被浪費(fèi)的情況。
緩存關(guān)閉
預(yù)加載的數(shù)據(jù)會(huì)被瀏覽器緩存在內(nèi)存中,當(dāng)瀏覽器運(yùn)行在前臺(tái)時(shí),手機(jī)分配的內(nèi)存空間足夠;而當(dāng)瀏覽器切到后臺(tái)時(shí),手機(jī)分配的內(nèi)存空間減少,會(huì)導(dǎo)致預(yù)加載數(shù)據(jù)的緩存空間被清除,這樣不僅之前緩存的預(yù)加載數(shù)據(jù)都被清除,下一次寫緩存數(shù)據(jù)時(shí)也會(huì)失敗。為了解決這個(gè)問題,只要每次寫緩存時(shí)檢查一下緩存空間還在不在,在的話就就直接寫,不在的話就得重新創(chuàng)建緩存空間。
二次打開
當(dāng)用戶退出短內(nèi)容頁(yè)面時(shí),大約會(huì)有 3% 的用戶會(huì)重新進(jìn)入。第一次打開短內(nèi)容頁(yè)面的時(shí)候,推薦的 2 條數(shù)據(jù)會(huì)被清除,緩存中只會(huì)留下第一條數(shù)據(jù)。用戶第二次進(jìn)入的時(shí)候,只會(huì)讀取那一條緩存的內(nèi)容,其余的需要從網(wǎng)絡(luò)拉取。
1.3 Bundle 預(yù)加載
分析了首屏渲染的各個(gè)關(guān)鍵耗時(shí)環(huán)節(jié),我們縮減了 bundle 的體積,提升了頁(yè)面啟動(dòng)的速度;同時(shí)對(duì)數(shù)據(jù)進(jìn)行了預(yù)加載,第一刷的數(shù)據(jù)直接從緩存中讀取,提升了數(shù)據(jù)拉取速度。除此以外,還有其他優(yōu)化方法嗎?減包加速頁(yè)面啟動(dòng)終究還是有瓶頸,何不一步到位直接讓頁(yè)面運(yùn)行在后臺(tái),等到用戶真正點(diǎn)擊的時(shí)候再把頁(yè)面提升到前臺(tái)呢?
這個(gè)方案的原理跟手機(jī)中的 APP 很相似,如果一個(gè) APP 運(yùn)行在后臺(tái),那被切到前臺(tái)時(shí)將會(huì)很快,但如果被第一次打開,耗時(shí)將會(huì)較長(zhǎng)。所謂的 bundle 預(yù)加載,就是將短內(nèi)容頁(yè)面預(yù)先加載在瀏覽器的后臺(tái),等到用戶點(diǎn)擊打開頁(yè)面時(shí)再顯示出來。這一過程的演示:
視頻中透明的浮層代表沒有任何內(nèi)容的短內(nèi)容頁(yè)面,當(dāng)瀏覽器啟動(dòng)時(shí),會(huì)在背后悄悄啟動(dòng)一個(gè)空白的短內(nèi)容頁(yè)面,如果用戶點(diǎn)擊了入口短內(nèi)容卡片,那么這個(gè)空白的短內(nèi)容頁(yè)面將會(huì)被提升到瀏覽器的最頂層,并且被渲染。這樣,bundle 加載的耗時(shí)將會(huì)被大大縮減。除此以外,瀏覽器還會(huì)在后臺(tái)又啟動(dòng)一個(gè)空白的短內(nèi)容頁(yè)面,以備下一次用戶打開短內(nèi)容頁(yè)面使用。
1.4 小結(jié)
為了解決白屏?xí)r間長(zhǎng)的問題,我們仔細(xì)剖析了頁(yè)面加載中的每一個(gè)環(huán)節(jié),其中針對(duì)“加載 bundle”和“獲取數(shù)據(jù)”兩個(gè)關(guān)鍵耗時(shí)環(huán)節(jié)采取了“減包”和“數(shù)據(jù)預(yù)加載”措施,同時(shí)也認(rèn)識(shí)到“減包”所帶來的收益是遞減并且有瓶頸的,所以直接采用“bundle 預(yù)加載”的方式,在瀏覽器啟動(dòng)時(shí)準(zhǔn)備一個(gè)運(yùn)行在后臺(tái)的空白短內(nèi)容頁(yè)面,用戶打開時(shí)直接使用該空白頁(yè)面,大大縮減了頁(yè)面啟動(dòng)了時(shí)間。
2. 圖片加載慢
從網(wǎng)絡(luò)加載圖片資源需要一定的耗時(shí),所以時(shí)常會(huì)出現(xiàn)文字已經(jīng)展示但圖片還是一片灰色的情形。那如何縮減圖片的加載時(shí)長(zhǎng)呢?我們探索出了 4 個(gè)方案:圖片壓縮、圖片裁剪、SharpP 和圖片預(yù)加載。
2.1 圖片壓縮
縮減網(wǎng)絡(luò)傳輸時(shí)長(zhǎng),最簡(jiǎn)單有效的方式便是減小網(wǎng)絡(luò)包的大小,圖片也不例外,所以我們很自然地想到了壓縮圖片。那如何壓縮圖片呢?得益于騰訊強(qiáng)大的技術(shù)基礎(chǔ)建設(shè),我們有比較完善的圖片服務(wù)。
這是一條常見的圖片 CDN 地址,主要包含 CDN 域名、圖片平臺(tái)業(yè)務(wù)ID、File ID 和壓縮寬度幾個(gè)部分,我們關(guān)心的圖片壓縮就跟這最后一個(gè)部分相關(guān)。
在上面的鏈接例子中,/0 指的是原圖,除了 /0 外,還有 /900、/600、/320、/200 和 /180 共計(jì) 6 種配置,/900 的意思是圖片最大的寬度是 900 像素,如果原圖寬度大于 900 像素就會(huì)被等比縮放到 900 像素,如果小于 900 像素則保持不變。
那問題來了,該選哪一種壓縮比例呢?
以 iPhone 11 為例,橫向上像素值為 828。如果圖片寬度大于 828,那么在 iPhone 11 上展示時(shí)就很清晰;如果圖片寬度小于 828,那么在 iPhone 11 上展示就會(huì)被拉伸,原圖寬度越小模糊感就越強(qiáng)烈,所以要想圖片在 iPhone 11 上展示清晰,需要寬度大于 828 像素,所以只有壓縮比例為 /0 或 /900 的圖片符合要求,挑選最小的尺寸即可,即 /900。同樣的,如果手機(jī)屏幕寬度只有 400 像素,那么圖片的寬度大于 400 像素即可,/0、/900 和 /600 都符合要求,我們選擇尺寸最小的 /600。
明白了這個(gè)道理,我們看實(shí)際應(yīng)用中的情況。上面的例子中是雙圖的場(chǎng)景,即兩張圖片并列排版,這樣每張圖片的展示區(qū)域最大是 828 / 2 = 414,也就是圖片的寬度大于 414 像素就足夠清晰了,滿足條件的有 /0、/900 和 /600 三種壓縮尺寸,我們選擇最小的 /600。
再看三圖的場(chǎng)景,每張圖片的展示區(qū)域最大只有 828 / 3 = 276 像素,所以 /320 已經(jīng)足夠滿足需要了。
綜上所述,圖片的壓縮尺寸由圖片的展示區(qū)域決定,而展示區(qū)域由手機(jī)分辨率和圖片的排版決定。
2.2 圖片裁剪
那有沒有辦法再減小圖片的大小呢?有的,圖片裁剪。
短內(nèi)容頁(yè)面中多圖都是以 1 : 1 展示的,也就意味著超出 1 : 1 的部分不僅不會(huì)展示,還會(huì)增加圖片的大小導(dǎo)致圖片加載耗時(shí)變長(zhǎng)。這樣的話,我們只需要加載 1 : 1 的部分就可以了。理想很豐滿,現(xiàn)實(shí)也很性感,強(qiáng)大的圖片服務(wù)也提供了圖片裁剪功能!
不過不是所有的圖片都支持裁剪,只有滿足業(yè)務(wù) ID 為 “qq_public_cover” 并且 File ID 以 “_open” 結(jié)尾的圖片才能夠裁剪。一共支持 16 種裁剪尺寸,239 ?95、358 ?143、564 * 280……其中數(shù)字僅表示裁剪比例,不表示圖片寬度。
上圖顯示了按一定比例裁剪后的圖片的 3 種樣式。
因?yàn)槎鄨D場(chǎng)景下圖片都是 1 : 1 展示的,所以我們只需要拉取對(duì)應(yīng)尺寸的圖片,即在 File ID 末尾加上 “_280_280”。上面的例子中,原圖 26KB,裁剪后的圖片只有 18KB,圖片體積縮減了 30%。
這里需要提一下的是,圖片裁剪服務(wù)原本的使用場(chǎng)景并不是為了縮減圖片體積,而是為了突出圖片主體。我們是不是經(jīng)常遇到因?yàn)閳D片中人物頭像在頂部,在信息流中展示時(shí)頭部被裁切掉,然后只能看到半截身子的情況?裁圖服務(wù)可以將原圖裁剪成不同比例,并且保證每種比例都會(huì)突出圖片主體,比如人物、動(dòng)物、物體等等,信息流業(yè)務(wù)在使用圖片時(shí)選取一種與展示比例相近的裁剪尺寸,這樣展示的圖片可以較好地突出主體。下面的例子可以很形象的展示是否使用裁剪過的圖片的不同效果,前者使用原尺寸,主體頭部被裁切,后者使用 280 * 280 比例的裁剪,主體依舊完整。
2.3 SharpP
前面兩個(gè)都是縮減靜圖加載時(shí)長(zhǎng)的方法,那動(dòng)圖呢?
動(dòng)圖我們采用了 SharpP 格式,這是騰訊自研的圖片壓縮技術(shù),對(duì)標(biāo)業(yè)界的 WebP,不過卻比 WebP 有更好的壓縮效果。
2.4 圖片預(yù)加載
無論是減包還是 SharpP,總會(huì)有一定的網(wǎng)絡(luò)耗時(shí),如果還想減少圖片加載耗時(shí)應(yīng)該怎么辦呢?沒錯(cuò),預(yù)加載圖片~
當(dāng)推薦流中短內(nèi)容卡片曝光后,瀏覽器會(huì)去請(qǐng)求第一條短內(nèi)容的圖片并緩存起來。短內(nèi)容頁(yè)面打開時(shí),直接使用緩存的圖片,這樣就可以避免長(zhǎng)時(shí)間只能看到圖片灰底的情況。不過為了節(jié)約流量,目前只會(huì)預(yù)加載第一條短內(nèi)容的圖片。下面的例子中,正文圖片很快加載完成,與此形成鮮明對(duì)比的是尺寸很小的頭像,在正文圖片加載完成后仍然還是灰底。
2.5 小結(jié)
為了解決圖片加載慢的問題,我們采取了壓縮圖片和裁剪圖片這兩個(gè)方法縮減靜圖的體積,而對(duì)于動(dòng)圖采用了 SharpP 格式。為了進(jìn)一步提升首屏體驗(yàn),我們對(duì)第一條短內(nèi)容的圖片進(jìn)行了預(yù)加載。
3. 頁(yè)面過渡僵硬
從推薦流進(jìn)入短內(nèi)容頁(yè)面過程很僵硬,可以感覺到就是頁(yè)面間的跳變,用戶體驗(yàn)不佳。那該如何優(yōu)化呢?在調(diào)研了瀏覽器現(xiàn)有的幾種頁(yè)面打開方式后,我們決定采用“側(cè)滑”的過渡動(dòng)畫,即短內(nèi)容頁(yè)面從右往左切到瀏覽器的前臺(tái),如圖演示:
4. 小結(jié)
站在用戶角度,以用戶的眼光審視短內(nèi)容頁(yè)面的首屏體驗(yàn),我們發(fā)現(xiàn)了三大問題:白屏?xí)r間長(zhǎng)、圖片加載慢和頁(yè)面過渡僵硬。
針對(duì)白屏?xí)r間長(zhǎng)的問題,我們梳理了首屏的關(guān)鍵耗時(shí)環(huán)節(jié),再分析縮減每個(gè)環(huán)節(jié)耗時(shí)的可能性,其中在 loadModule 環(huán)節(jié)我們采取了減包的方法,在 fetch 環(huán)節(jié)我們采取了數(shù)據(jù)預(yù)加載的方法。更進(jìn)一步的,我們通過 bundle 預(yù)加載的方法,瀏覽器在啟動(dòng)時(shí)會(huì)在后臺(tái)加載一個(gè)空白的短內(nèi)容頁(yè)面,用戶點(diǎn)擊短內(nèi)容卡片時(shí),再將空白的短內(nèi)容頁(yè)面提升到前臺(tái)并且渲染數(shù)據(jù)。
針對(duì)圖片加載慢的問題,我們采用圖片壓縮和圖片裁剪的方式縮減信息流中的圖片體積,同時(shí)使用 SharpP 格式替代傳統(tǒng)的 Gif 來縮減動(dòng)圖的體積。更進(jìn)一步的,為了首屏的體驗(yàn),我們預(yù)加載了第一條短內(nèi)容的圖片。
針對(duì)頁(yè)面過渡僵硬的問題,在調(diào)研了瀏覽器現(xiàn)有的幾種頁(yè)面打開方式后,我們采用了新頁(yè)面從右邊“側(cè)滑”的過渡動(dòng)畫。
經(jīng)過這一系列的優(yōu)化,首屏性能指標(biāo)和產(chǎn)品指標(biāo)都有顯著的提升。
先看平均耗時(shí)。在優(yōu)化前,首屏 FMP 平均為 2.9s,接入數(shù)據(jù)預(yù)加載后平均 FMP 為 0.75s,再接入 bundle 預(yù)加載后平均 FMP 為 0.6s。
再看耗時(shí)分布。在優(yōu)化前,FMP 在 0.5s 內(nèi)的訪問占 0%,1s 內(nèi)占 2%,2s 內(nèi)占 39%;接入數(shù)據(jù)預(yù)加載后,FMP 在 0.5s 內(nèi)占 44%,1s 內(nèi)占 82%,2s 內(nèi)占 97%;再接入 bundle 預(yù)加載后,FMP 在 0.5s 內(nèi)占 59%,1s 內(nèi)占 87%,2s 內(nèi)占 98%。
彩蛋~
想了解鵝廠程序員有多硬核?
有哪些歡樂沙雕日常?
快來視頻號(hào)找我們!
掃碼一鍵關(guān)注騰訊程序員
總結(jié)
以上是生活随笔為你收集整理的“秒开”浏览器实现起来有多难?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PB 级大规模 Elasticsearc
- 下一篇: 2017年html5行业报告,云适配发布