京東通天塔頁面(京東通天塔使用方法及作用解析)

通天塔是京東內部的一個快速搭建活動頁面的平臺,用戶可以通過在可視化平臺上選擇需要的模板及配置對應數據,來生成對應的原生、H5及PC活動頁面。模板樣式豐富,操作靈活,在京東被大量使用,用戶流量也呈現出了非常迅猛的增長。但隨著項目的迭代,功能越來越復雜,模板越來越多,前端和Node中間層性能問題也逐漸暴露出來,其中,前端首屏加載時間TP75性能要大于2秒,而Node中間層單核QPS相較其他應用也較低。為了提升用戶體驗,同時提高系統的吞吐率,在2019年下半年我們通過對現有通天塔H5項目進行一次全盤分析,做了一次全方位的性能優化。 綜合性能提升超過30% 通天塔H5是以React SSR為基礎進行架構的,首屏頁面在Node中間層進行數據請求及渲染,分頁和其他異步請求在客戶端請求網關接口并渲染,靜態資源托管在CDN,如圖1所示。
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖1:通天塔H5請求流程 基于以上架構,經過2019年下半年的優化,通天塔H5前端首屏加載性能和Node中間層渲染性能都得到了極大提升。

1

首屏加載性能 首屏加載耗時,TP75從原來的2.47秒減小到了1.58秒,性能提升約36.03%。圖2所示為優化前后以周為維度的首屏TP75加載時長。
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖2:首屏TP75加載時間 此處首屏加載時長,指用戶打開頁面到首屏第一張圖片請求完成所經歷的時間。橫坐標代表第幾周,01代表今年第一周(2020/01/06 ~ 2020/01/12),52代表去年最后一周(2019/12/23 ~ 2019/12/29)。

2

服務器性能 通過對服務器進行壓測,在相同QPS維度下,CPU從原來的29.52%降低至20.5%,CPU使用率相比之前降低了30.5%
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖3:同QPS下CPU利用率 線上性能分析 在進行優化前,需要先采集當前線上數據,了解服務目前的性能情況,我們主要通過以下方式對項目的性能進行分析及監控。

1

Performance API

Performance API是ECMAScript5才引入的,精度可達到1毫秒的千分之一,目前主流瀏覽器基本都已經支持performance對象。通過performance.timing對象,可以拿到瀏覽器處理網頁各個階段的耗時。通過performance.getEntries方法,可以獲取js, css, 圖片及ajax在內的所有請求的耗時信息。 我們基于Performance API,封裝了一個前端測速模塊,該模塊在頁面加載完成后將所需性能數據上報至服務器,之后可以在可視化平臺上進行數據的展示及分析。

2

Chrome Devtools

Chrome Devtools是前端調試及性能分析常用的工具,通過該工具,可以查看頁面資源加載情況,所加載CSS、JS及圖片的大小,還可以通過Performance面板,查看頁面渲染繪制和Script執行情況。

3

v8-profiler

通天塔H5是基于React SSR架構的,頁面首屏在Node中間層請求數據并渲染,所以除純前端的監控及分析,還需對Node層進行性能分析及優化。在Node層性能分析中,我們主要通過v8-profiler模塊進行性能分析。 在本地或測試環境下新增兩個路由:
const profiler = require('v8-profiler');


router.get('/profiler/start', (req, res) => {
   //Start Profiling
   profiler.startProfiling('CPU profile');
   res.end('profile start');
});


router.get('profiler/end', (req, res) => {
   const profile = profiler.stopProfiling()
   profile.export()
     .pipe(res)
     .on('finish', () => {
         profile.delete();
         res.end();
     });
});
通過ab壓測工具,對服務器發起請求

ab -c 10 -n 1000 http://localhost:7001/mall/active/xxx/index.html

在壓測過程中,可以通過 http://localhost:7001/profiler/start開始性能統計,通過http://localhost:7001/profiler/end結束性能統計,并將結果保存為 ***.cpuprofile文件,通過Chrome Devtools中的JavaScript Profiler工具進行分析。
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖4:Node服務端代碼執行情況 常規優化+業務特性優化 我們主要從兩個方面進行性能優化,一方面是基于較為通用的前端常規性能優化方案,另一方面基于通天塔業務特點進行的偏業務方面的優化。

1

