全民K歌跨端體系建設(shè)
點擊上方 前端Q,關(guān)注公眾號
回復加群,加入前端Q技術(shù)交流群
作者: Edwiin,原文鏈接:https://xie.infoq.cn/article/e284b3a19e7937dc209a3d345
1. 背景
1.1 移動端技術(shù)演進
跨端技術(shù)的本質(zhì)是實現(xiàn)代碼復用,減少開發(fā)者在多平臺上的適配工作量,移動互聯(lián)網(wǎng)發(fā)展至今,跨端技術(shù)經(jīng)歷了許多階段,大體上可以分成如下四類:
-
最早是通過 H5 來實現(xiàn)跨瀏覽器的頁面渲染; -
移動互聯(lián)網(wǎng)發(fā)展,催生了越來越多調(diào)用到原生能力的場景,于是步入了 Hybrid 技術(shù)階段; -
緊接著為了解決渲染性能問題,又催生了像 RN/Weex 這類的 Native 容器方案; -
再往下一步走,就是近年來聊得比較火熱的 Flutter,以及相關(guān)的一些自繪制能力的渲染技術(shù);
從整個變遷過程中我們會發(fā)現(xiàn),跨端技術(shù)的演進實際上是以 H5 代表的效率、動態(tài)性逐步遷往 Native 代表的性能體驗的過程,并在整個過程中不斷尋找兩者間的平衡點。
1.2 主流方案對比
接著我們再來看看目前主流的 Native 容器與自繪引擎方案的對比。
Native 容器方案
市面上 Native 容器方案最具代表的框架當屬 Weex 和 RN 兩類,對于這類框架而言,原理都大同小異,
他們其實由三部分組成,分別是 JS,Native 以及中間的 Bridge 層,JS 層通常是我們熟知的 Vue / React 框架,他其實會把需要生成的節(jié)點信息通過 Bridge 層序列化后轉(zhuǎn)發(fā)到 Native 層進行解析,并最終渲染為 Native 的組件,這是為什么 Native 容器方案性能比 H5 要好的一個重要的原因。
自繪制引擎
而對于自繪引擎方案,目前最具話題與代表性的是 Google 的 Flutter 框架,它重寫了一套跨平臺的 UI 框架,包括 UI 組件,
渲染引擎以及開發(fā)語言,渲染引擎基于 Skia 圖形庫,而依賴系統(tǒng)部分就僅有圖形繪制相關(guān)的接口,可以最大程度上保證跨平臺的一致性,同時也意味著不需要再像 RN 那樣經(jīng)過一層 Bridge 進行 JS 和 Native 的通信數(shù)據(jù)轉(zhuǎn)發(fā),渲染效率更高一籌,另外其上次基于 Dart 語言開發(fā),在執(zhí)行效率上也比 JS 要高效得多。
小結(jié)
兩種類型的框架就目前而言沒有誰優(yōu)誰劣,對于 Native 容器方案來說,他更多的是代表了研發(fā)效率與動態(tài)性;對于 Flutter 這類框架而言,它雖然實現(xiàn)了高性能,但是卻缺少一套較為完備的動態(tài)化方案。
PS: 這里需要提一嘴,RN 目前正在把 JsBridge 的架構(gòu)重構(gòu)為 JSI,通過 JSI 架構(gòu)可以省去 JsBridge 的異步序列化操作,節(jié)省了成本,提高了效率,目前還在研發(fā)當中。
1.3 技術(shù)選型
對于該使用哪種跨端技術(shù)作為產(chǎn)品的接入方案,在選型上我們應(yīng)該考量到以下幾點:
-
從產(chǎn)品角度,需要考慮迭代情況以及使用場景,比方說像直播這種類型就更適合用 Native 而不是任何一種跨端技術(shù)實現(xiàn); -
從接入成本,需要看看接入這項技術(shù)所帶來的成本,比如團隊的技術(shù)儲備,是否有相關(guān)人力,比如客戶端來支持,遇到問題依靠現(xiàn)有人力和生態(tài)是否能 hold 住; -
從研發(fā)效率,怎么實現(xiàn)最大化的代碼復用,以及建設(shè)相關(guān)的開發(fā)調(diào)試工具鏈,提高開發(fā)效率,是應(yīng)該考慮的問題之一; -
從性能體驗,跨端技術(shù)通常是通過犧牲部分體驗換來效率提升,所以體驗比起 Native 還是要差一些,這也是情理之中,但如何通過建設(shè)配套工具和針對性專項優(yōu)化也需要重點考慮進來。
1.4 K 歌現(xiàn)狀
對 K 歌來說,通過一段時間的調(diào)研,實踐和風險考慮,最終主要采用了騰訊內(nèi)部自研的類 RN 框架 - Hippy,目前在站內(nèi)已開發(fā)超過 200+的業(yè)務(wù),覆蓋了像點歌臺,任務(wù)頁這類一級入口,同時包含 Poplayer 和游戲化的場景,日均 PV 直達 2.9 億,覆蓋了 41%+ 的主業(yè)務(wù)場景。作為 Hippy 最早的接入團隊之一,在廣泛應(yīng)用的同時,我們還深挖了框架技術(shù)痛點,并深度參與到開源共建中。
同時我們也有投入使用 Flutter 技術(shù)棧,目前主要是在應(yīng)用在創(chuàng)新項目當中。
2. K 歌跨端體系建設(shè)
2.1 體系建設(shè)
跨端技術(shù)的實踐往往需要一系列的配套建設(shè),以及針對性的性能優(yōu)化,下面是 K 歌在跨端上的體系建設(shè),主要分為四個部分:
-
開發(fā)支持,這里主要有開發(fā)調(diào)試使用到的工具鏈,組件文檔,以及與客戶端約定好的標準規(guī)范等; -
發(fā)布部署,包括 UI 自動化測試,Bundle 的包管理以及加載策略; -
質(zhì)量監(jiān)控,主要是一些質(zhì)量指標維度的制定以及配套的監(jiān)控系統(tǒng); -
性能優(yōu)化,包括在具體實踐過程中遇到的性能問題,以及解決方案,包括 Bundle 拆分,包內(nèi)置,秒開率及穩(wěn)定性的優(yōu)化等;
2.2 開發(fā)調(diào)試
為了提升開發(fā)聯(lián)調(diào)效率,除了框架本身提供的開發(fā)調(diào)試手段外,我們還沉淀了自己的一些工具和文檔,在新增一個接口協(xié)議后并提交后,觸發(fā)鉤子構(gòu)建,自動生成接口的文檔及調(diào)試工具。
同時為了方便開發(fā)過程中日志信息的查看,我們也開發(fā)了一個類 RN 版的 vConsole 工具,可對輸出及網(wǎng)絡(luò)流水進行攔截。
2.3 接口規(guī)范化
在與客戶端同學接口聯(lián)調(diào)時,經(jīng)常出現(xiàn)三端沒有對齊的情況,比如輸入輸出不一致的問題。由此提出了接口標準化的方案,通過在一個接口模板中約定好接口的規(guī)范,包括接口名,具體的輸入和輸出,再自動生成三端的接口模板,并在各端完成邏輯補齊、代碼提交后自動打包推送到各自倉庫,大大提高了聯(lián)調(diào)的效率,目前該方案已應(yīng)用到 k 歌國內(nèi)版,極速版以及 Flutter 的項目中。
3. K 歌跨端實踐優(yōu)化
3.1 能力擴展
首先是能力擴展部分,原框架提供的能力往往不能滿足和覆蓋我們復雜的業(yè)務(wù)場景,為此我們根據(jù)業(yè)務(wù)需要和優(yōu)先級梳理了一套符合 W3C 規(guī)范的 WebApi,依靠框架提供的插件能力擴展了所需要的功能,如觸摸事件,Performance 等原生接口能力,又如 Canvas, Audio 等原生組件和還有漸變色,魔法色等樣式能力支持。
其次 App 內(nèi)將常駐一個 Master 的無界面實例,這實際上是一個后臺的業(yè)務(wù),會在 App 啟動后自動加載,主要是服務(wù)于兩類任務(wù),一種是在 App 啟動時做一些初始化的操作,同時會啟動一個輪詢?nèi)蝿?wù),定時去拉取業(yè)務(wù)包的配置信息,實現(xiàn)業(yè)務(wù)包的下載管理,這個在文章后面也會提及;另外是實例間的通訊,在歌房和直播間的場景下,可能同時掛載多個 Hippy 業(yè)務(wù),而業(yè)務(wù)之間往往有通信的需求,針對這種場景,我們通過在 Native 實現(xiàn)一個中轉(zhuǎn)站對業(yè)務(wù)間的數(shù)據(jù)進行實時轉(zhuǎn)發(fā),以此完成業(yè)務(wù)實例間通訊的需求。
另外團隊與內(nèi)部設(shè)計團隊約定了組件的設(shè)計規(guī)范,并拉通客戶端同學,最終沉淀出三端通用的 UI 組件庫,包含多種通用組件與業(yè)務(wù)組件,目前已在業(yè)務(wù)中廣泛接入與使用,通過規(guī)范化,極大提升了組件復用性,同時也降低業(yè)務(wù)的開發(fā)成本。
3.2 性能優(yōu)化
下面將從以下幾個維度對頁面性能進行分析與優(yōu)化。
3.2.1 加載速度優(yōu)化
首先我們來看看加載速度方面的優(yōu)化,在這之前可以先了解一個 Hippy 業(yè)務(wù)的加載鏈路:一個業(yè)務(wù)在用戶點擊入口時,先會經(jīng)過 JS 引擎的初始化,接著是 JsBundle 文件的加載,在文件加載后客戶端會發(fā)送一個 loadInstance 的事件通知前端完成業(yè)務(wù)注冊,與此同時會創(chuàng)建一個 view 節(jié)點就緒,隨后前端會通過一系列的異步請求完成整個頁面的渲染。
在這個鏈路里面我們把引擎初始化到第一個 view 節(jié)點創(chuàng)建結(jié)束的這段時間成為首幀耗時,而此后直到頁面渲染完成的時間段稱之為異步加載耗時。由此可見,加載耗時也可以拆分成三部分,分別是引擎初始化耗時,JSBundle 耗時和請求的耗時,針對這三個細化的指標,也有相應(yīng)的優(yōu)化方案,分別是引擎的復用,包拆分、裁剪和預請求等優(yōu)化。
引擎復用
先看看引擎復用部分,在未做優(yōu)化之前,一個業(yè)務(wù) bundle 的加載需要開啟一個 JS 的引擎,而一個 JS 引擎初始化時間大概是在 500ms 左右;而在實際應(yīng)用中,可能存在多業(yè)務(wù)并行的場景,隨著業(yè)務(wù)加載數(shù)量的增加,我們需要開啟越來越多的 JS 引擎,由于每次初始化引擎都需要耗費耗時,這樣會直接導致頁面耗時增加,此外也占用了不少的客戶端的 CPU 和內(nèi)存等資源。
對于這個問題,我們首先想到的是用引擎池的方案,客戶端會預先創(chuàng)建兩個引擎作為備用,業(yè)務(wù)開始加載時,會優(yōu)先使用緩存池中的已經(jīng)創(chuàng)建好的引擎,當 2 個引擎不滿足場景時才開始創(chuàng)建下一個引擎。這種方案可以一定程度上解決引擎初始化耗時問題,但還不夠極致。我們在想每個業(yè)務(wù)新起一個引擎的目的究竟是什么?其實只是為了做業(yè)務(wù)的隔離,因為我們使用了 V8 作為 JS 的引擎,在 V8 中其實是可以通過單引擎多 context 方式進行業(yè)務(wù)隔離,所以我們在最新的業(yè)務(wù)實踐中也采用了這樣的方式來實現(xiàn)引擎的復用,從而減少初始化的耗時。
Bundle 包優(yōu)化
接著看看 bundle 包優(yōu)化,這里其實可以從兩方面著手,分別是體積優(yōu)化與下載耗時優(yōu)化,具體使用到的措施有如下幾點:
-
JS 拆包,采用了業(yè)界比較通用的做法,將前端的 JS 包拆分成 Base bundle 和業(yè)務(wù) bundle 兩部分,并把 base bunble 內(nèi)置于客戶端中,以此減少包體積與下載時長; -
業(yè)務(wù)優(yōu)化,不少業(yè)務(wù)中使用了很多 Base64 的圖片,會對業(yè)務(wù)包的體積造成一定影響,這里可以只保留必要的小圖 Base64 圖片,其他均采用外鏈方式,同時可以通過業(yè)務(wù)代碼重構(gòu),Tree-Shaking 等方式減少一些冗余代碼; -
Chunk 包加載,原框架不支持 Chunk 包加載,通過在 Native 層實現(xiàn) Chunk 包的緩存與加載,并將非首屏/核心資源抽離成 Chunk 包異步加載,從而實現(xiàn)首屏 Bundle 體積的減少; -
增量更新,在構(gòu)建階段通過與上次編譯結(jié)果的對比,實現(xiàn)了差分包的拆解,使得在業(yè)務(wù)包下載任務(wù)中只需要下載差分包,并在后臺合成,以此減少 Bundle 包下載耗時。
預請求優(yōu)化
再往下是預請求部分,上面我們提到一個業(yè)務(wù)中異步請求的耗時也是影響首屏渲染速度的一個重要因素,對此我們采用了預請求的優(yōu)化手段。
回顧及細化之前的加載鏈路,在前端業(yè)務(wù)響應(yīng)之前其實會經(jīng)過引擎初始化和業(yè)務(wù) bundle 的下載及加載的過程,在完成這兩個過程之后才能發(fā)起接口請求進行頁面的渲染,如果我們把請求提前至這幾個過程之前,或者說跟他們的加載時機并行跑,則會節(jié)省掉很多的耗時。事實上我們的預請求優(yōu)化就是這么做的,在加載業(yè)務(wù)之前,引擎通過業(yè)務(wù) url 上開關(guān)參數(shù)判斷出需要發(fā)起預請求,于是會讀取配置并發(fā)起一個請求,當前端業(yè)務(wù)被喚起后,通過客戶端提供的接口我們可以獲取緩存好的請求結(jié)果,從而減少請求的耗時。
關(guān)于預請求的配置我們通過一個 json 配置保存起來,并與業(yè)務(wù) bundle 一起打包到 Zip 包里,里面主要約定了具體請求的命令字,請求參數(shù),以及請求 Id 等信息,同時為了在請求參數(shù)中傳送一些動態(tài)的信息,比如登錄態(tài)中的 uid,url 上的參數(shù)信息等,我們也與客戶端同學約定了一些全局的變量定義以及獲取動態(tài)值的語法等。
3.2.2 卡頓優(yōu)化
Native 分析工具
對于 K 歌所使用到的 Hippy 框架,或者是 RN/Weex 這類的跨端框架,其實最終還是會渲染成 Native 的原生組件,所以我們也可以借助客戶端的相關(guān)工具排查卡頓性能,比如以 Android 為例,可以通過【設(shè)置】【開發(fā)者調(diào)試選項】中的【GPU 條形模式分析】得到頁面的 FPS 繪制效率,iOS 則可以使用 xcode 的 instruments 工具排查卡頓性能。
左上圖為安卓的 GPU 分析案例,可以看到截圖最下方是一條綠線,代表的是 16ms 的閾值,超過了這個界限則表示當前幀繪制的時間出現(xiàn)了延遲,卡頓的現(xiàn)象,而圖中具體的顏色值所代表的含義在右邊這張圖中我們也可以找到,如果以該案例來看,所處第二個顏色,也就是 Layout Measure 的處理耗時太多,表示當前觸發(fā) onLayout 和 onMeasure 的回調(diào)次數(shù)太多,由此可以推斷出頁面層級可能比較復雜。
有了這個結(jié)論后,再往下就可以通過過度繪制檢查工具來排查頁面的層級,如圖中所示,綠色部分表示層級簡單,紅色則表示嵌套層級比較深,那么在后續(xù)就可以做針對性的優(yōu)化了。
前端通信分析
對于 Hippy 這類跨端框架而言,前端最終傳遞給客戶端的是抽象的節(jié)點以及響應(yīng)的操作行為,當客戶端通過 UIManager 模塊接收這些信息,對其進行整合,并轉(zhuǎn)化為一系列的操作指令,最終渲染到 Native 中。
在前端部分,可以通過攔截 js2native 的通信數(shù)據(jù)來排查卡頓問題,比方說在列表場景下,會存在同時傳遞多個節(jié)點信息,這樣會導致頻繁的 js2native 的通信,對幀率也會造成影響。
問題及解決方案
通過結(jié)合 Native 與 JS 的排查手段,可以推斷卡頓的問題可能有如下幾類問題產(chǎn)生,分別是:
-
層級復雜,處理任務(wù)過多; -
頻繁的 js2native 的通信; -
js2native 通信數(shù)據(jù)更大導致通信延遲;
針對這類問題常用的解決方案分別是:
-
減少頁面層級,前端同學由于開發(fā)背景的原因,往往會忽略層級嵌套的問題,導致性能問題,這個需要在開發(fā)側(cè)注意,盡量減少組件層級的嵌套; -
對于頻繁 js2native 的通信,我們嘗試在前端 SDK 層面做處理,在一個微任務(wù)里對節(jié)點的操作進行合并,再統(tǒng)一傳到 Native,這樣可減少 js2native 的操作數(shù)量; -
對于節(jié)點數(shù)據(jù)問題,通過模版化的思想將節(jié)點里面一些公共的屬性和數(shù)據(jù)進行模版化的操作,并沉淀了高性能的列表組件。 -
另外在必要的時候還需要推進客戶端的同學進行具體問題分析,比如之前我們就遇到過列表里重復對 Base64 圖片進行解碼的問題,導致 FPS 數(shù)據(jù)下降,后面的解決方案是推進客戶端進行 Base64 圖片緩存,以此提高繪制效率。
3.2.3 成功率優(yōu)化
接著是成功率優(yōu)化,這里主要指的是業(yè)務(wù)的加載成功率,由于業(yè)務(wù)最終還是通過網(wǎng)絡(luò)分發(fā),在業(yè)務(wù)加載時,為了減少業(yè)務(wù)包的網(wǎng)絡(luò)下載耗時或者由于網(wǎng)絡(luò)問題而導致下載失敗的問題,在這里團隊結(jié)合了內(nèi)置包和緩存包兩種方式來保證業(yè)務(wù)的加載成功率。
內(nèi)置包
內(nèi)置包作為極端網(wǎng)絡(luò)情況下的保底方案,適用于 App 內(nèi)的一級入口頁面,如點歌臺,歌房 Tab 等業(yè)務(wù),保證在失去網(wǎng)絡(luò)時仍能打開這類業(yè)務(wù),它的具體更新流程如下:通過在一個特定的倉庫下維護了一份業(yè)務(wù)的版本配置文件,這里提供了手工錄入和定時拉取外網(wǎng)最新穩(wěn)定版本兩種方式來修改這份配置文件,而當該配置文件完成修改,并通過 Review 后,將觸發(fā) WebHook 鉤子通知構(gòu)建系統(tǒng),此時構(gòu)建會去拉取配置文件中的業(yè)務(wù)版本信息,并下載下來放到客戶端指定的本地目錄中,再向客戶端倉庫發(fā)起新的 MR,通過客戶端人員的 CR 后內(nèi)置包即可更新,并在下次發(fā)布 AppStore 或應(yīng)用市場時將最新的內(nèi)置包帶到外網(wǎng)中。
緩存包
接著再來看看緩存包部分,由于內(nèi)置包集成會增加客戶端的安裝包體積,并不適合所有的 Hippy 業(yè)務(wù),這時候緩存包就可以發(fā)揮作用了。同時由于業(yè)務(wù)頻繁迭代發(fā)布的特性,如何保證外網(wǎng)可以較實時地拉取,也需要一套更新機制,前面我們有提及 APP 啟動后會加載一個無界面的實例,該實例會在加載完畢后啟動一個輪詢?nèi)蝿?wù),時間間隔為 2min,在這個過程中將會實時地拉取外網(wǎng)的業(yè)務(wù)版本配置,并與本地的配置進行比對,如果發(fā)現(xiàn)版本有更新,將會下載最新的業(yè)務(wù)包,并更新到本地緩存中,提高緩存命中率。
小結(jié)
針對成功率優(yōu)化部分,我們通過結(jié)合內(nèi)置包和緩存包機制來完成,這里的優(yōu)先級是優(yōu)先使用緩存包,因為得先保證命中最新的版本,而當緩存失效或者不存在緩存包時才會命中內(nèi)置包,只有當內(nèi)置包不存在時,才會實時去外網(wǎng)拉取并下載最新包,以此提升成功率,再結(jié)合外網(wǎng)緩存命中率和 Crash 告警,實時監(jiān)聽外網(wǎng)成功率變化。
3.2.4 優(yōu)化效果
另外我們還做了其他的一些優(yōu)化,比如在用戶體驗部分,我們也采用了骨架屏的方式減少用戶肉眼等待時間;內(nèi)存部分,通過前端業(yè)務(wù)側(cè)和客戶端的圖片緩存,按容器尺寸渲染等方式減少了內(nèi)存消耗;針對 CPU/GPU 優(yōu)化部分,我們與官方的團隊保持密切的聯(lián)系,并通過推動優(yōu)化 SDK 升級等方式解決。
通過結(jié)合加載速度,卡頓和成功率三個緯度的優(yōu)化,整體下來目前取得了不錯的效果,其中成功率已達 3 個 9,主業(yè)務(wù) FPS 達 54+,這兩個指標均與 Native 對齊,另外整體秒開率方面對比優(yōu)化前有了 5% 以上的提升,達到 85%+。
3.3 質(zhì)量監(jiān)控
3.3.1 自動化測試
下一部分是質(zhì)量監(jiān)控部分,這里我們與測試團隊一起打通了自動化的測試流程,利用測試同學提供的測試機與埋點服務(wù),保障業(yè)務(wù)發(fā)布前的穩(wěn)定性,具體的流程如下:
-
首先是前端同學觸發(fā)一個業(yè)務(wù)的構(gòu)建,當業(yè)務(wù)構(gòu)建成功后會同步至我們的虛擬或體驗環(huán)境; -
當業(yè)務(wù)包在環(huán)境同步結(jié)束之后,構(gòu)建系統(tǒng)會向測試同學所提供的服務(wù)觸發(fā)一個鉤子,并附帶環(huán)境,業(yè)務(wù)名與具體的版本號信息; -
測試服務(wù)收到這些信息之后,通過腳本啟動真機群,并在上面運行指定環(huán)境與版本的業(yè)務(wù),通過埋點信息記錄業(yè)務(wù)的性能數(shù)據(jù),包括首幀,秒開率等等指標; -
自動化測試流程結(jié)束之后會回調(diào)給我們的構(gòu)建機,構(gòu)建機發(fā)起微信/郵件的結(jié)果推送,并記錄保存該任務(wù)的測試結(jié)果; -
到業(yè)務(wù)的發(fā)布階段,通過上面保存的測試結(jié)果,可以對業(yè)務(wù)的發(fā)布進行二次確認或阻斷。
3.3.2 監(jiān)控系統(tǒng)
監(jiān)控指標梳理
在做監(jiān)控之前,我們首先對監(jiān)控上報的指標進行了梳理和統(tǒng)一,大致可分為 5 大類,首先是性能緯度,這里包含了業(yè)務(wù)運行時所占用的內(nèi)存,CPU,GPU,F(xiàn)PS,引擎耗時和首幀耗時等等;然后是業(yè)務(wù) bundle 緯度,包括了業(yè)務(wù)的下載時間,加載時間和包體積大小等;緊接著是接口部分,包括了客戶端和后臺接口的調(diào)用,具體指標有調(diào)用/請求耗時,返回碼,通信數(shù)據(jù)大小等;再往下是錯誤緯度,包括 JS 異常,業(yè)務(wù)運行時的 Native Crash 等;最后還有一些大圖檢測和進程通信等等上報。
監(jiān)控系統(tǒng)
最后是監(jiān)控系統(tǒng)部分,其實在之前很長一段時間內(nèi)我們內(nèi)部有使用過多個不同的監(jiān)控系統(tǒng),這樣做的歷史背景是每個監(jiān)控系統(tǒng)的側(cè)重點有所不同,這就導致我們在比較長一段時間內(nèi)需要到各個平臺上篩選不同的上報數(shù)據(jù),這對問題的定位和排查造成了很大困擾和阻礙,在這之后我們下定決心把所有的上報口徑和渠道統(tǒng)一起來,最終收歸落到同一個平臺上。
一個靠譜好用的監(jiān)控系統(tǒng)應(yīng)該支持實時性,多維度/指標看板和自定義告警等能力,在經(jīng)過一段時間的試用和產(chǎn)品 PK,我們最終采用騰訊內(nèi)部自研的監(jiān)控系統(tǒng),同時也參與到內(nèi)部的開源共建中。
4. 最后
本篇文章首先是對跨端技術(shù)的演進過程進行了介紹,從整個變遷過程中我們會發(fā)現(xiàn),跨端技術(shù)的演進實際上是以 H5 代表的效率、動態(tài)性逐步遷往 Native 代表的性能體驗的過程,并在整個過程中不斷尋找兩者間的平衡點。在跨端建設(shè)的實踐過程中,往往需要建設(shè)一系列配套建設(shè)和針對性性能優(yōu)化,這里也介紹了我們在這方面的一些實踐。
最后引用阿里圣司之前在分享中的話,“性能體驗、研發(fā)效率與穩(wěn)定性是前端三駕馬車,圍繞這些大方向很多技術(shù)規(guī)劃都是類似的,但落到執(zhí)行結(jié)果上千差萬別;頂層設(shè)計之下,對每個細節(jié)的執(zhí)行與積累存在差異,而這些差異聚合在一起決定了成敗”。
往期推薦
最后
歡迎加我微信,拉你進技術(shù)群,長期交流學習...
歡迎關(guān)注「前端Q」,認真學前端,做個專業(yè)的技術(shù)人...
