過去十年,現代web站點變得更加動態和內容化,交互性也逐步加強,傳統的頁面處理的方式卻沒有保持同樣的速度發展,愈來愈不能知足用戶對極致性能的追求。javascript
先來看一下頁面傳統的交互模型:css
傳統的頁面交互模型按照必定的順序來執行的,每個過程都是不可重疊的,即每個過程不能在同一時間被執行。當服務器端獲取數據並生成頁面的時候,客戶端被閒置,等待服務器端生成數據;當客戶端接收到服務前端返回的頁面並開始下載資源,解析頁面的時候,服務器又在等待來自客戶端的下一次請求。空閒時間形成資源的浪費。html
若是客戶端可以在服務器生成頁面的時候同時可以進行資源的下載和頁面的解析,在頁面進行資源下載和解析的過程服務器端也可以繼續生成頁面,那麼總體的性能將會被提高。前端
爲了能讓一個頁面可以同時被客戶端和服務前端同時處理,首先咱們須要將一個完成的頁面劃分爲若干小塊,這些小分塊被稱爲 pagelets
。 而後經過bigpipe技術,讓頁面以pagelet
的形式在服務前端生成並 分塊
發送給客戶端。
BigPipe 讓頁面的生成步驟拆成成一下幾個步驟:java
一、服務前端接收來自客戶端的HTTP請求
二、從存儲層獲取數據。
三、生成HTML,響應給客戶端。
四、瀏覽器解析內容,開始下載CSS,瀏覽器生成DOM Tree,生成CSS Rule Tree,構造 Rendering Tree, 繪製和顯示元素。
五、下載和執行JavaScript。web
前面三個步驟在服務前端完成,後面三個在瀏覽器端執行。每個pagelet都要執行以上的所有步驟,可是bigpipe 可讓這些pagelet並行的去完成這一些步驟。shell
首先客戶端給瀏覽器發送一個HTTP請求給服務器。服務器首先會生成一段不閉合的HTML片斷,包含了<head>和不閉合的<body>標籤,在head裏面包含了處理後續接收到的 pagelet
的 BigPipe
庫,在這裏是bigpipe.js
,而後發送給客戶端。數據庫
javascript<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="HandheldFriendly" content="true"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <title>BigPipe Test</title> <link rel="stylesheet" href="bigpipe.styl"> <script src="bigpipe.js"></script> </head> <body>
這個時候服務器就繼續去生成頁面的 pagelets
。而客戶端已經開始下載CSS和其它資源了。當服務器端生成好一個pagelet 的時候,會當即 flush
到客戶端,pagelet 的格式以下:瀏覽器
<script type="text/javascript"> big_pipe.onPageletArrive({id: 「pagelet_composer」, content=<HTML>, css=[..], js=[..], …}) </script>
一個 pagelet
包含了 id
、 HTML片斷
、 依賴的CSS
、JavaScript 資源
。緩存
在客戶端,當接收到一個pagelet(此時服務端還在繼續生成其它pagelet) 的時候,立刻回執行 onPageletArrive
的方法,BigPipe庫會根據返回的pagelet信息 當即開始下載CSS資源,下載完以後會在頁面顯示pagelet片斷。因爲JavaScript的下載和執行會阻塞頁面的渲染,因此,JavaScript 下載和執行的優先級會被下降,等待全部 pagelet
所有被展現完了,JavaScript資源纔會被開始下載和執行。
重複上面的步驟,直到 pagelet
所有處理完畢,這個流程就結束了,pagelet
處理的過程服務器端和客戶端一直保持 同步工做狀態
。
BigPipe 是FaceBook 在性能優化探索的過程當中結合本身的業務場景提出來的一個優化手段,並在FaceBook中取得了巨大的成就,在2009年的時候,他們使用BigPipe和其它一些優化手段,成功將網站的響應速度提升了到以前的兩倍。