亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

HTML5頁(yè)面無(wú)縫閃開(kāi)的問(wèn)題及解決方案

  發(fā)布時(shí)間:2020-06-11 11:04:16   作者:Tencent AlloyTeam   我要評(píng)論
這篇文章主要介紹了HTML5頁(yè)面無(wú)縫閃開(kāi)方案,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

在傳統(tǒng)的 web 優(yōu)化中,我們可以采取壓縮、拆包、動(dòng)態(tài)加載等方法減少首屏資源大小,也能通過(guò)離線包、頁(yè)面直出等方案加速 html 返回,之前一篇h5 秒開(kāi)大全有部分簡(jiǎn)析。在大部分場(chǎng)景中,這些方案都足夠用,也能得到出色的效果。但仍有兩種無(wú)法盡善盡美的地方:其一是短暫的白屏現(xiàn)象不可避免,其二是對(duì)于超大型 web 應(yīng)用難以做到秒開(kāi)。結(jié)合客戶端特性,我們有沒(méi)有辦法,進(jìn)一步做到極致,打開(kāi) web 頁(yè)面和打開(kāi)客戶端頁(yè)面無(wú)差異的體驗(yàn)?zāi)兀?/p>

傳統(tǒng)方案的困境

無(wú)論是 html 離線,還是直出,以及讓 webview 啟動(dòng)和網(wǎng)絡(luò)請(qǐng)求并行 ,頁(yè)面的切換和打開(kāi)都無(wú)法避免 html 加載這一過(guò)程。對(duì)于大型應(yīng)用而言,龐大的 js 初始化解析和執(zhí)行會(huì)耗費(fèi)巨大的時(shí)間。

 

新的思考方向?

速度優(yōu)化的本質(zhì)是以空間換時(shí)間。我們是否可以從這個(gè)思路,將打開(kāi) webview 及解析 html 這以過(guò)程省略掉呢?答案是可以的。

容器化方案

容器化 即是我們最終探索與實(shí)踐的出來(lái)的一套方案。正常 web 頁(yè)面關(guān)閉后,webview 組件即會(huì)銷(xiāo)毀掉,下一次再打開(kāi)需要重新啟動(dòng)。通常讓 webview 保持常駐的做法可以節(jié)省 webview 啟動(dòng)時(shí)間, 但簡(jiǎn)單的常駐 webview 并不能做到頁(yè)面秒開(kāi),頁(yè)面打開(kāi)仍然需要重新解析 html。

對(duì)于我們的應(yīng)用特征而言,頁(yè)面切換實(shí)際上是僅僅內(nèi)容數(shù)據(jù)的變化,比如切換一篇文檔,其 html 容器及樣式都是同一套,而差異僅僅只是在數(shù)據(jù)上,重新載入 html 及初始化 js 這部分耗時(shí)完全可以避免掉。讓 webview 組件及其容器內(nèi)的 html 頁(yè)面常駐,在文檔切換的過(guò)程,僅僅對(duì)數(shù)據(jù)進(jìn)行替換,這即是容器化方案。容器化方案省去了 webview 重復(fù)啟動(dòng)和渲染 html 的問(wèn)題,打開(kāi)文檔,耗時(shí)只在做數(shù)據(jù)替換,真正做到了秒開(kāi)。

容器切換

web 側(cè)如何感知到不同的頁(yè)面在進(jìn)行互切換,數(shù)據(jù)如何做到替換呢?

首先在 app 打開(kāi)的時(shí)候,文檔列表會(huì)進(jìn)行數(shù)據(jù)預(yù)拉取,同時(shí)觸發(fā)客戶端預(yù)啟動(dòng)容器,除此外,其他任意場(chǎng)景也能按需觸發(fā)容器啟動(dòng)(后面會(huì)聊到)。容器內(nèi)會(huì)提前進(jìn)行 html 渲染和 js 執(zhí)行,此時(shí)的數(shù)據(jù)是空的。用戶點(diǎn)擊文檔,客戶端會(huì)對(duì)打開(kāi) url 這一行為進(jìn)行監(jiān)聽(tīng),同時(shí)解析 url,取出唯一標(biāo)識(shí)符, 判斷本地是否已經(jīng)存在并且符合要求的數(shù)據(jù),如果條件命中,直接使用已經(jīng)打開(kāi)的容器切出,通知到容器內(nèi)的 web,web 收到通知,通過(guò) url 取出標(biāo)識(shí)符,從本地進(jìn)行數(shù)據(jù)獲取,然后對(duì)數(shù)據(jù)進(jìn)行替換渲染,從而完成頁(yè)面切換。