前端常規優化 在優化之初,根據《高性能網站建設指南》提及的常規優化方案,我們檢查了項目中需要改進或深度優化的地方,主要涉及以下方面:
  • 盡可能的減少HTTP的請求數,減小HTTP請求大小
  • 將靜態資源放在CDN,最大化利用CDN緩存能力
  • 減少CSS和JS請求個數,減小CSS和JS包大小
  • 啟用gzip壓縮
1)減少圖片請求大小 在通天塔頁面中,圖片請求一般占比最大,在前期開發過程中,針對圖片請求我們已做過懶加載優化,圖片請求數很難更進一步減少,但針對圖片大小,我們可以進行優化。
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖5:圖片展示尺寸及實際尺寸 如圖5,在頁面中圖片實際所展示坑位大小為115×115,即使在3倍屏上,所需圖片尺寸也只是345×345,但實際請求中,圖片的原始尺寸卻是800×800,這對用戶流量是一種浪費,同時也增加了圖片加載耗時,而通天塔活動頁中,這種類似的圖片還有很多,而同時,京東圖片服務器正好支持圖片的裁剪,原來一張800×800的圖片,可以按比例縮小到所需的高度,如一張800×800的原圖 https://m.360buyimg.com/babel/jfs/t1/85209/24/15512/218570/5e7179d8E957c16c1/5fbcc42fad37fe94.jpg!q70.dpg ,通過修改URL,可以改成下發230×230尺寸的圖?http://www.cymth.com/wp-content/uploads/2023/02/5fbcc42fad37fe94.jpg!q70.dpg 鑒于此,針對圖片大小,可以做按實際展示大小請求對應尺寸的圖片的優化,以減小HTTP的大小。
const isJfsRegex = /360buyimg\.com\/.*\/((s([\d^_]+)x([\d^_]+)_)?jfs)/i;
export function resizeImg(url, rect) {
    const dpr = window.devicePixelRatio;
    if (!isJpegRegExp.test(url)) {
        return url;
    }
    const result = url.match(isJfsRegex);
    if (!result) {
        return url;
    }
    if (result[3] && result[4]) {
        if (!rect || (!rect.width && !rect.height)) {
            return url;
        }
        if (rect.width && !rect.height) {
            rect.height = rect.width / result[3] * result[4];
        }
        if (rect.height && !rect.width) {
            rect.width = rect.height / result[4] * result[3];
        }
        const t = 's' + Math.ceil(rect.width* dpr)  + 'x' + Math.ceil(rect.height* dpr) + '_jfs';
        return url.replace(result[1], t);
    } else {
        if (rect && rect.width && rect.height) {
            return url.replace('/jfs/', `/s${Math.ceil(rect.width * dpr)}x${Math.ceil(rect.height * dpr)}_jfs/`);
        }
    }
    return url;
}
2)最大化利用CDN緩存 在做性能優化前,通天塔靜態資源的打包,是開發者在上線前,在自己電腦上進行的,且文件名會依據文件內容重新生成,格式為[filename].[contenthash:8].js。 按這種方式在個人電腦上打包,即使有package-lock.json鎖定包版本,但由于個人電腦操作系統及使用的npm包管理工具的不同(有的包管理工具不讀package-lock.json),node_module下的文件可能會不一致,導致文件的contenthash不同。 針對這個問題,我們基于Jenkins搭建了一個前端CI打包系統,后繼所有上線前的前端靜態資源打包,都遷移到CI上進行,通過這種方式,確保了文件名的一致性,以最大程度的利用CDN緩存。 3)調整webpack打包策略,按需加載CSS和JS 在性能優化前,通天塔的CSS和JS資源是按以下策略打包的:
  • vendor.[contenthash:8].js: 包含node_module下的代碼
  • common.[contenthash:8].js: 包含非node_modules下的代碼
  • [channel].[contenthash:8].js: 通天塔有很多渠道,每個渠道的專屬代碼打包到這個JS中
  • template.[contenthash:8].css: 包含所有渠道通用CSS
  • [channel].[contenthash:8].css: 包含渠道專有CSS
