整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          前端加速利器「離線包」

          前端加速利器「離線包」


          H5頁面給人的感覺通常是開發成本低、迭代速度快但使用體驗不佳。其中最容易被用戶感知的體驗問題就是首屏速度,由于H5頁面的所有資源都需要實時從網絡上下載,提升這些資源的加載速度就可以明顯提升首屏速度。我們通常將提前下發資源到App,并在打開H5頁面時使用預載資源加速訪問的技術稱為“離線包”。

          B站的離線包技術方案與大部分互聯網公司實現的方案在底層邏輯上是一致的,都實現了基礎的資源下發和攔截匹配機制。但在此基礎上我們也有一些創新,例如頁面快照技術、AB實驗能力,同時也做了很多優化,包括用掃碼調試降低調試成本、版本快速收斂、預約定時錯峰發布等。目前我們的離線包技術已經接入183個項目,覆蓋12個業務線,在公司內被廣泛使用。


          頁面加載速度的瓶頸分析



          當我們用工具分析一個典型H5活動頁(2024紀錄片開放周)時,可以發現一個頁面的速度瓶頸主要在這些方面:

          HTML請求

          通常按照HTML是否動態生成,將其分為SSR(服務器端渲染)和CSR(客戶端渲染)頁面。

          SSR受服務器負載、頁面復雜度和網絡拓撲影響,首字節時間相對較晚,但一旦收到HTML響應,瀏覽器引擎就會立刻開始解析和繪制,所以首屏時間相比CSR會更有優勢。

          CSR的優勢在于可以很容易地使用部署在各地的CDN服務節點來加速,且可以配置一定時間的緩存,所以首字節時間更短,但所有頁面結構都需要JS運行后才可以產出,首屏時間會晚很多。

          通常CSR頁面的響應時間大概在10ms-50ms,SSR頁面通常50ms - 數百毫秒。SSR頁面在等待服務器渲染上會耗費更多時間,根據之前一些案例的經驗結果,SSR對中低端機型的首屏提升比離線包大,離線包在對高端機型的首屏提升比SSR大,其原因在于離線包下渲染頁面屬于單純的CPU密集型任務,高端機型處理器較好,相對服務器端需要排隊處理的SSR會有更快的響應。



          主JS下載&編譯

          目前前端項目通常都會使用JS框架,疊加引入3-15個左右的第三方庫,產出的JS Bundle一般會有數百KB-2M左右的大小,下載需要花費數百毫秒的時間。較大的JS文件也會讓JS引擎的分析過程更加漫長,一般看CPU速度,需要十幾毫秒到幾十毫秒的時間。

          在SSR項目中,主JS過大通常導致用戶首次交互時間變晚,一些場景下,用戶會發現頁面一開始無法響應交互,在JS運行完成后才可以正常使用。

          在CSR項目中,主JS過大會導致頁面白屏時間較長,需要等待一段時間后才能出現頁面內容。

          請求頁面主接口

          單個接口通常消耗30ms-100ms的時間。但JS往往會等待接口返回后,才會開始生成實際的框架內虛擬DOM樹,所以這個同步等待的時間越長,白屏時間也越長。SSR項目通常會在渲染服務器上調用這個接口,利用內網網絡高帶寬低延遲的特性,降低這塊的耗時。CSR項目可以考慮提前加載時機(接口預取或請求前置)或緩存上一次的結果來盡量減少請求耗時。

          應用虛擬DOM樹生成

          這一步通常都是Vue或者React這類框架在運行應用代碼,生成虛擬DOM,進而將虛擬DOM掛載到實際的DOM樹中。這個過程伴隨大量的CPU密集計算,可能需要幾十毫秒到百毫秒的時間才能完成。這一步由于視圖結構受業務形態影響很大,通常難以優化,比較可行的方案是先加載首屏的、重要的組件,延后加載非首屏、不重要的組件。

          加載首屏資源

          當頁面實際的DOM構建完成后,瀏覽器才會知道需要加載哪些資源,并開始下載。這個過程大概需要數百毫秒。這一步通常會使用CDN加速、文件名帶哈希+強緩存、優化圖片和其他資源體積等方式,優化加載速度。

          綜上,一般一個頁面從開始加載到用戶看到相對穩定的頁面,通常需要1.2秒到2.5秒左右的時間。其中相當的一部分時間耗費在網絡IO(下載資源和請求接口)上,剩余的主要就是JS編譯運行的開銷,以及瀏覽內核處理Layout和Render的時間。其中比較容易優化的主要是網絡IO時間。而在JS代碼運行和界面布局效率方面,在不同的業務場景下有較大的差異,需要根據業務場景量身定制。


          離線包技術方案簡介


          離線包的技術基礎就在于Webview為調用層提供的請求劫持能力,匹配資源路徑后可直接返回本地文件內容。

          Android系統可以直接使用shouldInterceptRequest API來實現,可以攔截https或者私有協議的請求。而IOS是基于WKURLSchemeHandler hook系統方法來實現https的攔截,但由于系統Bug在post請求中存在body丟失和上傳圖片可能導致進程崩潰的問題。對于這個問題,我們一方面要求H5頁面使用JSAPI來發起POST請求,另一方面限制僅在命中離線包的情況下開啟https攔截。在此限制下,因此這套方案基本可用。

          解決了請求劫持問題,接下來就可以實現透明的資源加速能力了。我們需要先完成資源的準備:


          代碼資源的準備


          資源準備的過程比較簡單,與構建工具無關,只要收集頁面所需的資源文件,并且配置好URL到本地路徑的映射關系就可以了。

          通常會有兩種代碼來源:

          1. 代碼工程:由前端工程構建產出的文件。這類情況下,枚舉每個產出的文件,去掉一些過大或不常用的文件,加上一些需要額外加載的線上資源,就可以打包發布了
          2. 線上抓取:其他無法控制源代碼的線上業務頁面,例如低代碼平臺產出的頁面。這類情況下,可以使用模擬瀏覽器環境,抓取實際請求的資源列表,按照用戶定義的規則去掉部分文件后,就可以打包發布了

          最后打包的目錄,大概包含以下內容

          • config.json用來描述客戶端需要攔截的URL列表,攔截的一些基礎信息和資源映射表
          • html 入口文件,客戶端根據config.json的描述找到這個入口文件,并交給webview加載這個文件
          • 其他資源文件(css、js、圖片、字體、svg等),這些資源會在頁面運行時發起請求,由客戶端查表攔截,并返回給webview使用

          一個典型的代碼產出目錄如圖所示:



          config.json示例:



          離線包的下發機制


          離線包的下發依賴Fawkes(客戶端統一平臺)的ModManager,使用與客戶端統一的下發渠道,有利于統一調度,控制下載期間的CPU、帶寬占用和存儲空間占用。

          ModManager是用于下發客戶端資源的一個統一渠道,絕大部分需要動態下發的資源都會通過ModManager統一管理和分發,并具備了諸如增量包生成、資源錯峰下發、熱推送下發、版本和網絡環境限制等諸多能力。復用這套基礎能力省去了我們額外建立一套下發鏈路的成本,也能更容易地管控CDN流量以及客戶端存儲空間占用。

          離線包平臺有三種發布模式,分為常規發布、錯峰發布和預約發布,這些發布模式的實現方案有一定的差異:



          常規發布


          代碼包將直接發布到線上,所有符合限制條件(版本、時間、灰度等策略)的冷啟動App的用戶都將按照資源包優先級逐步下載到新版本。

          如果用戶本地沒有這個包的舊版本,那么會下載全量包;如果已經存在較近的舊版本,則會下載增量包。但即使有增量更新能力,在用戶使用的高峰時段,常規發布仍會帶來較大的帶寬壓力,所以高峰期發布需要額外審批。



          如圖所示,在常規發布后,資源包的下載會快速制造一個流量高峰,而后隨著覆蓋率的提升,緩慢下降,直到大部分用戶完成更新。因此,我們除了常規發布外,還需要更智能的發布策略來降低成本。


          錯峰發布


          錯峰發布模式下,會設置離線包延后1-3天生效,在此期間,會借用流量低谷下載離線資源包。從而有效利用CDN的閑時流量,節約成本。

          錯峰發布適合第一次發布的包,可以利用閑時流量緩解第一次全量下載對用戶的流量壓力。后續版本再發布時則可根據上線時間要求靈活使用發布模式。


          預約發布


          在離線包的實踐中有這樣一個問題:直播業務的大部分頁面都接入了離線包,但某些頁面常常需要在晚上高峰期上線發布,但在高峰期上線離線包又會帶來很高昂的帶寬費用。如何既保證可以及時發布,又可以兼顧離線包呢?我們設計了預約發布功能。

          預約發布允許設置后續24小時內的某個低峰時間點發布。設置后,當前線上使用的包版本可以設置即刻失效,用戶降級請求線上頁面訪問新版本內容。而新版本會在指定時間點發布,在此后更新完成的用戶,就可以正常使用加速能力。

          預約發布適合需要在高峰時段上線新功能,且對短時間內性能下降不敏感的業務。即可以取得足夠快的發布速度,又可以避免較高的帶寬費用。缺點是會影響這個時間段內用戶訪問頁面的速度,也可能對線上服務造成突發壓力。


          資源匹配機制



          如圖所示,當Webview加載一個URL時,會經歷以下環節:

          1. 確認當前是否可以使用離線包。這包括確認全局開關、url開關和協議匹配情況。
          2. 如果當前頁面URL命中了離線包,那么則確認本地包版本是否在接口下發的版本白名單中,如果存在,則進入到離線包加載流程,否則就正常走線上請求。
          3. 進入離線包加載流程后,會開啟容器的https攔截能力,此后所有實例內的資源請求都會被攔截來確認是否存在對應的離線資源。同時開始加載離線的Html資源。
          4. html加載后,Webview會發起對JS和圖片等資源的請求,此時請求攔截器識別到這些網址都在資源映射表中,就會使用本地文件系統的資源返回。對于不在列表的文件,則正常拉取線上資源后返回
          5. 此外還有一種特殊的資源類型,名叫公共資源。這類資源位于單獨的公共包中,當頁面命中離線包后,如果url符合公共資源的命名要求,就會嘗試去加載本地資源。
          6. 對于所有本地資源加載失敗的場景,都會回退到請求線上資源,至少保證功能可用。


          版本控制和快速回滾策略


          離線包由于是預先給客戶端下發資源,所以不可避免地會遇到更新時效的問題。在更新時效上,我們之前在使用ModManager時會遇到這些問題:

          1. 更新不及時。比如在修復線上bug或者響應業務的臨時改動時,希望用戶能盡快更新到新版本,但要等到大部分用戶更新到新版本需要很長的時間(一般發布完1小時能覆蓋90%,2小時覆蓋97%)
          2. 更新觸發頻率低。常規優先級的包,只會在冷啟動時才會拉取,所以很多用戶如果一直開著App,就會一直停留在老版本
          3. 版本殘留。由于更新時間是在App冷啟動時,而冷啟動后可能有很多資源包需要更新,所以往往會在沒有更新完成前就使用到了對應的H5頁面,訪問到舊版本內容。
          4. 下線后資源包被刪除。當用戶有緊急情況需要臨時下線資源包時,如果一個包的所有版本都被下線,則會刪除這mo d個包的資源。再次啟用這個包時,就需要一次全量下載。

          考慮到前端離線包的主要目的是加速,不同于客戶端包下載到資源才可以使用對應功能的限制,我們可以靈活利用線上兜底策略,來解決這幾個問題。

          于是在ModManager機制的基礎上,我們又額外引入了一個接口(x/offline/version接口),用來告知客戶端當前可以使用的版本白名單。客戶端會在每次冷啟動和切后臺返回時刷新接口數據(有較短時間的限頻和緩存邏輯),從而可以實現以下能力:

          1. 發布新版本時設置舊版本過期時間。靈活控制舊版本的下線時間,如果在指定時間后,用戶仍然沒有更新到新版本,那么就會直接請求線上資源。一般設置2個小時過期,就能保證大部分用戶仍然可以享受到離線包的提速,也能保證不存在版本殘留問題和更新不及時的問題。
          2. 快速下線。在出現線上緊急Bug需要修復時,可以使用版本白名單,強制客戶端走線上請求,但仍然保留本地離線資源包,從而方便后續發布新版本修復問題。
          3. 預約發布。預約在指定時間發布離線資源包,在此期間會強制用戶走線上請求,從而兼顧上線速度和流量成本。

          版本接口的大概形式是這樣的:



          這個接口采取版本白名單機制,在接口參數中確定了App環境信息后,會查詢出這個環境這個App下可用的包版本列表。在發布新版本時,白名單里會同時出現2個版本,從而允許舊版本離線包仍然使用一段時間,在指定時間后,會只下發最新版本號,舊版用戶在更新完成前會請求線上資源。

          版本接口為了提供較高的時效性,每次切后臺返回或者冷啟動都會請求刷新,會有較高的QPS,我們在接口上做了充足的緩存策略,所有數據均是異步定時更新并完成計算,在請求到達時始終從內存緩存中返回數據,服務資源占用率比較可控



          上圖表示了一個設置了1小時舊版本過期的項目在占有率變化上的趨勢。版本控制功能主要解決舊版本過期問題,可以使得舊版本在過期后立刻失效,而新版本不受影響。


          調試流程優化


          離線包由于需要等待客戶端將包下載完成才可以體驗,因此在開發調試階段會帶來很大的痛苦。為此,我們仿照小程序的開發流程,設計了掃碼調試功能,在開發、預覽等場景上,均可以使用掃碼調試功能快速預覽頁面在離線包下的效果。



          掃碼后,在預覽調試頁面,會調用JSAPI要求客戶端下載指定的zip資源包,放置到特定的調試目錄。后續在App存續期間再次打開對應的H5頁面時,會優先使用調試目錄內的資源,而其他機制保持一致,因此在大部分場景下可以完美還原線上離線包的使用體驗。

          另外在打開的調試頁面上,還會注入離線包調試工具,幫助業務發現有哪些未命中離線的資源以及查看Performance Timing API數據,幫助優化離線包的文件組合,提升加速效果。


          HTML快照


          在很多需要優化首屏速度的場景,使用SSR都是一個可行的方式,在服務器端提前渲染好整個頁面的HTML結構,這樣瀏覽器拉取到HTML后就可以立刻開始渲染,用戶就能更快地看到內容。

          SSR能夠加速的核心條件是提前渲染完的HTML,如果我們可以緩存上一次的頁面渲染結果,是否也可以用于加速下一次用戶進入時的首屏速度呢?顯然是可以的,只不過需要先解決一些問題,例如

          1. DOM一致性問題。比如JS運行時會修改DOM實現動態樣式、rem布局等能力,這些修改的副作用需要考慮哪些要留下,哪些要舍棄的問題。
          2. 反復生成快照帶來的副作用累積問題。由于每次都會使用當前頁面的DOM作為快照,但直接使用快照頁面再次加載時,JS邏輯會再次執行一邊,導致出現多套副作用累積,導致不可預期的bug。
          3. 緩存問題。如何保證代碼上線后,用戶不會仍然因為快照訪問到舊版本。如何保證不同參數進入頁面時,頁面數據的隔離性。
          4. 數據時效性問題。一些時效敏感數據,如何針對性地從緩存里去除,避免舊數據對用戶的誤導
          5. 前后的銜接問題。不像SSR有成熟的方案和框架支持,可以很順暢地從快照的DOM結構中注入JS交互邏輯。快照頁面通常只能重新生成一套DOM,完整替換原來的DOM,所以銜接的時機就很重要

          基于上述問題,離線包HTML快照能力做了一些針對性的方案。不過我們可以先看一下這個功能的運行流程:



          如圖所示,當用戶請求一個URL時,會先判斷是否命中離線包,如果命中,則檢查是否存在HTML快照,如果存在快照,那么使用快照HTML,否則使用離線包內附帶的HTML。當頁面完成加載后,會在頁面上調用一個JSB,用來存儲當前頁面的快照。

          關于快照,還設置了以下限制:

          1. 每個快照使用1次后即刪除,必須在加載快照的頁面上,調用JSB重新存儲當前頁面的快照,才能讓下一次頁面加載時使用。刪除的條件為:當前打開的容器,存續時間大于3秒,這個是為了防止用戶誤操作導致快照被刪的問題。
          2. 當離線包更新版本后,將不能使用舊版本離線包下創建的快照,即你需要將離線包版本當作一個key。這是為了保證代碼更新后,頁面可以正常更新。
          3. 快照需要有緩存key策略,允許前端根據url query、cookie、登錄狀態等參數區分頁面,防止頁面數據錯亂。
          4. 快照需要設置最大存儲時間和存儲隊列長度。最大存儲時間可以由jsb設置,但最長不超過5天,存儲隊列長度,每個url下(去query的)最大存儲20個HTML快照。整體快照大小不超過10MB

          除此之外,對于設置的HTML內容,還需要注意以下問題:

          1. 使用原始空殼HTML作為基礎,注入當前頁面#app節點內的結構。如果使用rem布局則追加設置rem的fontSize,整合后的HTML才用于設置快照
          2. 應用代碼在識別到當前使用快照時,先完整生成dom結構,再替換當前#app的內容
          3. 每個應用自行處理好時效敏感數據節點內的數據

          這樣基本可以解決上述提到的問題。HTML快照的技術基礎是在基于一個假設,即頁面DOM結構會與數據一一對應,所以相同的數據輸入,無論多少次渲染都應該輸出相同的DOM結構。那么只要提前緩存DOM結構,就可以在下次訪問時先展示舊頁面,再無縫切換到新頁面。

          這個假設雖然大部分情況下雖然成立,但卻仍舊缺乏業務實踐,具體在實踐中會遇到哪些問題,需要在生產應用后才能有相對靠譜的最佳實踐。這方面的實踐會在今年展開,歡迎持續關注與合作。


          AB實驗


          由于離線包會攔截入口HTML文件請求,在頁面做了大改版需要頁面級AB實驗的場合,就無法在服務端來進行分流決策。為此,我們使用網址Rewrite能力使得同樣一個URL在不同用戶側對應兩份不同的離線包。

          其大概流程如下:


          1. 在每次熱啟動請求離線包控制接口時,接口計算該用戶對應的AB實驗分組
          2. 根據對應的分組,下發url重寫規則,將地址重寫到對應版本離線包的URL
          3. 客戶端在打開頁面時,會根據映射表,將URL重映射到新的URL上,并且按照參數要求添加分組結果參數
          4. 最后按照修改后的url打開頁面,頁面上報URL參數里的分組結果

          上述方案可以實現頁面的AB能力,但由于AB分流決策與頁面打開的時機不同,所以無法上報進組數據,只能上報用戶實際進入頁面的數據,所以會影響部分數據的回收。



          新舊版本的配置差異如上圖所示。使用兩個不同的URL,就可以分別對應兩個不同的離線包,從而在不影響離線包本體設計的基礎上實現AB能力。


          適用場景與局限


          離線包提供的幾個核心能力,可以有效提升頁面的首屏速度,但仍然因為技術實現和架構的原因,存在一些限制:

          存在失效場景,需保留線上訪問能力

          在某些場景下,離線能力會暫時失效,從而會請求線上頁面。接入離線包的業務需要自行確保線上URL可訪問且功能正常,只能把離線包作為加速手段,而非最終部署目標。

          失效的場景包括:App版本過低、尚未更新到可用版本的用戶(新下載App用戶或長期低活躍用戶)、緊急下線或預約發布期間由業務觸發的暫時禁用

          增加上線復雜度

          接入離線包后,需要在上線前完成離線包功能驗證,且需要在線上頁面上線完成后,再操作離線包發版。會增加一定的上線復雜度。

          雖然離線包的資源預載和接口預載能力已經比較成熟,通常不會引入額外的問題,但仍然需要注意自測。

          上線鏈路復雜的問題,通過在公司前端統一發布平臺集成離線包發布流程來解決。

          帶來額外帶寬成本

          每一個上線發布的離線包,都會下發到絕大部分用戶的手機中,而很多用戶可能根本不是這個業務的目標用戶。同時下發的過程也會帶來額外的帶寬成本,尤其是在高峰期上線時。

          目前我們確實還沒有精細化提升帶寬使用率的能力,未來可能會看情況,采用人群包或其他方式,優化下發資源的精準度。

          Webview本身的限制

          目前由于IOS系統在使用https攔截能力時的一些Bug,需要格外注意這兩個問題:

          1. 不要在離線包的頁面內直接發起post請求,包括post數據或者圖片。如果有需要的話,可以使用基于JSAPI請求的公司內NPM包
          2. IOS離線包下,使用history.push,左滑時會退出整個webview容器,而非返回上一頁。目前技術無解,只能使用ability.openScheme打開新的容器來替代

          綜上,哪些業務適合接入離線包呢?離線包通常適合以下類型的業務:

          1. 有一定的用戶體量,例如日PV大于5萬的業務(不是硬性要求)。這一點主要是出于資源利用率考慮。
          2. 短時間內有大量用戶訪問的活動頁,或者有常駐入口的業務流程頁面
          3. 營收相關或者速度敏感的業務,提升用戶體驗可能對營收有一定的幫助
          4. 相對穩定,改動不頻繁的業務


          離線化的終點在哪里?


          當我們將越來越多資源提前緩存在用戶手機里,免去網絡IO這一最大的速度瓶頸,就會發現其實它跟客戶端界面業務差距并不會很大。這個存在形態位于Native和H5之間,它犧牲了一些發版的便利性,但獲得了更快的加載速度。雖然我們無法修改承載H5的Webview本身,也必須要承受Webview帶來的性能問題,但我們也很好奇如果將一個頁面優化到極致,是否真的可以讓用戶無法通過加載速度區分哪些頁面是Native實現,哪些頁面是H5實現呢?

          后續我們將在一些頁面上實驗這樣的速度優化策略:

          1. 所有代碼自身的資源離線化,這個目前就能實現
          2. 代碼通過script標簽引入的三方庫離線化,通過離線包平臺自動化管理三方庫的公共包,自動更新自動發布。保證頁面本身的代碼資源不再需要通過網絡加載
          3. 接口數據緩存和stale-while-revalidate策略組合。頁面預先使用上一次緩存的接口數據,等接口預載數據Ready后,替換成最新數據。(類似客戶端頁面進入后,先看到舊數據和loading標志,隨后刷新為新數據)
          4. HTML快照策略。充分利用HTML快照,在JS還未執行時就能看到首屏頁面
          5. 其他常規優化手段。包括優化第三方庫引用、優化代碼執行流、觀察代碼性能瓶頸并解決等。

          當這個實驗做完后,會再寫一篇文章,總結這樣綜合實踐方案下的經驗,為其他業務的優化提供參考。我們的目標是樹立起H5性能的新標桿,讓更多的業務可以使用H5來承載,釋放業務迭代的潛力!


          性能表現


          全局性能表現:

          Android:



          IOS:



          整體看,離線包對Android系統的頁面加載提升服務比較明顯,對IOS系統的提升相對幅度小一些,但也有可感知的速度提升。

          從單獨業務角度觀察,從番劇片單頁來看,離線包的速度提升效果如下:



          由于PV數較小的性能數據不可置信,因此看可置信數據而言,在onload事件的平均時間上,非離線包狀態的加載時間約為2700ms左右,簡單接入離線包后,加載時間約為2300ms,提升400ms。

          在經過對資源的詳細分析,將所有線上加載的js文件都打入離線包后,加載時間下降到2016ms,可以再提升300ms。總體而言,離線包可以為簡單H5頁面能提供700ms的加載性能提升(onLoad)。且在用戶觀感上,頁面基本可以在切換動畫完成前展現。



          配合頁面的FCP數據,可以看到在優化后,頁面的首屏渲染時間可以從1550下降到1230,能提升300ms,且基本接近“秒開”。

          在其他更復雜的頁面上(更多圖片、更多JS),離線包可以取得更好的性能提升效果。


          業界方案對比


          B站方案與業界方案的差異點


          綜合來看,B站的離線包方案有以下亮點:

          錯峰發布:通過錯峰發布,充分利用CDN閑時流量,可以用較低的成本下發資源

          版本控制策略:通過版本控制策略,避免舊版本滯留,符合前端業務一次發布所有用戶更新的常規心智,對于需要緊急更新或下線的場景比較重要

          調試流程優化:掃碼調試可以明顯提高接入效率,保證線上穩定性是性能優化的第一前提。

          HTML快照:利用上一次渲染結果優化下次進入的首屏速度,雖然有較多的調試成本,但也有一試的價值。這個方案在某些社區文章里有被簡單提到過。

          AB實驗能力:保證頁面重大改版期間性能不下降,且能回收AB實驗數據,兼顧用戶體驗和業務訴求


          同時,有些業界常見的方案我們選擇不去實現,例如:

          Webview預載

          提前初始化一個Webview掛在后臺,等需要的時候直接使用。這個方案在前期因為公司內各業務容器不統一而無法落地,現在統一后發現預載收益有限,B站App內的容器二次加載耗時基本在130ms以下,為了這點時間而長期占用較多的內存,在一個視頻觀看體驗優先的App上并不明智。而如果為提升首次初始化耗時而在App啟動時預載Webview,又會影響用戶的啟動速度,因此作罷。

          接口預請求

          同樣也是收益不夠高的問題。這里我們談的是在Webview初始化時提前發起接口請求的方案。在一個充分優化的離線包上,理論上在html和js加載后,會很快開始接口請求,所以有概率在請求還沒返回時,前端就開始從客戶端取數據,處理這個中間狀態有一定的成本,也會帶來額外的調試心智負擔。理論的性能優化表現應該在50-150ms左右,相對來說動力不足。

          對于像Feed流預加載后續文章接口的實現方案,由于通用性不足,不作為全公司級離線包需要考慮的方案,可以在各業務層自行實現。


          有一些技術是我們已經實現了,但其他人也都有類似實現的:

          公共包技術:集合公共JS資源,避免多份打包,同時利用平臺能力,自動完成公共資源更新

          增量包下發:對每個版本的包,都會生成這個包和前N個版本差分計算的增量包,根據客戶端當前版本下載增量包,降低CDN壓力

          熱更新推送:可以對某些高優先級業務,開啟熱更新推送,助力快速更新

          僅Wifi下載和版本限制:對下發條件做一定的限制,節約用戶流量


          Webview常駐方案


          簡介:對于Feed流或者頻繁打開同類頁面的場景,可以保持Webview常駐后臺,點擊鏈接時將Webview拉到前臺,并替換頁面的URL參數,頁面拉取接口數據并展現。

          差異點:



          Webview常駐方案

          B站離線包方案

          性能

          非常快。由于省去了容器初始化和頁面JS初始化的諸多流程,這個方案的性能優于離線包,配合feed流數據接口預取,可以讓用戶幾乎無法感知到加載過程。

          性能比較常規,在不使用HTML快照這樣的特殊方案時,性能與業界方案是類似的。

          方案通用性

          較差。適用場景相對局限,比較適合頻繁往返于列表頁到詳情頁的這類場景,例如新聞閱讀類應用、商城類應用等。

          通用性好,同樣的方案可以在B站絕大部分H5業務上使用。漫畫App、云視聽小電視、直播姬等App的也已低成本接入

          代碼侵入性

          強。需要代碼做針對性適配,以及客戶端配合才能完成一個特定場景下的落地

          侵入性低,除了需要注意Post請求問題和History API在IOS上無法記錄歷史記錄外,其他代碼與線上業務完全相同


          總體看,B站的離線包方案為了方案通用性,犧牲了一些性能表現,好處是可以比較簡單地應用在各業務場景上,帶來相對普遍的價值。


          貨拉拉的離線方案


          簡介:貨拉拉方案與本文提到的方案在某些方面是有共通之處的,在基礎加速層面上除了底層的技術實現思路采用了加載本地路徑的方案,其他包括資源下發、多層降級機制等方面基本類似。

          差異點:

          由于技術實現原理類似,因此在性能和通用性上,兩者差異較小。我們從另外的方面比較:



          貨拉拉方案

          B站離線包方案

          容器實現位置

          基于通用容器上的一個獨立增強容器,各業務容器基于此拓展

          直接放入基礎容器內,開箱即用

          兼容性

          存在跨域問題

          基于https攔截,與線上幾乎一致

          代碼侵入性

          有少量侵入性,需要對本地加載的路徑做一些適配

          侵入性低,除了需要注意Post請求問題和History API在IOS上無法記錄歷史記錄外,其他代碼與線上業務完全相同


          另外我們觀察到貨拉拉方案里離線包的URL映射是動態下發的,B站的離線包URL映射則是打包到包里的,另外通過一個動態接口控制當前可用的版本。

          這兩個方案都是可行的,總體來看,有這些差異:



          動態下發URL映射

          打包URL映射

          優勢

          方便靈活,可以很簡單地修改映射關系

          有利于這個包的邏輯獨立性,這也是掃碼調試功能好實現的一個因素

          缺點

          可追溯性差,配置不斷在變化,配置和包資源無法一一匹配時,可能導致過去歷史版本可能因為配置變更而不能再看

          靈活度差,修改URL映射需要發一個新的包


          支付寶的Nebula方案離線包能力


          支付寶的離線包的定位并非是加速線上業務的能力,而是更接近離線H5應用的模式。在離線包未下載的時候,他會請求提前部署的降級資源,也就是使用的業務并不需要自行部署一套頁面在線上,需要有一個域名和url,而是只需要使用它提供的方案就可以完成部署。

          其運行機制,類似貨拉拉方案,是用file協議加載,向H5頁面提供一個虛擬域名供識別。

          在API能力上,配備了一套JSAPI來滿足業務的使用,所以看起來比較接近小程序的實現思路。

          總體來講,支付寶因為業務都是以一個個獨立的H5App來承載的,H5 App之間彼此關聯和交互較少,所以方案會接近小程序,而后續支付寶也確實往前走了一步,實現了小程序的能力。

          B站由于頁面基本都是自有的,且Native跳H5、H5跳Native的場景很多,需要為用戶提供一個整體性的體驗,所以方案更偏向“加速”,而非獨立H5 App


          UC的NSR方案


          UC瀏覽器在新聞feed流頁面加載中采用了NSR(Native Side Rendering),首先在列表頁中加載離線頁面模板,通過Ajax預加載頁面數據,通過Native渲染生成Html數據并且緩存在客戶端。

          NSR本質是分布式SSR,將服務器的渲染工作放在了一個個獨立的移動設備中,實現了頁面的預加載,同時又不會增加額外的服務器壓力。

          下面看方案對比:



          NSR方案

          B站離線包方案

          性能

          更快,通過客戶端渲染,可以不依賴Webview生命周期就可以提前渲染出所需的HTML

          一般,仍然需要等待容器初始化+html加載+JS編譯執行+接口請求+框架渲染

          方案通用性

          相對一般,有一定的定制性

          比較通用,整體都是在Web標準上做的一些優化

          代碼侵入性

          較強侵入性。一個是代碼編寫接近常規帶SSR的頁面,另一方面NSR渲染結果和Webview內展現的過程是有一定邏輯的。

          較低侵入性。使用常規方案幾乎不需要改代碼。

          如需更快的性能,代碼快照會類似這套方案,只不過復用的是上一次渲染的結果。當然使用代碼快照也意味著帶來更強的侵入性。

          兼容性

          需要額外考慮在客戶端JS環境運行的兼容性

          較好,與線上頁面類似


          騰訊的VasSonic方案


          VasSonic除了常規的資源預載之外,還做了以下事情:

          • webview 初始化和通過客戶端代理資源請求并行
          • 流式攔截請求,邊加載邊渲染
          • 實現了動態緩存和增量更新

          VasSonic 的方案整體思路和效果非常不錯,特別是對于大部分 web 場景,通常我們的模板較少發生變化,大部分是數據部分變化,能夠很好的通過局部刷新做到秒開效果。對于首次加載而言,通過并發請求和 webview 創建帶來了不錯的性能提升,還能無縫的支持離線包策略。

          但是 VasSonic 定義了一套特殊的注釋標記及拓展了頭部,需要包括后臺在內的前后端進行改造,對 web 侵入性非常強,接入的工作量及維護成本會非常大。


          方案總結


          總的來講,離線包加速方案的各個技術決策其實就是在平衡通用性和性能。

          通用性越好,能做的事情越少,方案約需要遵循Web標準,當然性能的提升幅度也會小一些。

          拋開通用性,如果針對業務特定定制更多的優化方案,那么優化效果一定是可以做的更好的,當然也就更專用,難以大規模鋪開。


          B站的離線包在決策時更多考慮了通用性,因此得以在各業務線都能比較低成本地接入,有比較廣泛的使用群體。在此基礎上,例如電商業務也針對他們的業務特點做了更專用化的定制,例如Webview常駐方案,得到了更好的效果。所以可以認為離線包作為一個通用方案,提升了性能的下限,它并不與專用方案沖突,可以再額外使用專用方案來提升性能的上限。


          參考文章


          B站離線包在研發階段基本遵循凈室研發規則,除參考了業界方案的一些思路外,具體的方案設計和實現均為自研。

          在本篇文章的方案對比方面,主要參考了以下文章:

          【移動端h5秒開方案總結】https://blog.towavephone.com/mobile-h5-startup-way/

          【貨拉拉H5離線包原理與實踐】https://juejin.cn/post/7103348563479887885

          【CSR、SSR、NSR、ESR傻傻分不清楚,一文幫你理清前端渲染方案!】https://juejin.cn/post/6844904178519834638

          【離線化集成方案-安全設計與優化】https://research.szltech.com/?p=1935

          【WebView性能、體驗分析與優化】https://tech.meituan.com/2017/06/09/webviewperf.html

          【螞蟻金服金融科技產品手冊】https://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/87479/AntCloud_zh/1578025862524/10%20H5%20%E5%AE%B9%E5%99%A8%E5%92%8C%E7%A6%BB%E7%BA%BF%E5%8C%85%2020200101.pdf



          作者:大前端

          來源-微信公眾號:嗶哩嗶哩技術

          出處:https://mp.weixin.qq.com/s/WMf28adh30v67uuEn99F6Q

          眾號【傳智播客博學谷】回復關鍵詞:前端 PS Java(100G) Python(80G) 大數據 區塊鏈 測試 PPT JS(40g+300教程) HTML 簡歷 領取相關學習資料!

          一、HTML

          1、<image>標簽上title屬性與alt屬性的區別是什么?

          alt屬性是為了給那些不能看到你文檔中圖像的瀏覽者提供文字說明的。且長度必須少于100個英文字符或者用戶必須保證替換文字盡可能的短。

          這包括那些使用本來就不支持圖像顯示或者圖像顯示被關閉的瀏覽器的用戶,視覺障礙的用戶和使用屏幕閱讀器的用戶等。

          title屬性為設置該屬性的元素提供建議性的信息。使用title屬性提供非本質的額外信息。參考《alt和title屬性的區別及應用》

          2、分別寫出以下幾個HTML標簽:文字加粗、下標、居中、字體

          加粗:<b>、<strong>

          下標:<sub>

          居中:<center>

          字體:<font>、<basefont>、參考《HTML標簽列表》

          3、請寫出至少5個html5新增的標簽,并說明其語義和應用場景

          section:定義文檔中的一個章節

          nav:定義只包含導航鏈接的章節

          header:定義頁面或章節的頭部。它經常包含 logo、頁面標題和導航性的目錄。

          footer:定義頁面或章節的尾部。它經常包含版權信息、法律信息鏈接和反饋建議用的地址。

          aside:定義和頁面內容關聯度較低的內容——如果被刪除,剩下的內容仍然很合理。

          參考《HTML5 標簽列表》

          4、請說說你對標簽語義化的理解?

          a. 去掉或者丟失樣式的時候能夠讓頁面呈現出清晰的結構

          b. 有利于SEO:和搜索引擎建立良好溝通,有助于爬蟲抓取更多的有效信息:爬蟲依賴于標簽來確定上下文和各個關鍵字的權重;

          c. 方便其他設備解析(如屏幕閱讀器、盲人閱讀器、移動設備)以意義的方式來渲染網頁;

          d. 便于團隊開發和維護,語義化更具可讀性,遵循W3C標準的團隊都遵循這個標準,可以減少差異化。

          5、Doctype作用? 嚴格模式與混雜模式如何區分?它們有何意義?

          聲明位于文檔中的最前面,處于 標簽之前。告知瀏覽器以何種模式來渲染文檔。

          嚴格模式的排版和 JS 運作模式是,以該瀏覽器支持的最高標準運行。

          在混雜模式中,頁面以寬松的向后兼容的方式顯示。模擬老式瀏覽器的行為以防止站點無法工作。

          DOCTYPE不存在或格式不正確會導致文檔以混雜模式呈現。

          6、你知道多少種Doctype文檔類型?

          標簽可聲明三種 DTD 類型,分別表示嚴格版本、過渡版本以及基于框架的 HTML 文檔。

          HTML 4.01 規定了三種文檔類型:Strict、Transitional 以及 Frameset。

          XHTML 1.0 規定了三種 XML 文檔類型:Strict、Transitional 以及 Frameset。

          Standards (標準)模式(也就是嚴格呈現模式)用于呈現遵循最新標準的網頁,

          Quirks(包容)模式(也就是松散呈現模式或者兼容模式)用于呈現為傳統瀏覽器而設計的網頁。

          7、HTML與XHTML——二者有什么區別

          a. XHTML 元素必須被正確地嵌套。

          b. XHTML 元素必須被關閉。

          c. 標簽名必須用小寫字母。

          d. XHTML 文檔必須擁有根元素。

          參考《XHTML 與 HTML 之間的差異》

          8、html5有哪些新特性、移除了那些元素?

          a. HTML5 現在已經不是 SGML 的子集,主要是關于圖像,位置,存儲,多任務等功能的增加。

          b. 拖拽釋放(Drag and drop) API

          c. 語義化更好的內容標簽(header,nav,footer,aside,article,section)

          d. 音頻、視頻API(audio,video)

          e. 畫布(Canvas) API

          f. 地理(Geolocation) API

          g. 本地離線存儲 localStorage 長期存儲數據,瀏覽器關閉后數據不丟失

          h. sessionStorage 的數據在頁面會話結束時會被清除

          i. 表單控件,calendar、date、time、email、url、search

          j. 新的技術webworker, websocket等

          移除的元素:

          a. 純表現的元素:basefont,big,center, s,strike,tt,u;

          b. 對可用性產生負面影響的元素:frame,frameset,noframes;

          9、iframe的優缺點?

          優點:

          a. 解決加載緩慢的第三方內容如圖標和廣告等的加載問題

          b. iframe無刷新文件上傳

          c. iframe跨域通信

          缺點:

          a. iframe會阻塞主頁面的Onload事件

          b. 無法被一些搜索引擎索引到

          c. 頁面會增加服務器的http請求

          d. 會產生很多頁面,不容易管理。

          參考《iframe的一些記錄》

          10、Quirks模式是什么?它和Standards模式有什么區別?

          在寫程序時我們也會經常遇到這樣的問題,如何保證原來的接口不變,又提供更強大的功能,尤其是新功能不兼容舊功能時。IE6以前的頁面大家都不會去寫DTD,所以IE6就假定 如果寫了DTD,就意味著這個頁面將采用對CSS支持更好的布局,而如果沒有,則采用兼容之前的布局方式。這就是Quirks模式(怪癖模式,詭異模式,怪異模式)。

          區別:總體會有布局、樣式解析和腳本執行三個方面的區別。

          a. 盒模型:在W3C標準中,如果設置一個元素的寬度和高度,指的是元素內容的寬度和高度,而在Quirks 模式下,IE的寬度和高度還包含了padding和border。

          b. 設置行內元素的高寬:在Standards模式下,給等行內元素設置wdith和height都不會生效,而在quirks模式下,則會生效。

          c. 設置百分比的高度:在standards模式下,一個元素的高度是由其包含的內容來決定的,如果父元素沒有設置百分比的高度,子元素設置一個百分比的高度是無效的用

          d. 設置水平居中:使用margin:0 auto在standards模式下可以使元素水平居中,但在quirks模式下卻會失效。

          11、請闡述table的缺點

          a. 太深的嵌套,比如table>tr>td>h3,會導致搜索引擎讀取困難,而且,最直接的損失就是大大增加了冗余代碼量。

          b. 靈活性差,比如要將tr設置border等屬性,是不行的,得通過td

          c. 代碼臃腫,當在table中套用table的時候,閱讀代碼會顯得異常混亂

          d. 混亂的colspan與rowspan,用來布局時,頻繁使用他們會造成整個文檔順序混亂。

          e. 不夠語義

          參考《為什么說table表格布局不好?》

          12、簡述一下src與href的區別

          src用于替換當前元素;href用于在當前文檔和引用資源之間確立聯系。

          src是source的縮寫,指向外部資源的位置,指向的內容將會嵌入到文檔中當前標簽所在位置

          href是Hypertext Reference的縮寫,指向網絡資源所在位置,建立和當前元素(錨點)或當前文檔(鏈接)之間的鏈接

          公眾號【傳智播客博學谷】回復關鍵詞:前端 PS Java Python 大數據 區塊鏈 測試 PPT JS HTML 簡歷 領取相關學習資料!

          么是HTML / HTM文件?他們相差一個字母有什么區別嗎,如何查看或編輯源代碼以及如何轉換成其他格式,例如DOCX,PDF,JPG 等,針對這些問題編程獅W3Cschool整理以下資料希望能對你有所幫助:

          什么是HTM或HTML文件?

          HTM / HTML 文件是超文本標記語言(Hyper Text Markup Language)文件,是 Internet 上的標準網頁文件類型。

          由于 HTM 文件是純文本文件,因此它們僅包含文本(例如您現在正在閱讀的內容)以及對其他外部文件的文本引用(例如本文中的配圖)。

          HTM 和 HTML 文件還可以引用其他文件,例如視頻,CSS 或 JS 文件。

          HTM與HTML的區別

          HTM 與 HTML 沒有本質意義的區別,只是為了滿足 DOS 僅能識別 8+3 的文件名而已,因為一些老的系統 (win32) 不能識別四位文件名,所以某些網頁服務器要求 index.html 最后一個 l 不能省略。MSIE 能自動識別和打開這些文件,但編寫網頁地址的時候必須是完全對應的,也就是說 index.htmindex.html 是兩個不同的文件,對應著不同的地址。值得一提的是 UNIX 系統中對大小寫敏感,不吻合的話就可能報沒有文件或者找不到文件。

          如何打開HTM或HTML文件?

          任何 Web 瀏覽器,例如 Edge,Firefox,Chrome,Opera,IE,360 安全瀏覽器等,都可以打開并正確顯示 HTM 和 HTML 文件。換句話說,在瀏覽器中打開這些文件并“解碼(decode)” HTM 或 HTML 文件使其能正確顯示。

          現在有很多簡化編輯和創建 HTM / HTML 文件的工具。一些著名的免費 HTML 編輯器包括 Eclipse ,Komodo Edit 和 Bluefish 。另一個流行的具有許多高級功能的 HTM / HTML 編輯器是 Adobe Dreamweaver ,不過它是收費的。

          雖然 Windows 系統自帶的記事本等簡單的文本編輯器的功能不如專用的 HTM 編輯器那么豐富,但是對 HTM 或 HTML 文件進行簡單編輯修改還是可以的。不過,W3Cschool還是建議大家使用專用的編輯器,如 WebStorm、VS Code 等,它具更多專業功能。

          這是一個非常簡單的 HTML 頁面以文本形式顯示的示例:

          源碼:

          <!doctype html>
          <html>
          
              
          <head>
          <meta charset="utf-8">
          <title>什么是HTM或HTML文件? - 編程獅(w3cschool.cn)</title>
          </head>
          
          
          <body>
              <h1>什么是HTM或HTML文件?</h1>
              <p>HTM / HTML 文件是超文本標記語言(Hyper Text Markup Language)文件,是 Internet 上的標準網頁文件類型。</p>
              <p>由于 HTM 文件是純文本文件,因此它們僅包含文本(例如您現在正在閱讀的內容)以及對其他外部文件的文本*引用*(例如本文中的配圖)。</p>
              <p>HTM 和 HTML 文件還可以引用其他文件,例如視頻,CSS 或 JS 文件。</p>   
          </body>
          
              
          </html>

          當 Web 瀏覽器呈現信息時,HTML 文件的源代碼被“轉換”為真實的網頁(盡管源代碼已很精簡了)。

          如何轉換HTML和HTM文件?

          HTM 文件以特定的語法(規則)構成,以使其中的代碼和文本在瀏覽器中打開時能夠正確顯示。因此,將 HTM / HTML 文件轉換為另一種格式可能會丟失頁面上的所有功能。

          如果你想要做的是將一個 HTM / HTML 文件轉換為方便離線查看的文件,這時圖片或 PDF 格式會方便很多。

          在 Chrome 中,鼠標右鍵單擊網頁,出現的選項菜單中進入 “打印(P)...”(快捷鍵:CTRL + P) ,在打印選項中選擇另存為 PDF,以將窗口中的頁面轉換為 PDF 文件。Chrome 瀏覽器的擴展功能也稱為“全屏截屏”,可將 Chrome 瀏覽器中所有打開的 HTM / HTML 文件轉換為 PNG 文件。

          其他瀏覽器具有類似的功能,例如 Firefox 的 “另存為 PDF” 加載項。

          您也可以使用專門用于 HTM / HTML 進行圖像文件轉換的網站,例如iWeb2Shot 或Web-capture 。

          一個免費的文件轉換器可以用來轉換并保存 HTM / HTML 文件到您的計算機。如 FileZigZag 是一個免費的文檔轉換器網站,可將 HTM 轉換為RTF,EPS,CSV,PDF 和許多其他格式。

          HTM / HTML 文件不能轉換為文本文件格式以外的任何格式。例如,HTML 文件永遠不能轉換為 MP3 音頻文件。

          文件打不開?

          HTML / HTM 文件應該很容易打開,因為它們只是任何 Web 瀏覽器都可以查看的文本文件。如果您的文件沒有從上面建議的任何程序打開,則很有可能正在打開的這個文件并非超文本標記語言文件。

          某些文件格式使用的文件擴展名與 HTML / HTM 非常相似,但實際上并非相同。一個主要的示例是用于壓縮 HTML 電子書文件的 HTMLZ 文件擴展名。有 HTML 文件在內的 HTMLZ 文件,但整個包的格式為 ZIP,不會在 Web 瀏覽器或文本編輯器打開。

          在此示例中,您需要特定的 HTMLZ 文件查看器,例如Caliber 。或者,由于此文件格式實際上是存檔,因此您可以使用 7-Zip 之類的文件解壓縮器將其打開,然后您可以使用網絡瀏覽器或上述任何其他 HTML 查看器/編輯器打開任何單獨的 HTML 文件。

          TMLANGUAGE 是另一個可能與 HTML / HTM 文件混淆的文件擴展名。這些實際上是TextMate 用于 macOS 的 TextMate 語言語法文件。

          以上就是編程獅W3Cschool為你整理的關于《什么是HTM或HTML文件?如何打開、編輯和轉換HTM和HTML文件?》的全部內容,現希望可以幫到你~


          主站蜘蛛池模板: 国产福利微拍精品一区二区| 亚洲av永久无码一区二区三区| 国产在线一区二区三区| 无码人妻啪啪一区二区| 久久久91精品国产一区二区三区| 日本一区二区三区在线网| 一区二区三区影院| 日本不卡一区二区三区| 香蕉久久一区二区不卡无毒影院| 久久综合精品不卡一区二区| 久久国产免费一区二区三区| 无码人妻精品一区二区三18禁| 国产亚洲一区二区手机在线观看| 亚洲色婷婷一区二区三区| 美女一区二区三区| 亚洲第一区香蕉_国产a| 亚洲av成人一区二区三区| 亚洲香蕉久久一区二区| 日韩福利视频一区| 任你躁国产自任一区二区三区| 亚洲午夜电影一区二区三区| 久久综合精品不卡一区二区| 中文无码一区二区不卡αv| 国产精品一区二区三区高清在线| 波多野结衣在线观看一区| 中文字幕在线观看一区二区 | 在线播放偷拍一区精品| 欲色影视天天一区二区三区色香欲 | 国产一区高清视频| 亚洲AV美女一区二区三区| 综合一区自拍亚洲综合图区| 国产一在线精品一区在线观看| 无码福利一区二区三区| 成人免费一区二区三区| 日韩人妻无码一区二区三区99| 亚洲av无码片vr一区二区三区 | 日本无卡码一区二区三区| 国产精品第一区第27页| 国模无码视频一区二区三区| 亚洲国产精品第一区二区| 中文字幕一区二区区免|