容器化數(shù)據(jù)替換

直接容器替換的思路省去了代碼加載和解析時(shí)間,但對(duì)于前端代碼而言,需要支持直接替換數(shù)據(jù)。大部分前端項(xiàng)目代碼設(shè)計(jì)都是 自執(zhí)行調(diào)用 方式,支持容器化的前提是:需要對(duì)代碼改造成可支持 數(shù)據(jù)組裝和銷(xiāo)毀 。

// 大部分應(yīng)用加載頁(yè)面初始化的場(chǎng)景
class App {
    public init() {
     initA();
     initB();
        // 初始化各種模塊
        ...
    }
}
 
const app = new App();
app.init();

自執(zhí)行調(diào)用后,大量的內(nèi)部依賴(lài)模塊也依次進(jìn)行初始化,然后數(shù)據(jù)常駐在內(nèi)存中,通常對(duì)于加載一個(gè)正常網(wǎng)頁(yè)而言,用戶每次都是新開(kāi)頁(yè)面,加載 html, 重新進(jìn)行解析和初始化,并不會(huì)帶來(lái)什么問(wèn)題。但是按照容器化思路,頁(yè)面不會(huì)重新載入,只進(jìn)行數(shù)據(jù)替代,對(duì)于大型應(yīng)用而言意味著成千上萬(wàn)的模塊需要支持內(nèi)存釋放和數(shù)據(jù)切換,一旦沒(méi)有處理好,會(huì)面臨嚴(yán)重的內(nèi)存泄露和代碼健壯性問(wèn)題。如何組織和管理這些代碼,支持可插拔式,讓整個(gè)頁(yè)面初始化流程都能鏈?zhǔn)浇M裝,可以進(jìn)行配置,是進(jìn)行容器化代碼改造的難點(diǎn)。

  • 依賴(lài)倒置

依賴(lài)倒置原則的是指內(nèi)部模塊不應(yīng)該依賴(lài)外部模塊,底層模塊不應(yīng)該依賴(lài)上層模塊。

哪些才是底層模塊,哪些才是上層模塊呢?通常而言,越穩(wěn)定不變邏輯,應(yīng)該是越底層,越接近用戶交互,容易變化的部分是上層。具體層級(jí)劃分需要分析應(yīng)用的結(jié)構(gòu)和依賴(lài)關(guān)系,良好劃分層級(jí)的應(yīng)用是容器化改造的前提。

  • 職責(zé)鏈模式

職責(zé)鏈模式是指每個(gè)對(duì)象都有接受請(qǐng)求的可能,這些對(duì)象連接成一條鏈,請(qǐng)求沿著這條鏈的傳遞,直到有對(duì)象處理,這樣做的好處是減少接受者和發(fā)送者直接的耦合。比如在一個(gè)頁(yè)面加載生命周期中,我們可以讓內(nèi)部模塊到外部模塊都實(shí)現(xiàn)相應(yīng)的生命周期職責(zé),應(yīng)用啟動(dòng)和銷(xiāo)毀的過(guò)程,請(qǐng)求沿著指定鏈條從外到內(nèi)傳遞,也可以按需指定跳躍某個(gè)模塊,這樣大大降低了模塊之間的耦合,從而更好的管理代碼。

