名站技術(shù)分析 — facebook奇特的頁面加載技術(shù)

沒事使用代理上了下facebook,注冊進入個人首頁后,習慣性的查看源代碼,發(fā)現(xiàn)了1個很有意思的現(xiàn)象,首頁內(nèi)容不少,但源代碼中HTML的代碼卻很少,但去多出了很多段的javascript代碼,這些js代碼都是用于動態(tài)生成html的,facebook為什么需要這樣做了?出于職業(yè)習慣,研究研究:


一、html代碼。

???先看看首頁查看的源代碼,因為源代碼比較大,所以把圖片壓縮了下,可能看不太清楚,只需要注意圖中紅色是html代碼,其余黑壓壓一片的就全部是JS代碼:



二、JS代碼

???看到黑壓壓的JS代碼是不是被嚇一跳,下面就截取一段JS來分析(其余段的JS都是類似的),facebook源代碼中充斥了類似于下面的JS代碼:


<script>

big_pipe.onPageletArrive({

????"id":"pagelet_welcome_box","phase":1,"is_last":false,"append":false,"bootloadable":[],

????"css":["lDRwi","eon+N"],

????"js":["F+B8D","IdQlc"],

????"resource_map":[],"requires":[],"provides":[],

????"onload":["window.__UIControllerRegistry[\"c4c13a3ed2dd1e0e349b72\"] = new UIPagelet(\"c4c13a3ed2dd1e0e349b72\", \"\\\/pagelet\\\/generic.php\\\/WelcomeBoxPagelet\\\/\", {}, {});; ;"],

????"onafterload":[],"onpagecache":[],"onafterpagecache":[],"refresh_pagelets":[],"invalidate_cache":[],

????"content":{

????????"pagelet_welcome_box":"<div id=\"c4c13a3ed2dd1e0e349b72\"><div class=\"UIImageBlock clearfix fbxWelcomeBox\"> ...這里省略N多HTML"

????????},

????"page_cache":true

});

</script>


讓我們再看看big_pipe.onPageletArrive函數(shù)到底做了什么了?我們只關(guān)注參數(shù)中的id,js,css,content4個參數(shù),可以看出js和css都是進行過編碼,下面是解碼后我們關(guān)注的代碼:

<script>

big_pipe.onPageletArrive({

????"id":"pagelet_welcome_box",

????"css":{

????????name: "css/c5mv8gd5gwoc4kk0.pkg.css"

????????permanent: true

????????src: "http://static.ak.fbcdn.net/rsrc.php/zBP3B/hash/abee68r4.css"

????????type: "css"

????},

????"js":{

????????name: "js/19khsprwvtvokwow.pkg.js"

????????permanent: false

????????src: "http://static.ak.fbcdn.net/rsrc.php/zAVXU/hash/e8mwcqsi.js"

????????type: "js"

????},

????"content":{

????????"pagelet_welcome_box":"<div id=\"c4c13a3ed2dd1e0e349b72\"><div class=\"UIImageBlock clearfix fbxWelcomeBox\"> ...這里省略N多HTML"

????????}

});

</script>

看到還原后的JS,你應(yīng)該猜出onPageletArrive函數(shù)是干嘛的吧,其實onPageletArrive最主要實現(xiàn)就是把"content"中的html內(nèi)容插入到對應(yīng)id(上面的"pagelet_welcome_box")的html元素中,并下載對應(yīng)的css和JS。


三、chunk、flush

????看到上面的分析后,大家一定奇怪,facebook為什么要生成那么多段JS,再用js去動態(tài)插入html代碼,這不是脫了褲子放屁,多此一舉嗎?還不如直接生成html代碼了。facebook當然不會那么笨了,讓我們先監(jiān)控下facebook的http請求,監(jiān)控圖如下:

????注意上圖中紅色部分,原來facebook使用了chunk對頁面進行分塊輸出。這就比較容易理解了,facebook首頁的js代碼段不是1次就全部輸出的,而是一段一段進行輸出的。

????什么是chunk和如何使用chunk,請參考我的另1篇博文:flush讓頁面分塊,逐步呈現(xiàn)


總結(jié)

???facebook使用chunk技術(shù)讓頁面分塊輸出成很多JS段,這樣做的好處就是服務(wù)器和客戶端可以并行進行處理,不用等服務(wù)器全部處理完畢,客戶端才進行處理。

???舉個博客園首頁的列子,博客園首頁分為下面幾塊("推薦博客排行","首頁隨筆列表","最新新聞"...),

???我們一般對該http請求處理如下:

?????1. 瀏覽器發(fā)送http請求

?????2. 服務(wù)器處理請求(從緩存讀取前50個推薦博客,從數(shù)據(jù)庫讀取"首頁隨筆列表",從數(shù)據(jù)庫讀取"最新新聞"),生成首頁的html代碼。

?????3. 服務(wù)器發(fā)送html代碼給客戶端

?????4、瀏覽器接收到響應(yīng),處理html(下載css,js,image,執(zhí)行js等等)

???可以看出傳統(tǒng)的http請求4個過程中,每個過程都必須等待前1個過程完成后才能執(zhí)行,這樣就存在很大的資源浪費。


???facebook的對該http請求的處理如下:

?????1. 瀏覽器發(fā)送http請求

?????2. 服務(wù)器處理請求(從緩存讀取前50個推薦博客,生成"推薦博客"的js代碼段,flush輸出該代碼段,

服務(wù)器繼續(xù)讀取"首頁隨筆列表",并生成輸入js代碼段。

服務(wù)器繼續(xù)讀取"最新新聞",并生成輸入js代碼段。

?????3. 瀏覽器接收到j(luò)s代碼段,下載該代碼段所需的js和css。插入html代碼。

???在這個處理流程中,最大的特點就是2,3是并行進行處理的,服務(wù)器處理完一部分數(shù)據(jù)就把已經(jīng)處理好的數(shù)據(jù)交給瀏覽器進行呈現(xiàn)處理,自己再繼續(xù)處理其他的數(shù)據(jù)。


PS:文章看完了,有些同學可能會想,為什么不像博客園一樣,前臺全部用ajax來異步讀取"推薦博客" ,“最新新聞”的數(shù)據(jù)了,這樣做就不會出現(xiàn)因為要處理太多數(shù)據(jù)而讓客戶端等待太久的問題了。我覺得對于facebook這種并發(fā)量巨大的網(wǎng)站,使用這種方法無疑會產(chǎn)生太多的請求,比如facebook首頁用了14個chunk,如果使用ajax,則需要多14個request請求,這將增加不少服務(wù)器的壓力吧。????

文末也給大家,分享主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK技術(shù),面試技巧方面的資料技術(shù)討論。

感興趣的朋友戳這里可以加群:812855908

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容