按這種方式來進行打包,有以下兩個問題, 1. 每個活動會加載所有模板對應的CSS和JS,造成不必要的加載。 2. 所有的系統模板代碼都打包到common包,導致common包非常龐大,而其中有任何一個模板代碼有改動,都會影響到common包的文件名,從而導致CDN緩存失效,客戶端必須重新請求CDN。 針對兩個問題,我們改進了打包策略,最終方案改為:
  • vendor.[contenthash:8].js: 包含node_module下的JS文件
  • lowUsedTemp.[contenthash:8].js: 包含使用頻率低的系統模板代碼,頁面會按照活動是否使用到低頻模板按需請求
  • mute.[contenthash:8].js: 包含剔除低頻使用模板后,較為穩定,很少改動的系統模板
  • template.[contenthash:8].js: 包含剩余非node_modules下的代碼
  • [channel].[contenthash:8].js: 包含渠道專屬代碼
  • lowUsedTemp.[contenthash:8].css: 包含使用頻率低的系統模板代碼的CSS,頁面會按照活動是否使用到低頻模板按需請求
  • template.[contenthash:8].css: 包含所有渠道通用CSS
  • [channel].[contenthash:8].css: 包含渠道專有CSS
按照這種方式打包,只有使用到低頻使用模板的活動,才會加載lowUsedTemp.[contenthash:8].css和lowUsedTemp.[contenthash:8].js,其中按需加載的CSS占總CSS大小的25%,按需加載的JS占總大小的17%。而單獨打包出的mute.[contenthash:8].js這個JS資源,由于里面包含的模板很少被改動,所以在打包上線時,其文件名也很少會變,這就可以利用CDN緩存,不會每次上線后,用戶都重新請求這部分代碼。

2

業務優化 在常規的前端性能優化達到瓶頸后,我們開始嘗試基于業務進行性能優化。 1)首屏精準化優化 通天塔頁面是運營在可視化配置平臺中,通過選擇模板,配置數據來動態生成的,而其中類似商品樓層這種素材樓層,配置的素材數量也由運營自己決定,少的可能只有幾個,多的幾十上百個,這便導致通天塔首屏頁面有以下特點 1. 頁面靈活多變,頁面結構難以預測。 2. 在請求首屏樓層數據時,服務端難以計算需要下發幾個樓層剛好滿首屏,故按照素材樓層數來進行分頁,如果首頁素材樓層配置的素材較多,節點數會非常龐大。 由于以上兩個特點,導致很多活動頁首屏的內容,遠大于客戶端首屏實際所需展示的長度,這既加大了首屏的渲染耗時,同時也浪費了Node服務器的CPU資源(渲染了不必要的樓層)。 另外,在通過v8-profiler測試Node服務器性能時,我們發現Node服務器端開銷最大的地方有三處
  • 通過JSON.parse解析后端下發的活動數據
  • React.renderToString 進行首屏渲染
  • JSON.stringify將首屏數據序列化后跟隨HTML下發給客戶端
綜合考慮各種優化方式,最終決定采用在Node層計算每個樓層高度,按首屏高度渲染樓層數的方案。
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖6:首屏精準渲染流程 1. 用戶向Node中間層發起請求的時候,客戶端會向cookie中埋入設備寬高信息。 2. Node中間層從cookie中獲取設備寬高信息,若獲取失敗,則使用默認值。 3. 循環計算每個樓層的高度,如果樓層累計高度超過2倍設備高度,丟棄后面的樓層數據,并重置分頁信息。 4. Node中間層根據計算過后的數據,渲染首頁樓層,并將數據序列化后隨HTNL下發到客戶端。 5. 前端檢測頁面是否滿兩屏,若沒滿兩屏,立即請求下一頁數據。 在樓層維度的分頁優化完畢后,還可以精益求精,針對素材樓層進行樓層內素材的優化,如果首頁最后一個素材樓層中有素材超過兩屏,還可以將超過兩屏的素材降級到客戶端來渲染。 上面結論中所提到的服務端性能優化,主要就是通過首屏精準化優化實現的。 2)首屏圖片預加載 由于通天塔頁面的靈活性,開發者并不知道哪些樓層元素會出現在首屏,所以頁面中所有的圖片資源,統一設置為懶加載模式。而基于通天塔H5 SSR的架構,首頁在服務端渲染完成后下發給前端,前端只有在加載完JS后判斷圖片是否在首屏,在首屏的才開始加載圖片,這就會造成圖片必須要在JS加載執行完成后才進行加載,圖片坑位的白屏時間較長。 基于以上圖片加載滯后的問題,前期我們做了第一個優化是,在第一屏樓層之后插入一段內聯JS,獲取頁面已加載的圖片元素,如果在首屏則先將首屏圖片的data-src置為src進行加載,但發現以下問題,下面是一個測試Demo。
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <img data-src="/img-size.png" id="test" />
  <h1>我是測試代碼</h1>
  <script>
    (function() {
        var start = Date.now();
        console.log('start', start)
        var img = document.getElementById('test');
        img.onload = function() {
console.log('end', Date.now(), Date.now() - start);     // end - start > 2000ms
        }
        img.src = img.getAttribute('data-src');
    })();