export default interface IRestart{
    emitter: EventEmitter;
    startDestroy(): void;
    destroy(): void;
    restart(): void;
    restartEnd(): void;
    // ...
}
class Page {
    next: PageFlow|null;
    cache: {
        start: (() => Promise<any>)[];
        end: (() => Promise<any>)[];
    };
    waitStart(callback: () => Promise<any>) {
        this.cache.start.push(callback);
    };
    waitEnd(callback: () => Promise<any>) {
        this.cache.end.push(callback);
    };
    setNext(flow: PageFlow) {
        this.next = flow;
        return flow;
    }
     // ...
   }
  • 依賴(lài)注入

所謂依賴(lài)注入是當(dāng)指 A 對(duì)象依賴(lài)另一個(gè) B 對(duì)象時(shí),不直接在 A 對(duì)象內(nèi)初始化 B,而是通過(guò)外部環(huán)境進(jìn)行初始化,作為參數(shù)傳入 A 對(duì)象中。這樣做的好處是當(dāng) B 模塊的初始化等條件發(fā)生變化時(shí),不必在 A 對(duì)象中進(jìn)行重復(fù)的修改。管理成百上千個(gè)這樣模塊相互依賴(lài)的代碼中,統(tǒng)一的依賴(lài)注入管理器會(huì)讓依賴(lài)關(guān)系管理變得更方便。

// 模塊加載器
class ServiceLoader {
    source: CONFIG;
    loaded: boolean;    // 是否已加載
    initialized: boolean;   // 是否已初始
    module: any;
    constructor(source: CONFIG) {
        this.loaded = false;
        this.initialized = false;
        // ...
    }
    async load(params?: any): Promise<any> {
     // ..load module
        return this.module;
    }
    //...
}
// 模塊管理器
class ServiceCollection {
    stack: ServiceLoader[];
    private services = new Map<CONFIG, ServiceLoader>();
    constructor() {
        this.stack = [];
    }
    createLoader(config: CONFIG): ServiceLoader {
        const loader: ServiceLoader =  new ServiceLoader(config);
        this.services.set(config, loader);
        return loader;
    }
    // ...
}
initA () {
    const ALoader= this.serviceCollection.createLoader(CONFIG.A);
    const discussMobile = ALoader.init(this.app);
}

數(shù)據(jù)預(yù)拉服務(wù)

容器是否會(huì)命中依賴(lài)兩個(gè)條件,其一對(duì)應(yīng)離線包代碼是否下載好;其二對(duì)應(yīng)版本的數(shù)據(jù)是否已經(jīng)預(yù)拉緩存完畢。

用戶進(jìn)入文檔管理首頁(yè),首先會(huì)去拉取列表索引數(shù)據(jù),然后通過(guò)列表數(shù)據(jù) id 進(jìn)行文檔內(nèi)容數(shù)據(jù)做預(yù)拉,儲(chǔ)存在本地?cái)?shù)據(jù)庫(kù),本地?cái)?shù)據(jù)庫(kù)的存儲(chǔ)可以參考前端離線化探索。

webview service

在整個(gè)數(shù)據(jù)預(yù)拉的過(guò)程,我們是通過(guò)一套獨(dú)立的客戶端后臺(tái) webview 服務(wù)執(zhí)行具體任務(wù),獨(dú)立服務(wù)的好處是讓各種容器化基礎(chǔ)服務(wù)和文檔管理列表本身進(jìn)行解耦,同時(shí)將拉取、解析、儲(chǔ)存數(shù)據(jù)這一對(duì)性能有消耗的過(guò)程放后臺(tái)服務(wù),減少了列表用戶交互界面層的性能壓力。

另一方面,作為多端公用的一個(gè)服務(wù),構(gòu)建流程上單獨(dú)部署,更新代碼的時(shí)候能夠不依賴(lài)其他頁(yè)面,變得更靈活。

數(shù)據(jù)快照

