從快取角度入手實現聊天室軟體原始碼的前端效能優化

雲豹科技程式設計師發表於2021-10-12

在我們考慮提高聊天室軟體原始碼頁面渲染速度之前先來思考一個問題,一個頁面的速度由什麼決定?顯而易見,這裡主要包含兩方面的影響因素。

1、資源傳輸時間(tcp連結時間和響應時間)
2、dom渲染時間

這兩方面的耗時可以通過瀏覽器環境下通過window的內建物件window.performance拿到相關資料並計算得到

const { timing } = window.performance// 計算資源傳輸耗時const tcpTimes = (timing.connectEnd - timing.connectStart)/1000// 計算dom渲染耗時const domTimes = (timing.domComplete - timing.domLoading)/1000

前端常見的優化方式

所以進行聊天室軟體原始碼前端優化的方式,通常是針對圍繞兩個方面進行優化,即儘可能的減少資源傳輸時間和dom渲染時間。

以下是前端常見的三種優化方式:

1、伺服器優化
2、減少傳輸體積-壓縮和切片技術
3、合理利用快取

展開來講每一種優化方式都能對應跟多具體的行為,對於聊天室軟體原始碼伺服器優化,vue和react生態體系下都給出了較為成熟的解決方案。比如Vue提出的Nuxt.js和React提出的Next.js。

對於第二種方式,聊天室軟體原始碼可以通過減少傳輸體積來達到優化的目的可以採用一下幾種方法:

  • 資源壓縮(包括圖片、字型庫以及js指令碼)
  • Tree shaking技術:剔除無用程式碼
  • 程式碼分離以及提取公共程式碼
  • 懶載入
  • 使用webp格式圖片
  • 在生產環境關閉source map

對於第三種方式,聊天室軟體原始碼可以通過合理利用快取的方式來達到效能優化的目的,這是本文側重討論的重點。

快取方式有哪些

1、cookies-快取量,不安全
2、全域性狀態快取-不持久, 佔用記憶體
3、本地快取-locaStorage,sessionStroage,持久化

對於聊天室軟體原始碼本地快取,我們需要知道locaStorage,sessionStroage有哪些區別:

  • locaStorage,除非手動刪除,不然會一直存在,
  • sessionStroage,基於會話級別的快取策略,頁面會話關閉,則清除。

做一個快取架構

這裡我們基於聊天室軟體原始碼請求傳送實現一個快取架構。在運用快取進行效能優化時需要考慮的問題有:

  • 快取的量引起的壓力,儲存壓力。
  • 快取的更新問題-如何在資料更新後保持最新資料。

基於這兩點的考慮,在對資料進行快取的時候,資料的變動越少越好。

解決跨域

1、webpack 代理轉發:做了一個node中間層——只對開發環境有效
2、nginx代理或者手動做node中間層–成本太大
3、jsonp,適合靜態頁面和jquery–不適合vue
4、聊天室軟體原始碼後端介面配置跨域資源共享(CORS)–簡單高效

快取思路:

第一次載入後,後續無需請求
熱門商品放入localStroage,非熱門的放到狀態快取裡

// 快取物件的建立應該使用單例模式——全域性只能有一個快取物件。if(!window.mycache){
    window.mycache = function(){
        window.cache = {};
        window.cachArr = [];
        return function(){
            get:function(api){
                return new Promise((resolve, reject) => {
                    if(cache[api]){
                        resolve(cache[api])
                    }else{
                        if(localStroage.getItem(api)){
                            resolve(JSON.parse(localStroage.getItem(api)));
                        }else {
                            this.set(api).then(res=>{
                                var name = '';
                                if(res.data.ishot){
                                    if(cacheArr[1].length>4){
                                        name=cacheArr[1].shift();
                                        localStroage.removeItem(name)
                                    }
                                    localStroage.setItem(api, Json.stringify(res));
                                    cacheArr[1].push(api)
                                }else {
                                    if(cacheArr[0].length>3){
                                        name = cahceArr[0].shift();
                                        delete cache[name];
                                    }
                                    cache[api] = res;
                                    cacheArr[0].push(api);   
                                }
                                resolve(res);
                            })
                        }
                    }
                })
            },
            set:function(api){
                return axios.get(api);
            },
            remove:function(api){
                delete cache(api);
            }
        }
    }}

