要
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到本地路徑的映射關系就可以了。
通常會有兩種代碼來源:
最后打包的目錄,大概包含以下內容
一個典型的代碼產出目錄如圖所示:
config.json示例:
離線包的下發機制
離線包的下發依賴Fawkes(客戶端統一平臺)的ModManager,使用與客戶端統一的下發渠道,有利于統一調度,控制下載期間的CPU、帶寬占用和存儲空間占用。
ModManager是用于下發客戶端資源的一個統一渠道,絕大部分需要動態下發的資源都會通過ModManager統一管理和分發,并具備了諸如增量包生成、資源錯峰下發、熱推送下發、版本和網絡環境限制等諸多能力。復用這套基礎能力省去了我們額外建立一套下發鏈路的成本,也能更容易地管控CDN流量以及客戶端存儲空間占用。
離線包平臺有三種發布模式,分為常規發布、錯峰發布和預約發布,這些發布模式的實現方案有一定的差異:
常規發布
代碼包將直接發布到線上,所有符合限制條件(版本、時間、灰度等策略)的冷啟動App的用戶都將按照資源包優先級逐步下載到新版本。
如果用戶本地沒有這個包的舊版本,那么會下載全量包;如果已經存在較近的舊版本,則會下載增量包。但即使有增量更新能力,在用戶使用的高峰時段,常規發布仍會帶來較大的帶寬壓力,所以高峰期發布需要額外審批。
如圖所示,在常規發布后,資源包的下載會快速制造一個流量高峰,而后隨著覆蓋率的提升,緩慢下降,直到大部分用戶完成更新。因此,我們除了常規發布外,還需要更智能的發布策略來降低成本。
錯峰發布
錯峰發布模式下,會設置離線包延后1-3天生效,在此期間,會借用流量低谷下載離線資源包。從而有效利用CDN的閑時流量,節約成本。
錯峰發布適合第一次發布的包,可以利用閑時流量緩解第一次全量下載對用戶的流量壓力。后續版本再發布時則可根據上線時間要求靈活使用發布模式。
預約發布
在離線包的實踐中有這樣一個問題:直播業務的大部分頁面都接入了離線包,但某些頁面常常需要在晚上高峰期上線發布,但在高峰期上線離線包又會帶來很高昂的帶寬費用。如何既保證可以及時發布,又可以兼顧離線包呢?我們設計了預約發布功能。
預約發布允許設置后續24小時內的某個低峰時間點發布。設置后,當前線上使用的包版本可以設置即刻失效,用戶降級請求線上頁面訪問新版本內容。而新版本會在指定時間點發布,在此后更新完成的用戶,就可以正常使用加速能力。
預約發布適合需要在高峰時段上線新功能,且對短時間內性能下降不敏感的業務。即可以取得足夠快的發布速度,又可以避免較高的帶寬費用。缺點是會影響這個時間段內用戶訪問頁面的速度,也可能對線上服務造成突發壓力。
資源匹配機制
如圖所示,當Webview加載一個URL時,會經歷以下環節:
版本控制和快速回滾策略
離線包由于是預先給客戶端下發資源,所以不可避免地會遇到更新時效的問題。在更新時效上,我們之前在使用ModManager時會遇到這些問題:
考慮到前端離線包的主要目的是加速,不同于客戶端包下載到資源才可以使用對應功能的限制,我們可以靈活利用線上兜底策略,來解決這幾個問題。
于是在ModManager機制的基礎上,我們又額外引入了一個接口(x/offline/version接口),用來告知客戶端當前可以使用的版本白名單。客戶端會在每次冷啟動和切后臺返回時刷新接口數據(有較短時間的限頻和緩存邏輯),從而可以實現以下能力:
版本接口的大概形式是這樣的:
這個接口采取版本白名單機制,在接口參數中確定了App環境信息后,會查詢出這個環境這個App下可用的包版本列表。在發布新版本時,白名單里會同時出現2個版本,從而允許舊版本離線包仍然使用一段時間,在指定時間后,會只下發最新版本號,舊版用戶在更新完成前會請求線上資源。
版本接口為了提供較高的時效性,每次切后臺返回或者冷啟動都會請求刷新,會有較高的QPS,我們在接口上做了充足的緩存策略,所有數據均是異步定時更新并完成計算,在請求到達時始終從內存緩存中返回數據,服務資源占用率比較可控
上圖表示了一個設置了1小時舊版本過期的項目在占有率變化上的趨勢。版本控制功能主要解決舊版本過期問題,可以使得舊版本在過期后立刻失效,而新版本不受影響。
調試流程優化
離線包由于需要等待客戶端將包下載完成才可以體驗,因此在開發調試階段會帶來很大的痛苦。為此,我們仿照小程序的開發流程,設計了掃碼調試功能,在開發、預覽等場景上,均可以使用掃碼調試功能快速預覽頁面在離線包下的效果。
掃碼后,在預覽調試頁面,會調用JSAPI要求客戶端下載指定的zip資源包,放置到特定的調試目錄。后續在App存續期間再次打開對應的H5頁面時,會優先使用調試目錄內的資源,而其他機制保持一致,因此在大部分場景下可以完美還原線上離線包的使用體驗。
另外在打開的調試頁面上,還會注入離線包調試工具,幫助業務發現有哪些未命中離線的資源以及查看Performance Timing API數據,幫助優化離線包的文件組合,提升加速效果。
HTML快照
在很多需要優化首屏速度的場景,使用SSR都是一個可行的方式,在服務器端提前渲染好整個頁面的HTML結構,這樣瀏覽器拉取到HTML后就可以立刻開始渲染,用戶就能更快地看到內容。
SSR能夠加速的核心條件是提前渲染完的HTML,如果我們可以緩存上一次的頁面渲染結果,是否也可以用于加速下一次用戶進入時的首屏速度呢?顯然是可以的,只不過需要先解決一些問題,例如
基于上述問題,離線包HTML快照能力做了一些針對性的方案。不過我們可以先看一下這個功能的運行流程:
如圖所示,當用戶請求一個URL時,會先判斷是否命中離線包,如果命中,則檢查是否存在HTML快照,如果存在快照,那么使用快照HTML,否則使用離線包內附帶的HTML。當頁面完成加載后,會在頁面上調用一個JSB,用來存儲當前頁面的快照。
關于快照,還設置了以下限制:
除此之外,對于設置的HTML內容,還需要注意以下問題:
這樣基本可以解決上述提到的問題。HTML快照的技術基礎是在基于一個假設,即頁面DOM結構會與數據一一對應,所以相同的數據輸入,無論多少次渲染都應該輸出相同的DOM結構。那么只要提前緩存DOM結構,就可以在下次訪問時先展示舊頁面,再無縫切換到新頁面。
這個假設雖然大部分情況下雖然成立,但卻仍舊缺乏業務實踐,具體在實踐中會遇到哪些問題,需要在生產應用后才能有相對靠譜的最佳實踐。這方面的實踐會在今年展開,歡迎持續關注與合作。
AB實驗
由于離線包會攔截入口HTML文件請求,在頁面做了大改版需要頁面級AB實驗的場合,就無法在服務端來進行分流決策。為此,我們使用網址Rewrite能力使得同樣一個URL在不同用戶側對應兩份不同的離線包。
其大概流程如下:
上述方案可以實現頁面的AB能力,但由于AB分流決策與頁面打開的時機不同,所以無法上報進組數據,只能上報用戶實際進入頁面的數據,所以會影響部分數據的回收。
新舊版本的配置差異如上圖所示。使用兩個不同的URL,就可以分別對應兩個不同的離線包,從而在不影響離線包本體設計的基礎上實現AB能力。
適用場景與局限
離線包提供的幾個核心能力,可以有效提升頁面的首屏速度,但仍然因為技術實現和架構的原因,存在一些限制:
存在失效場景,需保留線上訪問能力
在某些場景下,離線能力會暫時失效,從而會請求線上頁面。接入離線包的業務需要自行確保線上URL可訪問且功能正常,只能把離線包作為加速手段,而非最終部署目標。
失效的場景包括:App版本過低、尚未更新到可用版本的用戶(新下載App用戶或長期低活躍用戶)、緊急下線或預約發布期間由業務觸發的暫時禁用
增加上線復雜度
接入離線包后,需要在上線前完成離線包功能驗證,且需要在線上頁面上線完成后,再操作離線包發版。會增加一定的上線復雜度。
雖然離線包的資源預載和接口預載能力已經比較成熟,通常不會引入額外的問題,但仍然需要注意自測。
上線鏈路復雜的問題,通過在公司前端統一發布平臺集成離線包發布流程來解決。
帶來額外帶寬成本
每一個上線發布的離線包,都會下發到絕大部分用戶的手機中,而很多用戶可能根本不是這個業務的目標用戶。同時下發的過程也會帶來額外的帶寬成本,尤其是在高峰期上線時。
目前我們確實還沒有精細化提升帶寬使用率的能力,未來可能會看情況,采用人群包或其他方式,優化下發資源的精準度。
Webview本身的限制
目前由于IOS系統在使用https攔截能力時的一些Bug,需要格外注意這兩個問題:
綜上,哪些業務適合接入離線包呢?離線包通常適合以下類型的業務:
離線化的終點在哪里?
當我們將越來越多資源提前緩存在用戶手機里,免去網絡IO這一最大的速度瓶頸,就會發現其實它跟客戶端界面業務差距并不會很大。這個存在形態位于Native和H5之間,它犧牲了一些發版的便利性,但獲得了更快的加載速度。雖然我們無法修改承載H5的Webview本身,也必須要承受Webview帶來的性能問題,但我們也很好奇如果將一個頁面優化到極致,是否真的可以讓用戶無法通過加載速度區分哪些頁面是Native實現,哪些頁面是H5實現呢?
后續我們將在一些頁面上實驗這樣的速度優化策略:
當這個實驗做完后,會再寫一篇文章,總結這樣綜合實踐方案下的經驗,為其他業務的優化提供參考。我們的目標是樹立起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除了常規的資源預載之外,還做了以下事情:
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 文件是超文本標記語言(Hyper Text Markup Language)文件,是 Internet 上的標準網頁文件類型。
由于 HTM 文件是純文本文件,因此它們僅包含文本(例如您現在正在閱讀的內容)以及對其他外部文件的文本引用(例如本文中的配圖)。
HTM 和 HTML 文件還可以引用其他文件,例如視頻,CSS 或 JS 文件。
HTM 與 HTML 沒有本質意義的區別,只是為了滿足 DOS 僅能識別 8+3 的文件名而已,因為一些老的系統 (win32) 不能識別四位文件名,所以某些網頁服務器要求 index.html 最后一個 l 不能省略。MSIE 能自動識別和打開這些文件,但編寫網頁地址的時候必須是完全對應的,也就是說 index.htm 和 index.html 是兩個不同的文件,對應著不同的地址。值得一提的是 UNIX 系統中對大小寫敏感,不吻合的話就可能報沒有文件或者找不到文件。
任何 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 文件的源代碼被“轉換”為真實的網頁(盡管源代碼已很精簡了)。
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文件?》的全部內容,現希望可以幫到你~
*請認真填寫需求信息,我們會在24小時內與您取得聯系。