對(duì)于純 dom 結(jié)構(gòu)的文檔型品類(lèi),我們會(huì)在打開(kāi)文檔,解析數(shù)據(jù)后,把生成的 html 緩存在本地?cái)?shù)據(jù)庫(kù)一張快照表里。下一次切換容器時(shí),在取本地?cái)?shù)據(jù)去解析的同時(shí),會(huì)判斷對(duì)應(yīng) id 在快照表是否存在緩存,如果有,直接取出來(lái),覆蓋在 html 上,用戶可以提前看到上一次渲染的數(shù)據(jù),等本地?cái)?shù)據(jù)真正解析完,再展示可交互界面。解析數(shù)據(jù)準(zhǔn)備渲染也是需要一個(gè)上百毫秒的過(guò)程,這一策略可以讓用戶提前看到內(nèi)容。

預(yù)創(chuàng)建

有了極致的打開(kāi)速度,如何優(yōu)化新建速度呢。正常的新建流程是這樣的,用戶點(diǎn)擊新建按鈕,前端請(qǐng)求創(chuàng)建 cgi, 等待后臺(tái)創(chuàng)建成功返回新文檔 url,前端再新開(kāi) webview,加載展示頁(yè)面。我們可以看,由于需要等待創(chuàng)建接口返回的原因,到新建的過(guò)程比正常打開(kāi)一個(gè)文檔還要更久。

怎么樣才能讓新建也做到秒開(kāi)呢?思路和數(shù)據(jù)預(yù)拉取一樣,在用戶進(jìn)入文檔首頁(yè)的同時(shí),我們會(huì)提前預(yù)請(qǐng)求一批創(chuàng)建 id,然后緩存到本地,同時(shí)根據(jù)創(chuàng)建 id 生成一篇空白文檔數(shù)據(jù),儲(chǔ)存在本地,標(biāo)示狀態(tài)為未使用。用戶點(diǎn)擊新建按鈕,本質(zhì)上是從本地取一個(gè)未使用的文檔 url,直接用容器切換打開(kāi),然后再和后臺(tái)進(jìn)行同步。

秒開(kāi)效果

容器化方案前:

容器化方案后:

 

監(jiān)控與開(kāi)關(guān)系統(tǒng)

容器方案使用了數(shù)據(jù)預(yù)取場(chǎng)景,命中率的監(jiān)控非常重要。由于切換頁(yè)面的過(guò)程,如果命中容器,我們會(huì)接受來(lái)自客戶端的通知,在這個(gè)時(shí)機(jī),我們可以進(jìn)行上報(bào)。

另外一個(gè)非常重要的是容器能力的開(kāi)關(guān)系統(tǒng),在發(fā)布之初保持現(xiàn)網(wǎng)穩(wěn)定性是非常重要的措施,但任何程序都不能保證沒(méi)有 bug,我們通過(guò)內(nèi)部七彩石配置系統(tǒng)控制這套容器方案的各種特性在不同品類(lèi)下是否啟用,同時(shí)這套配置也支持灰度和回滾方案,能夠應(yīng)急各種突發(fā)問(wèn)題。

灰度期容器間命中率

 

待優(yōu)化的問(wèn)題

容器化方案用各種預(yù)創(chuàng)建 webview 的方式換取了打開(kāi)速度,app 內(nèi)存占用上會(huì)比未使用容器化方案要大非常多,webview 的釋放時(shí)機(jī)、預(yù)加載數(shù)據(jù)的策略優(yōu)化,及從客戶端到 web 端,如何更好的做內(nèi)存管理是接下來(lái)需要進(jìn)一步優(yōu)化的點(diǎn)。

總結(jié)