</script>
  <h1>我是測試代碼22222</h1>
  <img src="/performance-cpu.jpg" />
  <script src="/test.js"></script>
</body>
</html>
其中test.js中很簡單
console.log('start');
var start = Date.now();
for(;;) {
    if (Date.now() - start > 2000) {
        break;
    }
}
console.log('end');
京東通天塔頁面(京東通天塔使用方法及作用解析)

圖7:Demo頁加載執行 從圖中可以看出這個圖片依然在JS執行完畢后才加載。但我們發現performance-cpu.jpg這張圖片,由于瀏覽器對圖片資源預加載的緣故,沒被JS阻塞,基于瀏覽器對圖片的預加載,及上面做的首屏精準化渲染,我們又進行了一個優化:在計算首屏樓層高度時,給處于首屏的部分圖片元素打標,根據這個標識在render渲染時,對打標的圖片不進行懶加載處理,而直接用src,通過這個優化,圖片將不被JS阻塞,提前了首屏圖片開始加載的時機,減少了圖片坑位的白屏時間。 3)交互優化 在通天塔活動中,有許多包含多Tab的模板,如商品類模板,在之前的開發中,每次切換Tab我們都是銷毀之前Tab下的內容,重新渲染新Tab下的內容,這樣在重新切換回去的時候,還是需要重新渲染,造成頁面的卡頓。基于此,我們將Tab渲染改成了增量渲染,這樣在切回上一個Tab的時候,白屏及渲染時間會大大減少。 優化是持續性工作 在通天塔H5前端性能優化的過程中,很大一部分是站在巨人的肩膀上進行的,但光這些遠遠不夠,當純技術優化到一定程度后,更需要根據自己的業務特點,從業務層面進行優化,這個優化的效果可能更好。 通天塔前端的優化在此告一段落,但優化之路還遠未結束,后續我們還會更進一步,基于自身的業務以及一些新技術,繼續深入優化,同時也希望本文能給前端及后臺開發人員帶來一些新的想法。

聲明:本文由網站用戶香香發表,超夢電商平臺僅提供信息存儲服務,版權歸原作者所有。若發現本站文章存在版權問題,如發現文章、圖片等侵權行為,請聯系我們刪除。

(0)
上一篇 2023年3月17日 12:10:56
下一篇 2023年3月17日 12:20:59

相關推薦

發表回復

您的電子郵箱地址不會被公開。 必填項已用*標注

主站蜘蛛池模板: 精品欧美一区二区三区在线观看 | 久久午夜无码鲁丝片午夜精品| 欧美最猛性xxxxx免费| 公交车上驯服冷艳麻麻| 青娱乐在线免费观看视频| 国产男女爽爽爽爽爽免费视频| 91av免费观看| 天堂网2018| 一区二区三区无码高清视频| 抽搐一进一出gif免费视频| 久久人人妻人人做人人爽| 曰批全过程免费视频观看免费软件| 亚洲国产高清美女在线观看| 波多野结衣一区二区免费视频| 免费一级肉体全黄毛片| 精品无码久久久久久久久| 四虎影视永久地址www成人 | 国产欧美日韩一区二区三区| 222www免费视频| 国产老妇伦国产熟女老妇视频| ass日本熟妇大全pic| 成人区人妻精品一区二区不卡视频| 久久AV高潮AV无码AV| 日本年轻的妈妈| 久久精品久久久| 日韩精品无码人成视频手机| 亚洲av日韩综合一区在线观看| 欧美在线暴力性xxxx| 亚洲国产精品综合一区在线| 欧美美女与野兽免费看电影| 又爽又黄又无遮挡的视频在线观看 | 日本黄色影院在线观看| 久久综合久久综合九色| 日韩精品无码一区二区三区不卡 | 中日韩亚洲人成无码网站| 日本不卡在线观看免费v| 久久国产精品99精品国产| 日本高清色www网站色| 久久国产精品偷| 日本网站在线看| 久久久精品2019中文字幕之3|