這段程式碼中設計到大量的條件判斷語句。總結起來快取入口可以分為三類:

1、快取
2、localStroage
3、傳送請求,處理快取邏輯

我們可以利用享元模式優化這一流程,享元模式是⼀種經典的結構型解決⽅案,⽤於優化重複、緩慢及資料共享效率較低的程式碼。它旨在通過與相關的物件共享盡可能多的資料來減少應⽤程式中記憶體的使⽤。

if(!window.mycache){
    window.mycache = function(){
        window.cache = {};
        window.cacheArr = [];
        return {
            get:function ( api ) {
                var state = 0;
                var stateHandler = [
                    function(resolve,reject) {
                        resolve(cache[api]);
                    },
                    function(resolve,reject) {
                        resolve(JSON.parse(localStorage.getItem(api)));
                    },
                    function(resolve,reject) {
                        this.set(api).then((res) => {
                            var type = 0;
                            var name = cacheArr[type].shift();
                            if(res.data.ishot){
                                type == 1;
                                name = cacheArr[type].shift();
                                if(cacheArr[1].length>4){
                                    localStorage.removeItem(name);
                                }
                                localStorage.setItem(api,JSON.stringify(res));
                            } else {
                                if(cacheArr[0].length>3){
                                    delete cache[name];
                                }
                                cache[api] = res;
                            }
                            cacheArr[type].push(api);
                            resolve(res);
                        })
                    }
                ]
                return new Promise((resolve,reject)=>{
                    if(localStorage.getItem(api)){
                        state = 1;
                    }
                    if(!cache[api] && !localStorage.getItem(api)){
                        state = 2;
                    }
                    stateHandler[state].call(this, resolve, reject);
                })
                
            },
            set:function(api){
                return axios.get(api);
            },
            remove:function(api){
                delete cache(api);
            }
        }
    }}

基於此,我們已經完成了一個快取架構的實現,現在可以直接在聊天室軟體原始碼中引入並使用這個快取架構。
新建.vue檔案

<template>...</template><script>export default {
    date() {
        return {
            goodInfo: {}
        }
    },
    mounted: function(){
        mycahce.get('/api/'+this.$route.params.goodApi).then(res=>{
            this.goodsInfo = res.data        })
    }}</script>

現在執行這段程式碼時候會進入到快取架構裡,先判斷localStroage下或者全域性狀態快取cache下有沒有對應api的值,如果有則直接取出,如果沒有則傳送axios請求,並快取對應的資料內容。

在上面的討論中我們注意到了使用快取提高聊天室軟體原始碼效能的同時需要考慮到快取的量引起的儲存壓力,在程式碼裡我們設定了最大快取的量,超過這個量時需要將舊資料刪除,存入新資料,這樣就能控制最大能快取的資料的量。

關於第二點考慮,聊天室軟體原始碼快取的更新問題,如何保證快取與實際資源一致的同時,提高快取命中率。如果時靜態資源快取的話,最好的方式時通過hash值來達到這個目的。但是基於本文提高的針對api請求介面快取暫時沒有很好的解決方案,即便如此,仍然可以通過以下幾種方式來達到快取更新這一目的:

1、聊天室軟體原始碼快取的介面變動的越少越少,可以設定快取時限以及設定觸發刪除的動作:比如退出登陸,手動觸發快取刪除。這種方式的成本較小,同時也適用與很多前端應用場景,如選單資訊以及個人資訊介面等資料可以使用這種快取策略。
2、websocket, 成本比較大,需要後段啟動一個websocket服務,能夠達到較即時的資料更新。

var ws = new Websocket();ws.onmessage=(data)=> {
    if(data.api){
        mycache.remove(api);
    }}

3、小成本請求:進入聊天室軟體原始碼時,先發一個小請求,響應只會給你回傳改變的介面。關鍵的設計在於傳輸的資料量定小,介面需要傳入當前抓取資料的時間節點。介面拿到這個時間節點後,對比當前的資料是否更新,如果更新的話返回更新了資料的api。

本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2795570/,如需轉載,請註明出處,否則將追究法律責任。

相關文章