到此這篇關(guān)于HTML5頁(yè)面無(wú)縫閃開(kāi)方案的文章就介紹到這了,更多相關(guān)HTML5頁(yè)面無(wú)縫閃開(kāi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!

相關(guān)文章

  • HTML5中的Microdata與歷史記錄管理詳解

    Microdata作為HTML5新增的一個(gè)特性,它允許開(kāi)發(fā)者在HTML文檔中添加更多的語(yǔ)義信息,以便于搜索引擎和瀏覽器更好地理解頁(yè)面內(nèi)容,本文將探討HTML5中Microdata的使用方法以及
    2025-04-21
  • HTML5表格語(yǔ)法格式詳解

    在HTML語(yǔ)法中,表格主要通過(guò)< table >、< tr >和< td >3個(gè)標(biāo)簽構(gòu)成,本文通過(guò)實(shí)例代碼講解HTML5表格語(yǔ)法格式,感興趣的朋友一起看看吧
    2025-04-21
  • html5的響應(yīng)式布局的方法示例詳解

    這篇文章主要介紹了HTML5中使用媒體查詢和Flexbox進(jìn)行響應(yīng)式布局的方法,簡(jiǎn)要介紹了CSS Grid布局的基礎(chǔ)知識(shí)和如何實(shí)現(xiàn)自動(dòng)換行的網(wǎng)格布局,感興趣的朋友一起看看吧
    2025-04-21
  • 基于Canvas的Html5多時(shí)區(qū)動(dòng)態(tài)時(shí)鐘實(shí)戰(zhàn)代碼

    本文介紹了如何使用Canvas在HTML5上實(shí)現(xiàn)一個(gè)多時(shí)區(qū)動(dòng)態(tài)時(shí)鐘的web展示,通過(guò)Canvas的API,可以繪制出6個(gè)不同城市的時(shí)鐘,并且這些時(shí)鐘可以動(dòng)態(tài)轉(zhuǎn)動(dòng),每個(gè)時(shí)鐘上都會(huì)標(biāo)注出對(duì)應(yīng)的
    2025-03-11
  • HTML5 data-*自定義數(shù)據(jù)屬性的示例代碼

    HTML5的自定義數(shù)據(jù)屬性(data-*)提供了一種標(biāo)準(zhǔn)化的方法在HTML元素上存儲(chǔ)額外信息,可以通過(guò)JavaScript訪問(wèn)、修改和在CSS中使用,文章還介紹了高級(jí)用法,如存儲(chǔ)JSON數(shù)據(jù)、事
    2025-03-11
  • HTML5中下拉框<select>標(biāo)簽的屬性和樣式詳解

    在HTML5中,下拉框(<select>標(biāo)簽)作為表單的重要組成部分,為用戶提供了一個(gè)從預(yù)定義選項(xiàng)中選擇值的方式,本文將深入探討<select>標(biāo)簽的屬性、樣式,并重點(diǎn)介
    2025-02-27
  • HTML5 Input 日期選擇器詳解

    本文介紹了HTML5InputDatePicker對(duì)象表示HTML``元素,是HTML5中的新對(duì)象,介紹了日期、周、月份、時(shí)間、日期+時(shí)間、本地日期時(shí)間等不同類(lèi)型的日期選擇器,感興趣的朋友一起看
    2025-02-17
  • HTML5超鏈接和圖片基礎(chǔ)用法詳解

    本文介紹了HTML5中的超鏈接、相對(duì)路徑和圖片的使用方法,超鏈接可以創(chuàng)建指向另一個(gè)文檔或頁(yè)面內(nèi)部書(shū)簽的鏈接,相對(duì)路徑用于在同一服務(wù)器內(nèi)部跳轉(zhuǎn)頁(yè)面,圖片標(biāo)簽用于引入外部圖
    2025-02-17
  • HTML5超鏈接的創(chuàng)建方法

    本文介紹了HTML5超鏈接的創(chuàng)建方法,包括基本語(yǔ)法、創(chuàng)建圖像超鏈接的邊框去除方法以及錨點(diǎn)鏈接的使用,還討論了超鏈接的四種不同狀態(tài)(link、visited、hover、active)的CSS樣
    2025-02-17
  • HTML5使用details標(biāo)簽:展開(kāi)/收縮信息

    最近看一些技術(shù)網(wǎng)站發(fā)現(xiàn)了details 標(biāo)簽的妙用,這個(gè)不用js即可實(shí)現(xiàn)展開(kāi)/收縮信息,很方便用來(lái)讓用戶先才答案,然后下面點(diǎn)擊再給出答案的效果,這里就為大家簡(jiǎn)單介紹一下,
    2024-11-03

最新評(píng)論