1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        太吾-如何在雙 11 大促中實現(xiàn)會場頁面秒開

        共 12071字,需瀏覽 25分鐘

         ·

        2021-07-31 07:13

        前端早早聊大會,前端成長的新起點,與掘金聯(lián)合舉辦。加微信 codingdreamer 進大會專屬周邊群,贏在新的起跑線。


        第三十屆|前端 BFF 專場,了解 BFF 網(wǎng)關(guān)/GraphQL/聚合/剪裁/編排/接口玩法等等的可能性,8-14 全天直播,9 位講師(螞蟻/哈啰單車/阿里/網(wǎng)易嚴選/阿里云等等),點我上車?? (報名地址):

        分享內(nèi)容舉例: 4000多臺機器,30~100 萬 QPS 的 BFF 服務(wù),是如何做安全生產(chǎn)和工程保障的(CI治理、自動化監(jiān)控、組件復(fù)用、鏈路快排、變更風(fēng)險管控...)

        所有往期都有全程錄播和 PPT,可以購買年票一次性解鎖全部

        ??更多活動


        正文如下

        自我介紹

        大家好,我是來自飛豬的胡昊,花名是太吾。先不著急開始,因為我剛才在小助手的朋友圈中看到前幾位導(dǎo)師分享的截圖,同時看到大家的一些問題。有人說我這篇分享在掘金中有對應(yīng)的文章,相信也有不少小伙伴可能看過那篇文章,我想說的是看到過那篇文章還要不要聽我這邊分享,我覺得還是要聽的。文章主要的作用是一個傳播,而一些干貨肯定還是在PPT中,所以大家還是不要放過前端早早聊 2020 年最后一次分享。前兩位大佬都是比較偏硬核:IDE 和可視化。咱最后又回到了傳統(tǒng)的 H5 上的一個性能優(yōu)化,可能沒有前兩位那么硬核,但是希望可以給大家?guī)硪恍﹩l(fā)。

        這個 PPT 也是之前用于我們集團內(nèi)的一個分享,所以有點偷懶,其實大部分內(nèi)容是差不多的,但是有一些對外還是需要有一些具體的講解。本次分享是《飛豬雙 11 - 基于 Web 的性能優(yōu)化》,雙 11 我當(dāng)時的一個職責(zé)是性能的 pm,所以對雙 11 整體的 Web 性能優(yōu)化還是有一定的理解,希望把這個理解帶給大家。

        目錄

        整個會分為三個部分來講解。

        • 背景
        • 優(yōu)化的方向。主要的優(yōu)化手段就是右邊你看到的這 6 個東西,具體內(nèi)容后面具體講解。
        • 總結(jié)和規(guī)劃

        背景

        首先是背景。從 Weex 到 Web 是基于什么樣的考慮?

        技術(shù)棧演進

        我們飛豬從 2013 年第一個 H5 頁面的落地一直到 2016 年整體切換成 Weex,無論是 Weex 還是 Rax 整體都是以 Weex 渲染為主,在飛豬端和手淘端內(nèi)。一直到 2020 年的 6 月,我們又整體順應(yīng)集團的策略又切換回 H5,技術(shù)棧也作為了統(tǒng)一,整體使用了 Rax1.0 的一個技術(shù)棧。之前可能有 Rax 的同學(xué)來前端早早聊分享過。我們怎樣基于這樣一個考慮從 Weex 切換到 H5,我們對于Weex 性能的可信度還是比 H5 要好的。但為什么要從一個相對來說好一點的 Weex 技術(shù)棧切換到 H5?主要是基于以下幾點考慮:

        • 第一,我們認為 H5 的研發(fā)體驗一定是最好的,并且在飛豬端內(nèi)升級 UC 的 U4 內(nèi)核和 WKWebview 之后,性能我們認為和 Native 的差距是逐漸的縮小,所以我們可以嘗試去進行 H5 的渲染。
        • 第二,針對之前支付寶小程序的策略,對于小程序的開發(fā)場景越來越多,而小程序的開發(fā)動態(tài)性它是不足的,因為它傳統(tǒng)的開發(fā)意義和 H5 的體系是比較割裂的,是需要開發(fā)兩套代碼。如果一個頁面要分別投小程序和 H5 的話,需要雙倍的開發(fā)成本,我們是比較無法接受的,畢竟人力那么寶貴。
        • 第三,我們還是希望去統(tǒng)一端技術(shù)的方案,希望有一套代碼可以多端投放,支持 H5、小程序,以及未來的 Flutter。其實已經(jīng)是現(xiàn)在的 Flutter。
        • 第四,Rax1.0 也是可以支持 Weex,為什么沒有編譯成 Weex?因為 Weex 和小程序都有其需要開發(fā)兼容的地方,它都是一個對于傳統(tǒng) API 的子集以及一些單獨的 API。所以我們?nèi)绻瑫r要適配 Weex 和小程序,對于開發(fā)來說是災(zāi)難性的。底下有一個開發(fā)難度的簡單對比,單純的開發(fā) H5是沒有限制的,相信很多小伙伴很樂意去開發(fā),但是小程序它是有一定的限制。如果同時開發(fā) Weex 加小程序,兩端的同時兼容,那將是無法接受的。而如果是 H5 加小程序,也只需要去單純的適配一個小程序就可以完成。這樣是相對可以接受的。

        這是一個整體的背景。

        面臨的困難

        在基于這個背景下,H5 性能肯定是比 Weex 性能相對來說要差一點。之前剛切換的 H5 之后,兩次大促(618 大促和國慶),飛豬的會場性能 IOS 大概在 1.5 秒,安卓大概在 2 秒左右。相對比淘系 618 會場的性能 1.4 秒和 2.1 秒,相對來說是差不多的。大家基本上都是把通用的優(yōu)化手段都用盡了,需要進入一個深水區(qū)。對于飛豬雙11 的目標是 IOS 1.2 秒,安卓 1.6 秒,整體是要提升大概 20% 這樣一個水平。在通用手段已經(jīng)用盡的情況下,還要提升 20%,這樣也是一個非常大的挑戰(zhàn)。

        還有在飛豬這個場景下:

        • 飛豬會場的模塊復(fù)雜。運營業(yè)務(wù)方都針對于旅游場景有很多的想法,比如頭圖這邊一定是要有視頻的,去吸引別人去玩。以及飛豬這邊互動動畫模塊。還有飛豬榜單類型,也有一些榜單的聚合模塊,這些模塊都是比較復(fù)雜的。有些是前端耗時、有些算法耗時。
        • 接口 RT 比較高。并且服務(wù)端是沒有辦法優(yōu)化的。類似榜單這種場景,它是多榜單聚合,有榜單的個性化,并且算法那邊想要去加多種模型,去更加的拉高它的 RT,理論可以為點擊率帶來一定的提升,你也沒辦法反駁別人。所以你只能讓它任由的把 RT 升高,而你毫無辦法。
        • 旅行行業(yè)的一些特點特征。我們的一些個性化或者是一些模塊,都比較依賴于定位信息以及用戶信息來給大家推相應(yīng)的一些商品,定位信息和用戶信息會更加的拖慢一個首屏的時間,所以這就是整個優(yōu)化所面臨的一些困難。

        優(yōu)化方向

        針對這些困難,視野要從前端這邊就是脫離開來,站在是多職能協(xié)同的一個方向,主要借助于客戶端以及服務(wù)端的一些能力,來進行一個整體的優(yōu)化。

        優(yōu)化思路

        整體的一個優(yōu)化思路,先說一個通用的優(yōu)化思路。

        • 第一階段白屏。整個比如說類似一個頁面,它的打開的這樣一個進度,從一開始的白屏,主要就是進行一個 Webview 初始化以及主文檔下載,基礎(chǔ) JS 下載。前幾位講師基本上提到這些過程,前端優(yōu)化手段肯定是依賴于客戶端的緩存,以及減少資源包的大小這些通用手段。
        • 第二階段 Loading 情況。這邊基本上就是發(fā)生數(shù)據(jù)請求的這樣一個階段,在這個階段可以使用的通用手段,就類似服務(wù)端優(yōu)化,請求拆分,把一個頁面的數(shù)據(jù)可以分解成首屏和非首屏這樣一個思路。首屏渲染,盡量少的 DOM,盡量少的模塊以及一些數(shù)據(jù)預(yù)加載。之前說的數(shù)據(jù)并行以及客戶端那邊并行發(fā)起數(shù)據(jù)請求方式。之前幾位講師也有提到這里就不細說了。
        • 最后階段模塊上屏。慢慢的有元素可以往屏上進行加載。這段時間它主要發(fā)生的就是模塊 JS 加載以及模塊渲染。這里的通用手段基本上也就是對于模塊 JS 精簡以及就是對于模塊的緩存。這里提一點,我們會場基本上是搭建的場景,搭建是一個什么概念?就是一個底部的頁面的 Layout 上面可以把它想象成根據(jù)參數(shù)從服務(wù)端獲取需要某個頁面需要哪些模塊,再異步的去拉那些模塊下來,把數(shù)據(jù)灌入那些模塊再進行展示,是這樣一個思路。類似于你現(xiàn)在把你的一個通用型頁面,把它拆分成很多個模塊去進行渲染,渲染哪些模塊是由服務(wù)端的數(shù)據(jù)來決定的,比較類似搭建這樣的一個場景。

        基于這些通用手段大家都想到了,大家都肯定一定都會用完的,而用完之后的效果就比如之前提到的像618、國慶大促已經(jīng)是一個頂峰,而之后想再進行優(yōu)化,就要脫離這些進行更進一步的優(yōu)化。增進式手段就有以下這些:

        • 預(yù)渲染。這個是重點保障一個主會場的打開效果。具體的實現(xiàn)之后會提到。
        • SSR。前幾個講師也有提到,我們現(xiàn)在在 C 端場景可能 SSR 提的就比較少了,用的比較少了。但現(xiàn)在又重提SSR 這是為什么?也是為了提高秒開率。之前 Weex 的情況下,其實一直都是提秒開率的,但是切換到 H5 之后,可能確實沒有 Weex 當(dāng)時這么好,所以我們需要借助一些 SSR 這樣的東西去提升我們的頁面秒開率。
        • Snapshot。類似前幾位講師說的頁面快照,把頁面的一些數(shù)據(jù)或者是頁面 HTML 直接儲存下來。在真實數(shù)據(jù)到來之前,提前展示一個頁面結(jié)構(gòu),可以大大提前用戶的可視時間,讓用戶不這么焦急等待。
        • SPA。單頁應(yīng)用這樣一個東西。把多個頁面聚合,保障頁面間的跳轉(zhuǎn)順滑,來提升用戶的體感。

        主要就是這 4 點來進行一個雙 11 大促的場景的保障。

        整體思路用渲染流程來看,塊條對應(yīng)上面的渲染流程可以精簡的部分??梢钥吹綇纳系较?SSR、Snapshop 和預(yù)渲染效果會越來越好,但是它適用的場景肯定也是越來越少的。這個之后具體會提到。類似一些客戶端預(yù)加載、資源的離線緩存、數(shù)據(jù)的變形請求和模塊的緩存,這都是一些通用的手段,是跟客戶端集成已經(jīng)用了很久了。

        整體的主要思路,之前也說到的就是壓力轉(zhuǎn)移,把客戶端的壓力轉(zhuǎn)化到服務(wù)端上去。一些緩存、依賴于客戶端的能力、階段的變形以及最后在對用戶進行一些體感上的優(yōu)化,給用戶最優(yōu)秀的體驗。

        預(yù)渲染

        首先說一下預(yù)渲染。之前講師也提到預(yù)加載,可能飛豬這邊做的更激進一點,可以先看一下右邊這個效果。左邊開啟預(yù)渲染之后,點擊就類似主會場這樣一個膠囊,跳轉(zhuǎn)過去基本上秒開,沒有任何渲染的過程那種感覺。而右邊未開啟預(yù)渲染就會有白屏、Loading 以及模塊的加載這樣一個過程,很明顯的一個對比。

        什么是預(yù)渲染?客戶端以“離屏”的方式來初始化好容器并 LoadUrl,在上屏之前就完成了頁面的 Rasterization(光柵化)。即客戶端直接把 URL 通過 Webview 在后臺 Load 好,等我們需要的時候,它直接把 Webview 進行一個上屏的操作就好了,所以做的是比較激進一點。但是為了是對于主會場這種重點保障,還是在端側(cè)這邊做了這樣一個能力,體驗是比較好。

        預(yù)渲染它有什么特點?

        • 無感直出。很明顯的一個體驗。
        • 端側(cè)定制。這可能是因為是跟端側(cè)比較耦合,可能現(xiàn)在只有飛豬端內(nèi)可以使用這樣一個能力。
        • 少量頁面。目前是只給主會場用了,因為你想想一個 APP 后臺去一直啟動這樣一個 Webview,它肯定比較耗內(nèi)存,并且是可能會引起一些 crash 風(fēng)險的。所以只能配少量的頁面,多了肯定是 crash 率可能會越來越高。

        但是這樣一個預(yù)渲染方案上了之后,F(xiàn)CP(首屏首次渲染時間)就從 1~2 秒,一直到了前端這邊的 100 毫秒,在客戶端那邊的打點基本上在 50~60 毫秒,就可以完成一個頁面的展示,相當(dāng)之快。

        方案設(shè)計

        整體的一個方案的設(shè)計,我們會有一個類似 Orange 這樣一個動態(tài)下發(fā)的平臺,去配置一些我們想要預(yù)渲染的一個URL,它就會動態(tài)下發(fā)到一個用戶的 APP 上,APP 獲取到這些配置之后,就會在后臺這邊去加載這樣一個 URL,并且解析頁面,完成頁面的光柵化之后,置入緩存池,我們還會啟動一個內(nèi)存預(yù)警的監(jiān)控,保障 APP 的運行穩(wěn)定,如果有 crash 風(fēng)險,我們會自動釋放緩存池中頁面,我們肯定還是保穩(wěn)定性為主,設(shè)計了這樣一個內(nèi)存管控。

        當(dāng)用戶真實的去訪問 H5 頁面的時候,我們會檢測用戶 是否命中了預(yù)渲染的 URL 配置。我們會有一個 URL域名,以及 URL query 的一些特殊化的參數(shù),進行 key 的對比。如果命中了之后,就會通過 URL 作為 key,在緩存池中找到 Webview,直接進行一個上屏的操作,GPU 直接進行上屏的顯示。因為用客戶端在后臺已經(jīng)渲染好這個頁面肯定跟前端的一些邏輯不相符合,所以我們需要在真實的上屏之后,客戶端會派發(fā)一個document 事件來通知 H5 頁面渲染完成之后,前端監(jiān)聽這個事件之后,我們會進行一些對于性能埋點的處理、頁面埋點的處理以及最后那些動態(tài)投放的一些事件的處理,這些都是在前端需要進行兼容的地方。

        做完這些之后,這一個頁面的整體展示邏輯就完成了。在用戶退出這個頁面之后,我們會清除對應(yīng)的 Webview 緩存,并且在 300 毫秒后立刻又在后臺重新去啟動這樣一個新的 Webview 去加載這個頁面,重新的去進行下一次的這樣一個整體流程。

        預(yù)渲染這樣一個方案比預(yù)加載只加載一個 Webview 容器,不去請求真實的數(shù)據(jù),可能會更加激進一點。但是效果也會相對來說更好一點。

        SSR

        第二個方案就是 SSR。重啟 SSR 是為了什么?一般現(xiàn)在在集團內(nèi)基本上 SSR 它的定義,從原本的 Server-side-render 慢慢轉(zhuǎn)移到 Serverless-side-render,順應(yīng) Serverless 這樣一個大潮,反正慢慢的發(fā)現(xiàn) SSR 可用武之地。我們這種不是傳統(tǒng)意義上的 SSR,跟傳統(tǒng)意義上 SSR 就是類似 PC 時代這種主文檔,就直接返回HTML主文檔的那種 SSR。

        我們不同的點是看底下這樣兩個渲染流程的對比,上面就是傳統(tǒng)的 CSR 的渲染流程,在借助客戶端的文檔緩存以及數(shù)據(jù)的預(yù)加載,之后就進行模塊的 JS 和渲染模塊。而我們這邊,通過這個圖大家可以看到我們的 SSR是在接口中返回的 HTML,在接口返回 HTML 后,我們?nèi)グ?HTML 再異步 hydrate 到頁面上去,我們相當(dāng)于是省掉了后面加載模塊 JS 和渲染模塊這樣一個流程,因為把 HTML 放在接口中返回,所以接口可能是會比平常會更慢一點。我們認為把 HTML 直接塞到頁面中去,大概會花 10 毫秒左右的時間。這樣,整體在減掉后面模塊JS 加載和渲染模塊的時間,我們這邊大概會節(jié)省 700 毫秒~800 毫秒的時間,SSR 相對于 CSR 這樣一個對比。

        方案設(shè)計

        整個渲染流程的改變,為什么是基于這樣一個考慮,而不是把在傳統(tǒng)意義上在主文當(dāng)中直接返回整個頁面的結(jié)構(gòu),而是在接口返回的時候,返回這樣一個 HTML 來再進行一個渲染。

        這背后的思考主要是基于這樣一個考慮:之前手淘那邊也做了這樣一個方案,他們當(dāng)時做了同步 SSR 放在主文檔中返回。他們當(dāng)時就發(fā)現(xiàn)有同步 SSR 后,一個是白屏?xí)r間會變得長,因為它無法使用客戶端的一些能力,例如離線包以及數(shù)據(jù)預(yù)加載這樣兩個客戶端提供了很好的一個能力。我們就跟進了異步 SSR方案,也就是放在接口中返回一個 HTML 這樣一個方式。

        它有幾個優(yōu)點:

        • 減少渲染前的模塊 Load 的時間消耗。就是模塊那邊基本上數(shù)據(jù)返回回來之后,我們就可以進行一個頁面的展示,而不用等模塊在進行一個拉取以及模塊的渲染。
        • 渲染就放在了服務(wù)端上,可以規(guī)避高低端機容器的影響。在高端機上可能就是渲染以及模塊拉取這種都可能影響還不大。但對于低端機來說,對于一些模塊的拉取和渲染,這是非常耗時的。而如果把渲染放在服務(wù)端上,就可以規(guī)避掉這樣一個高低端機容器的影響。
        • 可以復(fù)用客戶端的一個性能優(yōu)化的能力。這樣我們可以使用客戶端提供的離線包以及數(shù)據(jù)預(yù)加載的這樣一個能力,就不會浪費客戶端的一些能力。

        我們基于改造成本最小化的這樣一個原則:

        • 基于現(xiàn)有的搭建的鏈路,僅僅增加一個 SSR render 的鏈路
        • 可以做到 CSR 到 SSR 的平滑的切換
        • 僅需要判斷 HTML 是否返回,就可以切換到不同的鏈路去進行渲染,并且模塊可以基本復(fù)用,這樣就形成一個改造成本非常小的SSR 效果。

        遇到的困難

        • 一個就是如何進行平滑的切換,就是 SSR 如果出現(xiàn)了問題怎么辦?怎么降級回去?基于考慮,所以我們只需要在前端這邊判斷接口有沒有返回 HTML,就可以走到不同的鏈路上去,這是一個比較直接就可以解決問題的方法。
        • 前端穩(wěn)定性的一些考慮。因為 SSR 肯定有很多模塊,它可能就是用的一些變量,或者是用的一些異步,可能在服務(wù)端那邊拿不到模塊的具體的一個數(shù)據(jù),這樣返回的時候可能會出現(xiàn)類似報錯或者類似一開始這個模塊沒有展示出來,之后在 Web 端在 Hydrate 的時候再展示出來,像一個頁面閃動這樣一個情況。這樣對業(yè)務(wù)模塊進行一個整體的就是升級,一個是在 SSR 層做一些變量的兜底,以及對模塊進行一些類似占位這樣的一個處理,保證頁面初始化跟 hydrate 最小更新。
        • 對于沉浸式 titlebar 的一個支持。沉浸式 titltbar 肯定是要依賴客戶端的一些變量,就客戶端的 navbar 的高度是沉浸式 titltbar 的一個必要的參數(shù),而 SSR 肯定是獲取不到客戶端參數(shù)的。所以我們后來發(fā)現(xiàn)在 innerHTML 的時候,是有間隙可以獲取到這樣一個 titlebar 高度的,我們在這個時候再通過 style 去動態(tài)設(shè)置這樣一個高度就可以實現(xiàn)沉浸式 titlebar 的一個支持。
        • 最后一點,因為我們現(xiàn)在搭建這邊都是通過統(tǒng)一渲染頁。無論是離線、數(shù)據(jù)預(yù)加載以及一些模塊緩存都是有一個統(tǒng)一渲染頁這樣一個東西。而類似這樣一個統(tǒng)一渲染頁,它進行離線了之后,它里面的就是 SSR 的配置,就會固定在那里,就無法針對于單頁面,就是相當(dāng)于你所有的頁面要開 SSR 就全開 SSR。我們有些頁面肯定不一定適配好了,或者是基于流量的考慮,不可能所有頁面都開 SSR 的。所以我們得再加一層攔截去確定 是走SSR 鏈路還是普通的 CSR 鏈路。我們就去進行一個域名的攔截,通過判斷后面的 query 來判斷它是否在白名單中。在白名單中就走 SSR 鏈路,否則就走 CSR 鏈路。

        完成這些考慮之后,我們就成功地上了 SSR 方案,也得到了不錯的效果,基本上是從之前的 1~2 秒用了 SSR 之后基本上平均耗時可以降到 1 秒以下。

        Snapshot

        頁面快照。先看右邊的效果,開啟了 Snapshot 之后,就沒有 Loading 的環(huán)節(jié),直接點開頁面,頁面就直接進行一個類似直出的效果。Snapshot 實際上的效果肯定是比 SSR 要好的,但是我們有了 Snapshot 為什么還要 SSR?

        • 首先我們在營銷頁面這樣一個場景下,回訪率是比較低的。一個頁面用戶第二次去打開這個頁面的概率僅為10%~30%。所以 Snapshot 它緩存那些數(shù)據(jù),它的命中率也就只有 10%~30% 這樣一個運動率。
        • 其次就是 Snapshot 適合的是一種非千人千面的場景。有些東西類似前幾位講師也有說到,就是一個商品的時效性的問題,所以有些場景就不適合用 Snapshot。

        針對這個頁面快照,我們這邊是設(shè)計了兩種方案。一種方案是接口緩存,一種方案是傳統(tǒng)意義上的 HTML 緩存。為什么會有這兩種方案的并存?

        一種會場每天都會變陣,其實你看雙11或者雙12,你去逛會場,每天模塊的順序以及模塊的數(shù)據(jù)展示邏輯,運營每天都會去進行修改的。所以每天都會變的情況下,如果是采用了 HTML 緩存,就不可避免的帶來一些閃動的問題。例如你昨天訪問了這個頁面,今天再訪問這個頁面,它可能中間有幾個模塊沒有了,或者有幾個商品,它的坑位從 4 個變成了 6 個,這樣你進去之后,它整個頁面都會啪啪啪亂閃一氣,并且就這種閃動過程,它其實會可能會帶來很多毛病,一些不可預(yù)知的問題。例如就是模塊可能會重復(fù)的渲染,并且有些模塊它可能就會錯位這樣一個特別玄學(xué)的一些問題。所以我們又設(shè)計了第二個接口緩存的一個方式,接口緩存配合上模塊緩存,基本上也可以做到性能和直接 HTML 緩存這樣性能保持基本一致。因為接口緩存配合模塊緩存數(shù)據(jù)相對來說固定,就避免了閃動,并且我們?yōu)楹斡胁⒋孢@樣一個東西,我們會發(fā)現(xiàn) HTML 緩存也并非毫無用武之地,就類似右邊這種場景,全部會場這種場景,他在整個大促期間基本上是不會變動的。所以就采用 HTML 緩存帶來更高更快的一個加載效率,是可以使用 HTML 緩存。

        方案設(shè)計

        整個的方案設(shè)計如下:

        • HTML 緩存。它的優(yōu)點就是展現(xiàn)的速度快,操作簡單,并且它的劣勢就是在模塊不確定的環(huán)情況下,頁面可能會閃,但是它適用場景就類似全部會場這種。HTML 緩存就類似大家可以理解成你在所有的頁面展示完成之后,你去存一個首屏的一個 DOM 到緩存中去,等下次你進入這個頁面,你首先去緩存中取這樣一個 HTML,先把它給塞到屏幕上去,先給它做上屏的操作。等真實的數(shù)據(jù)回來之后,在對這樣一個界面進行一個 hydrate 操作。
        • 接口緩存。為什么接口緩存跟頁面快照有關(guān)系。因為剛才說到搭建這樣一個場景,有哪些模塊其實都是接口去進行返回的,數(shù)據(jù)也是接口返回的。所以我們只要把接口緩存下來,我們就知道這個頁面它有哪些模塊,并且那些模塊的數(shù)據(jù)是什么,只要把這個接口緩存下來,我們就可以通過這個接口直接把頁面進行一個展示。它的優(yōu)點就是頁面的展示很穩(wěn)定,但是劣勢就是相較于 HTML 緩存,它的展示會相對來說較慢一點,并且接口緩存它把整個頁面的一個JS,就是整個接口都給緩存下來,相較于緩存 HTML,它緩存的占用空間會很大,但它適用的場景就更多了。我們的一些主要的會場,例如超級寶貝、榜單會場以及特色會場,這些都是使用了這樣一個接口緩存的頁面快照方式。

        再提兩點,一些設(shè)計上的思路。第一個就是 HTML 緩存中,類似我們有一些時效性的那些商品坑位,我們不想進行一個 HTML 的保存,DOM 的保存,我們就可以自定義一些 class name。去給那些模塊設(shè)置上,到保存的時候,我們會識別這些 class name,去把它進行一個剔除,或者是只保存父節(jié)點這樣一個方式,來進行一個時效性的問題解決。還有大家可以基于這樣一個 class name 的設(shè)計,我們可以設(shè)計一些類似橫滑列表,我們只保存前幾項,或者是類似頭圖 banner,我們只保存第一項就好了。這樣一個減少 HTML 緩存的大小以及效率設(shè)計。

        第二個緩存總控。如果緩存無限制的去塞,那肯定是不行的。我們肯定是要設(shè)計一個緩存的總控來控制緩存的數(shù)量。我們用 LRU (算法)慢慢的去剔除掉使用的最少以及最遠進行訪問的一些緩存的數(shù)據(jù),把新的給緩存進來,整體控制一個最大數(shù),我們當(dāng)時應(yīng)該是當(dāng)時應(yīng)該是有緩存最多 8 個。超過 8 個之后就會進行一些剔除的一些判斷,這樣就保證一個緩存的穩(wěn)定性。

        SPA

        最后一點就是 SPA。我們慢慢的在頁面中的一些優(yōu)化,給用戶的體驗也很好了。但是頁面間的一個切換的體驗還不是很好。因為之前其實你看到底下是有 Tabbar。但是它其實是多個頁面,你如果像之前那種方式去切換底部的 Tab,其實它整個是一個頁面的跳轉(zhuǎn),是 replace 方式,整個頁面都會進行一個刷新,這樣體驗是非常不好的。

        在雙 11 的時候,我們對它進行了一個改進。底部 bar 是整體一個包框,我們通過點擊底部 bar 切換的時候,我們僅需要去獲取數(shù)據(jù)。還是剛才提到那個點,我們的頁面是通過數(shù)據(jù)進行獲取到模塊,通過模塊拼裝組成的。所以我們只需要知道模塊有哪些,我們就可以把頁面組成起來。所以我們切換 tab 的時候,我們只需要去獲取數(shù)據(jù),去獲取到模塊,把頁面的 DOM 替換一下,我們就可以完成到頁面的這樣一個切換,而不用整個的 replace。

        為什么基于 SPA 實現(xiàn),還是剛才說到那個點。

        • 搭建頁面已經(jīng)形成比較成熟的體系,就是我們的頁面框架,它是共用一套 solution/core-render 的,它不會關(guān)聯(lián)頁面,就是業(yè)務(wù)的模塊,它背后的 Layout 它所有的頁面都是一個,只是上面的模塊不同,你所以看到的頁面不同,其余的后面的 Layout 永遠都是一樣的。
        • 第二點每個頁面業(yè)務(wù)模塊它都是通過數(shù)據(jù)獲取的,這兩個都是必要條件才可以進行這樣一個 SPA 的切換。它通過數(shù)據(jù)獲取模塊,我們只需要進行一個 DOM 的切換,就可以進行一個頁面間的一個跳轉(zhuǎn),跳轉(zhuǎn)回去的時候,我們只需要緩存模塊,就可以形成無感的切換效果。

        優(yōu)化演進

        我們第一版設(shè)計開啟了 SPA 之后,我們就獲取那個模塊的數(shù)據(jù),替換當(dāng)前 tab 對應(yīng)的模塊,進行頁面的更新。但是我們發(fā)現(xiàn)這樣有一個問題:如果整體去不停的去替換模塊,還是比較卡頓的。相對于直接傳統(tǒng)意義上我們心目中那種單頁應(yīng)用還是有一點鴻溝,所以我們就對它進行了升級。

        我們只緩存首屏的 DOM,減少數(shù)據(jù)獲取的過程。并且在高端機上我們會請求首個 tab 數(shù)據(jù)渲染完成之后,我們會去預(yù)加載其他幾個 tab 的數(shù)據(jù)。這樣下次切換過去的時候就沒有數(shù)據(jù)獲取過程,我們可以直接取用它。就相當(dāng)于把多頁面之間的數(shù)據(jù)同時都拿到之后,我們切 tab 就可以形成絲滑般的切換效果。我們只需要隱藏其他 Tab 容器內(nèi) DOM。把該展示的那些 DOM 給 display 出來就好了。

        資源&數(shù)據(jù)預(yù)緩存

        最后再提兩個小點,之前講師他們也說到?;旧厦總€優(yōu)化都要借助客戶端離線能力,離線包和數(shù)據(jù)的并行請求,我看基本上是 H5 這邊是每次都會用到的。

        但是就說一點小的設(shè)計,我們對于會場頁面是設(shè)計了一個 URL + package 方式,我們會在信鴿,就是我們一個后臺去輸入需要進行離線的頁面,在會場這種場景下。我們信鴿就會在后臺跑一個 puppetter,把頁面的資源給獲取到,并且再通過一些滾屏的操作,把一些懶加載的資源也給獲取到。就把整個資源打成一個資源包,最后通過一個hash的方式,在去真實頁面訪問的時候,進行匹配。

        第二點,數(shù)據(jù)并行請求的這樣一個部分,我們設(shè)計了相對于正常的 Memory 命中Miss 不命中這樣一個狀態(tài)下,我們還設(shè)計了一個 Ongoing 這樣一個狀態(tài)。我們認為只要客戶端發(fā)起請求,那一定是比前端真實發(fā)起請求要快的要提前的,因為實際它肯定是要提前的,所以我們就會等待就是客戶端真實的請求返回之后,我們再會拿客戶端的那樣一個數(shù)據(jù),而不是重新發(fā)起一次請求。

        總結(jié)和規(guī)劃

        整個這邊就不那么細說了,反正最終達成了我們當(dāng)時這樣一個目標,基于我們之前說到的無論是通用手段也好,還是一些增進手段也好。通用手段可能也是提供了很大的一個幫助,增進手段在它的基礎(chǔ)上有個更高的一個提升。反正最終是達成這樣一個目標,并且有了這些東西之后,我們會有一些未來可期的這樣一種感覺。

        總結(jié)

        性能優(yōu)化,慢慢的就會發(fā)現(xiàn)它從前端的這樣一個職能慢慢的上升到多職能協(xié)同的這樣一種方式。慢慢你如果去優(yōu)化,你肯定就慢慢不能站在前端的這樣一個視角,慢慢的就會依賴于就類似前面說的 NSR 還有服務(wù)端這種 SSR 以及我們現(xiàn)在還有那種 ESR 就是 CDN 邊緣計算這樣去的一些就是東西,就慢慢你會發(fā)現(xiàn)性能優(yōu)化慢慢是超脫了前端這樣一個單純的職能這樣一個方面,你要站在多智能協(xié)同方式進行性能優(yōu)化的嘗試。

        規(guī)劃

        規(guī)劃就不那么細說提幾點。

        • SSR 同步的方案。我們之前剛才說異步在接口中返回 HTML 的方式,異步的方案。同步的方案就是主文檔的那種方式,異步的方案在端內(nèi)效果是肯定很好的,因為它直接離線包之后,通過數(shù)據(jù)的 prefetch 并行請求之后直接拿到 HTML,直接渲染到屏幕上去,這樣肯定是效果很好的。但是在端外,我們會有很多,比如類似支付寶、手淘這種場景它就用不了端內(nèi)的一些離線包和 prefetch 這種方式,所以我們還是需要進行一些直接主文檔返回的方式。
        • 頁面的 Abtest。
        • 客戶端那邊,要考量接入一下 NativeTab 這樣切換多 Tab 的方式。
        • 喚端情況下的一些性能優(yōu)化,這么多新的優(yōu)化點,肯定需要統(tǒng)一的狀態(tài)管理。

        這樣等等一系列的內(nèi)功提升,以及我們飛豬這邊目標是前端的兩秒達標率要達到 90%。所以單純的單業(yè)務(wù),我們端內(nèi)的單業(yè)務(wù)當(dāng)然就需要去拓展到多業(yè)務(wù)。我們就想法是有一個優(yōu)化手段及現(xiàn)在在集團內(nèi)我們是有跨端性能小組是有白皮書這樣一個方式,去記錄一些優(yōu)化手段,慢慢去push各個業(yè)務(wù),進行落地,并且去收集各個業(yè)務(wù)的一些好的優(yōu)化的手段,來進行沉淀反哺,慢慢去把整體的性能給提高起來。

        推薦一本書

        最后慣例推薦一本書,這邊推薦的就是《金字塔原理》,它是講一個類似寫 PPT 或者是思考表達和解決方式的這樣一種邏輯。寫 PPT、寫文章之類的這樣一種邏輯,是一套就是邏輯清晰、重點突出、層次分明,簡單易懂的思考表達方式和規(guī)范動作。這本書我覺得是挺好的??戳酥髮τ谧?PPT 或者是寫文章,都是由不少的幫助的。大家有興趣的可以去看一下。

        團隊宣傳

        最后慣例中的慣例,肯定是需要招人的。我們團隊關(guān)于是飛豬的用戶前端和數(shù)字化經(jīng)營團隊,我們的業(yè)務(wù)是關(guān)于旅游的一切我們都可以去嘗試。我們團隊的基礎(chǔ)事項。之前有我們團隊的南路,也來分享過 Web Flutter 這樣一個方案,我們團隊的有 Flutter,那么以及在我們現(xiàn)在 SSR 也是我們團隊基于 Serverless 這樣一個大潮去做的。還有一些中后臺的微前端,以及一體化的開發(fā)以及端線互動,以及智能搭建這樣一個東西,我們團隊技術(shù)思想都是包括的。所以基本上各個方面大家都有包括,所以大家有興趣就等你了,就可以通過郵箱,P6、P7 多多益善。

        大家也可以關(guān)注一下我們飛豬技術(shù)的公眾號,F(xiàn)liggy F2E 以及掘金,有些之前看到我這篇文章有在掘金上發(fā),也是被我們飛豬前端這邊專欄去收藏。如果對跨端這邊性能這邊有想法的,也可以加我微信了解一下。



        別忘了 8-14 的第三十屆|前端 BFF 專場,了解BFF 網(wǎng)關(guān)/GraphQL/聚合/剪裁/編排/接口玩法等等的可能性,8-14 全天直播,9 位講師(螞蟻/哈啰單車/阿里/網(wǎng)易嚴選/阿里云等等),點我上車?? (報名地址):

        分享內(nèi)容舉例: 4000多臺機器,30~100 萬 QPS 的 BFF 服務(wù),是如何做安全生產(chǎn)和工程保障的(CI治理、自動化監(jiān)控、組件復(fù)用、鏈路快排、變更風(fēng)險管控...)

        所有往期都有全程錄播和 PPT,可以購買年票一次性解鎖全部

        ??更多活動


        別忘了給文章點贊


        瀏覽 55
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            china高潮china激情 | 国产成人福利 | 国产精品一线二线 | 天天曰 | 美女日麻批 | 日本www在线 | 夜夜高潮夜夜爽 | 91在线无码精品秘 蜜桃 | 久久久999精品视频 | 91久久久久无码精品国产绯闻 |